From 00af1e3b4696927f9a7e6716c69c7c983ecc2431 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sat, 3 Jan 2026 15:43:55 -0600 Subject: [PATCH 001/234] chore: update .gitignore and .prettierignore to include MagicMock and additional directories for better file management --- .gitignore | 4 +++- .prettierignore | 38 ++++++++++++++++++++++++++++++-------- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 3f9b5f0..6e7f0ca 100644 --- a/.gitignore +++ b/.gitignore @@ -76,4 +76,6 @@ Thumbs.db meshchat-config/ .hypothesis -.hypothesis/ \ No newline at end of file +.hypothesis/ + +MagicMock/ \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index 048274e..5ab4ab5 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,9 +1,31 @@ -dist -node_modules -build -electron/assets -meshchatx/public -pnpm-lock.yaml -poetry.lock -*.log +# Prettier ignore file +# Dependencies +node_modules/ +pnpm-lock.yaml + +# Build output +dist/ +build/ +linux-unpacked/ +win-unpacked/ +mac-unpacked/ + +# Public assets and libraries +meshchatx/public/ +meshchatx/src/frontend/public/ +meshchatx/src/frontend/style.css + +# Other +storage/ +__pycache__/ +.venv/ +MagicMock/ +*.min.js +*.wasm +*.proto + +# Documentation and misc +misc/README.md +android/README.md +CHANGELOG.md From b544108d4b50b5daadf4aa58a2636cb0922bd0dc Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sat, 3 Jan 2026 15:44:06 -0600 Subject: [PATCH 002/234] chore: update package.json and pnpm-lock.yaml for dependency upgrades and new configurations --- package.json | 22 +- pnpm-lock.yaml | 1211 ++++++++++++++++++++++++++++++++++++------------ poetry.lock | 2 +- pyproject.toml | 7 +- 4 files changed, 929 insertions(+), 313 deletions(-) diff --git a/package.json b/package.json index c8d3f38..65ed4cd 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ }, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=22" }, "packageManager": "pnpm@10.0.0", "devDependencies": { @@ -36,7 +36,8 @@ "@vue/eslint-config-prettier": "^10.2.0", "@vue/test-utils": "^2.4.6", "electron": "^39.2.7", - "electron-builder": "^24.13.3", + "electron-builder": "^26.0.12", + "electron-builder-squirrel-windows": "^26.0.12", "eslint": "^9.39.2", "eslint-config-prettier": "^10.1.8", "eslint-plugin-prettier": "^5.5.4", @@ -48,6 +49,14 @@ "terser": "^5.44.1", "vitest": "^3.2.4" }, + "pnpm": { + "onlyBuiltDependencies": [ + "electron", + "electron-winstaller", + "esbuild", + "protobufjs" + ] + }, "build": { "appId": "com.sudoivan.reticulummeshchat", "productName": "Reticulum MeshChatX", @@ -55,6 +64,14 @@ "asarUnpack": [ "build/exe/**/*" ], + "electronFuses": { + "runAsNode": false, + "enableCookieEncryption": true, + "enableNodeOptionsEnvironmentVariable": false, + "enableNodeCliInspectArguments": false, + "enableEmbeddedAsarIntegrityValidation": true, + "onlyLoadAppFromAsar": true + }, "files": [ "electron/**/*" ], @@ -150,6 +167,7 @@ "ol": "^10.7.0", "postcss": "^8.5.6", "protobufjs": "^7.5.4", + "qrcode": "^1.5.4", "tailwindcss": "^3.4.19", "vis-data": "^7.1.10", "vis-network": "^9.1.13", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9660caa..2ef2be9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -50,6 +50,9 @@ importers: protobufjs: specifier: ^7.5.4 version: 7.5.4 + qrcode: + specifier: ^1.5.4 + version: 1.5.4 tailwindcss: specifier: ^3.4.19 version: 3.4.19 @@ -94,8 +97,11 @@ importers: specifier: ^39.2.7 version: 39.2.7 electron-builder: - specifier: ^24.13.3 - version: 24.13.3(electron-builder-squirrel-windows@24.13.3) + specifier: ^26.0.12 + version: 26.0.12(electron-builder-squirrel-windows@26.0.12) + electron-builder-squirrel-windows: + specifier: ^26.0.12 + version: 26.0.12(dmg-builder@26.0.12) eslint: specifier: ^9.39.2 version: 9.39.2(jiti@1.21.7) @@ -192,27 +198,52 @@ packages: resolution: {integrity: sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==} engines: {node: '>=0.8.0'} + '@electron/asar@3.2.18': + resolution: {integrity: sha512-2XyvMe3N3Nrs8cV39IKELRHTYUWFKrmqqSY1U+GMlc0jvqjIVnoxhNd2H4JolWQncbJi1DCvb5TNxZuI2fEjWg==} + engines: {node: '>=10.12.0'} + hasBin: true + '@electron/asar@3.4.1': resolution: {integrity: sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==} engines: {node: '>=10.12.0'} hasBin: true + '@electron/fuses@1.8.0': + resolution: {integrity: sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw==} + hasBin: true + '@electron/get@2.0.3': resolution: {integrity: sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==} engines: {node: '>=12'} - '@electron/notarize@2.2.1': - resolution: {integrity: sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==} + '@electron/node-gyp@https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2': + resolution: {tarball: https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2} + version: 10.2.0-electron.1 + engines: {node: '>=12.13.0'} + hasBin: true + + '@electron/notarize@2.5.0': + resolution: {integrity: sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==} engines: {node: '>= 10.0.0'} - '@electron/osx-sign@1.0.5': - resolution: {integrity: sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==} + '@electron/osx-sign@1.3.1': + resolution: {integrity: sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==} engines: {node: '>=12.0.0'} hasBin: true - '@electron/universal@1.5.1': - resolution: {integrity: sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==} - engines: {node: '>=8.6'} + '@electron/rebuild@3.7.0': + resolution: {integrity: sha512-VW++CNSlZwMYP7MyXEbrKjpzEwhB5kDNbzGtiPEjwYysqyTCF+YbNJ210Dj3AjWsGSV4iEEwNkmJN9yGZmVvmw==} + engines: {node: '>=12.13.0'} + hasBin: true + + '@electron/universal@2.0.1': + resolution: {integrity: sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==} + engines: {node: '>=16.4'} + + '@electron/windows-sign@1.2.2': + resolution: {integrity: sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ==} + engines: {node: '>=14.14'} + hasBin: true '@esbuild/aix-ppc64@0.25.12': resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} @@ -408,6 +439,9 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@gar/promisify@1.1.3': + resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -436,6 +470,14 @@ packages: resolution: {integrity: sha512-l6e4NZyUgv8VyXXH4DbuucFOBmxLF56C/mqh2tvApbzl2Hrhi1aTDcuv5TKdxzfHYmpO3UB0Cz04fgDT9vszfw==} engines: {node: '>= 16'} + '@isaacs/balanced-match@4.0.1': + resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} + engines: {node: 20 || >=22} + + '@isaacs/brace-expansion@5.0.0': + resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} + engines: {node: 20 || >=22} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -456,9 +498,9 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@malept/cross-spawn-promise@1.1.1': - resolution: {integrity: sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==} - engines: {node: '>= 10'} + '@malept/cross-spawn-promise@2.0.0': + resolution: {integrity: sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==} + engines: {node: '>= 12.13.0'} '@malept/flatpak-bundler@0.4.0': resolution: {integrity: sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==} @@ -479,6 +521,15 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@npmcli/fs@2.1.2': + resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + '@npmcli/move-file@2.0.1': + resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This functionality has been moved to @npmcli/fs + '@one-ini/wasm@0.1.1': resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} @@ -797,6 +848,9 @@ packages: resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==} engines: {node: '>=10.0.0'} + abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + abbrev@2.0.0: resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -819,6 +873,14 @@ packages: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} + agentkeepalive@4.6.0: + resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} + engines: {node: '>= 8.0.0'} + + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + ajv-keywords@3.5.2: resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} peerDependencies: @@ -850,27 +912,15 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} - app-builder-bin@4.0.0: - resolution: {integrity: sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==} + app-builder-bin@5.0.0-alpha.12: + resolution: {integrity: sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w==} - app-builder-lib@24.13.3: - resolution: {integrity: sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==} + app-builder-lib@26.0.12: + resolution: {integrity: sha512-+/CEPH1fVKf6HowBUs6LcAIoRcjeqgvAeoSE+cl7Y7LndyQ9ViGPYibNk7wmhMHzNgHIuIbw4nWADPO+4mjgWw==} engines: {node: '>=14.0.0'} peerDependencies: - dmg-builder: 24.13.3 - electron-builder-squirrel-windows: 24.13.3 - - archiver-utils@2.1.0: - resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==} - engines: {node: '>= 6'} - - archiver-utils@3.0.4: - resolution: {integrity: sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==} - engines: {node: '>= 10'} - - archiver@5.3.2: - resolution: {integrity: sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==} - engines: {node: '>= 10'} + dmg-builder: 26.0.12 + electron-builder-squirrel-windows: 26.0.12 arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -931,12 +981,6 @@ packages: bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - bluebird-lst@1.0.9: - resolution: {integrity: sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==} - - bluebird@3.7.2: - resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} - blueimp-canvas-to-blob@3.29.0: resolution: {integrity: sha512-0pcSSGxC0QxT+yVkivxIqW0Y4VlO2XSDPofBAqoJ1qJxgH9eiUDLv50Rixij2cDuEfx4M6DpD9UGZpRhT5Q8qg==} @@ -965,27 +1009,27 @@ packages: buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - buffer-equal@1.0.1: - resolution: {integrity: sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==} - engines: {node: '>=0.4'} - buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - builder-util-runtime@9.2.4: - resolution: {integrity: sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==} + builder-util-runtime@9.3.1: + resolution: {integrity: sha512-2/egrNDDnRaxVwK3A+cJq6UOlqOdedGA7JPqCeJjN2Zjk1/QB/6QUi3b714ScIGS7HafFXTyzJEOr5b44I3kvQ==} engines: {node: '>=12.0.0'} - builder-util@24.13.1: - resolution: {integrity: sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==} + builder-util@26.0.11: + resolution: {integrity: sha512-xNjXfsldUEe153h1DraD0XvDOpqGR0L5eKFkdReB7eFW5HqysDZFfly4rckda6y9dF39N3pkPlOblcfHKGw+uA==} cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} + cacache@16.1.3: + resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + cacheable-lookup@5.0.4: resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} engines: {node: '>=10.6.0'} @@ -1006,6 +1050,10 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + caniuse-lite@1.0.30001762: resolution: {integrity: sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw==} @@ -1017,8 +1065,8 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - check-error@2.1.1: - resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + check-error@2.1.3: + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} engines: {node: '>= 16'} chokidar@3.6.0: @@ -1036,6 +1084,18 @@ packages: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + + cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + cli-truncate@2.1.0: resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} engines: {node: '>=8'} @@ -1044,6 +1104,9 @@ packages: resolution: {integrity: sha512-sbplNecrup5oGqA3o4bo8XmvHRT6q9fvw21Z67aDbTqB9M6LF7CuYLTlLvNtOgKU6W3zst5H5zJuEh4auqA34g==} engines: {node: '>=6'} + cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -1051,6 +1114,10 @@ packages: clone-response@1.0.3: resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -1077,6 +1144,10 @@ packages: resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} engines: {node: '>= 6'} + commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + compare-version@0.1.2: resolution: {integrity: sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==} engines: {node: '>=0.10.0'} @@ -1085,10 +1156,6 @@ packages: resolution: {integrity: sha512-4m5s3Me2xxlVKG9PkZpQqHQR7bgpnN7joDMJ4yvVkVXngjoITG76IaZmzmywSeRTeTpc6N6r3H3+KyUurV8OYw==} engines: {node: '>=18'} - compress-commons@4.1.2: - resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==} - engines: {node: '>= 10'} - compressorjs@1.2.1: resolution: {integrity: sha512-+geIjeRnPhQ+LLvvA7wxBQE5ddeLU7pJ3FsKFWirDw6veY3s9iLxAQEw7lXGHnhCJvBujEQWuNnGzZcvCvdkLQ==} @@ -1098,27 +1165,18 @@ packages: config-chain@1.1.13: resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} - config-file-ts@0.2.6: - resolution: {integrity: sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==} + config-file-ts@0.2.8-rc1: + resolution: {integrity: sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==} core-util-is@1.0.2: resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} - core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - - crc-32@1.2.2: - resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} - engines: {node: '>=0.8'} - hasBin: true - - crc32-stream@4.0.3: - resolution: {integrity: sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==} - engines: {node: '>= 10'} - crc@3.8.0: resolution: {integrity: sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==} + cross-dirname@0.1.0: + resolution: {integrity: sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -1151,6 +1209,10 @@ packages: supports-color: optional: true + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + decimal.js@10.6.0: resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} @@ -1165,6 +1227,9 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + defer-to-connect@2.0.1: resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} engines: {node: '>=10'} @@ -1181,20 +1246,27 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + detect-node@2.1.0: resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} - dir-compare@3.3.0: - resolution: {integrity: sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==} + dijkstrajs@1.0.3: + resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} + + dir-compare@4.2.0: + resolution: {integrity: sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==} dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} - dmg-builder@24.13.3: - resolution: {integrity: sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==} + dmg-builder@26.0.12: + resolution: {integrity: sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==} dmg-license@1.0.11: resolution: {integrity: sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==} @@ -1205,12 +1277,13 @@ packages: dompurify@3.3.1: resolution: {integrity: sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==} - dotenv-expand@5.1.0: - resolution: {integrity: sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==} + dotenv-expand@11.0.7: + resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==} + engines: {node: '>=12'} - dotenv@9.0.2: - resolution: {integrity: sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==} - engines: {node: '>=10'} + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} @@ -1232,23 +1305,27 @@ packages: engines: {node: '>=0.10.0'} hasBin: true - electron-builder-squirrel-windows@24.13.3: - resolution: {integrity: sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==} + electron-builder-squirrel-windows@26.0.12: + resolution: {integrity: sha512-kpwXM7c/ayRUbYVErQbsZ0nQZX4aLHQrPEG9C4h9vuJCXylwFH8a7Jgi2VpKIObzCXO7LKHiCw4KdioFLFOgqA==} - electron-builder@24.13.3: - resolution: {integrity: sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg==} + electron-builder@26.0.12: + resolution: {integrity: sha512-cD1kz5g2sgPTMFHjLxfMjUK5JABq3//J4jPswi93tOPFz6btzXYtK5NrDt717NRbukCUDOrrvmYVOWERlqoiXA==} engines: {node: '>=14.0.0'} hasBin: true electron-prompt@1.7.0: resolution: {integrity: sha512-IfqJYEgcRO6NuyPROo8AtdkAiZ6N9I1lQEf4dJAkPuhV5YgOHdmLqZJf6OXumZJfzrjpzCM5jHeYOrhGdgbnEA==} - electron-publish@24.13.1: - resolution: {integrity: sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==} + electron-publish@26.0.11: + resolution: {integrity: sha512-a8QRH0rAPIWH9WyyS5LbNvW9Ark6qe63/LqDB7vu2JXYpi0Gma5Q60Dh4tmTqhOBQt0xsrzD8qE7C+D7j+B24A==} electron-to-chromium@1.5.267: resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} + electron-winstaller@5.4.0: + resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==} + engines: {node: '>=8.0.0'} + electron@39.2.7: resolution: {integrity: sha512-KU0uFS6LSTh4aOIC3miolcbizOFP7N1M46VTYVfqIgFiuA2ilfNaOHLDS9tCMvwwHRowAsvqBrh9NgMXcTOHCQ==} engines: {node: '>= 12.20.55'} @@ -1260,6 +1337,9 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + end-of-stream@1.4.5: resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} @@ -1403,6 +1483,9 @@ packages: resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} + exponential-backoff@3.1.3: + resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} + extract-zip@2.0.1: resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} engines: {node: '>= 10.17.0'} @@ -1454,6 +1537,10 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -1485,13 +1572,18 @@ packages: fraction.js@5.3.4: resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} - fs-constants@1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} + fs-extra@11.3.3: + resolution: {integrity: sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==} + engines: {node: '>=14.14'} + + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + fs-extra@8.1.0: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} engines: {node: '>=6 <7 || >=8'} @@ -1551,6 +1643,11 @@ packages: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported + glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + deprecated: Glob versions prior to v9 are no longer supported + global-agent@3.0.0: resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==} engines: {node: '>=10.0'} @@ -1628,6 +1725,9 @@ packages: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + iconv-corefoundation@1.1.7: resolution: {integrity: sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==} engines: {node: ^8.11.2 || >=10} @@ -1652,6 +1752,13 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + infer-owner@1.0.4: + resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} + inflight@1.0.6: resolution: {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. @@ -1662,6 +1769,10 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + ip-address@10.1.0: + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} + engines: {node: '>= 12'} + is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -1690,6 +1801,13 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + + is-lambda@1.0.1: + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -1697,8 +1815,9 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} isbinaryfile@4.0.10: resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} @@ -1780,10 +1899,6 @@ packages: lazy-val@1.0.5: resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==} - lazystream@1.0.1: - resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} - engines: {node: '>= 0.6.3'} - lerc@3.0.0: resolution: {integrity: sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==} @@ -1798,31 +1913,24 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} - lodash.defaults@4.2.0: - resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} - - lodash.difference@4.5.0: - resolution: {integrity: sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==} - - lodash.flatten@4.4.0: - resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} - - lodash.isplainobject@4.0.6: - resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} - lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash.union@4.6.0: - resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==} - lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + long@5.3.2: resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} @@ -1840,9 +1948,17 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + make-fetch-happen@10.2.1: + resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + matcher@3.0.0: resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} engines: {node: '>=10'} @@ -1875,6 +1991,10 @@ packages: engines: {node: '>=4.0.0'} hasBin: true + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + mimic-response@1.0.1: resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} engines: {node: '>=4'} @@ -1887,6 +2007,10 @@ packages: resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} hasBin: true + minimatch@10.1.1: + resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} + engines: {node: 20 || >=22} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -1905,6 +2029,26 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass-collect@1.0.2: + resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} + engines: {node: '>= 8'} + + minipass-fetch@2.1.2: + resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + minipass-flush@1.0.5: + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} + + minipass-pipeline@1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + + minipass-sized@1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} + minipass@3.3.6: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} engines: {node: '>=8'} @@ -1924,6 +2068,10 @@ packages: mitt@3.0.1: resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + mkdirp@1.0.4: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} engines: {node: '>=10'} @@ -1943,12 +2091,28 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + + node-abi@3.85.0: + resolution: {integrity: sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==} + engines: {node: '>=10'} + node-addon-api@1.7.2: resolution: {integrity: sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==} + node-api-version@0.2.1: + resolution: {integrity: sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==} + node-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + nopt@6.0.0: + resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true + nopt@7.2.1: resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -1986,22 +2150,46 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} + ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + p-cancelable@2.1.1: resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} engines: {node: '>=8'} + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -2048,6 +2236,10 @@ packages: resolution: {integrity: sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==} hasBin: true + pe-library@0.4.1: + resolution: {integrity: sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==} + engines: {node: '>=12', npm: '>=6'} + pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} @@ -2074,6 +2266,10 @@ packages: resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==} engines: {node: '>=10.4.0'} + pngjs@5.0.0: + resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} + engines: {node: '>=10.13.0'} + postcss-import@15.1.0: resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} engines: {node: '>=14.0.0'} @@ -2125,6 +2321,11 @@ packages: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} + postject@1.0.0-alpha.6: + resolution: {integrity: sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==} + engines: {node: '>=14.0.0'} + hasBin: true + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -2138,13 +2339,22 @@ packages: engines: {node: '>=14'} hasBin: true - process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + proc-log@2.0.1: + resolution: {integrity: sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} progress@2.0.3: resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} engines: {node: '>=0.4.0'} + promise-inflight@1.0.1: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + promise-retry@2.0.1: resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} engines: {node: '>=10'} @@ -2169,6 +2379,11 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + qrcode@1.5.4: + resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==} + engines: {node: '>=10.13.0'} + hasBin: true + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -2186,23 +2401,17 @@ packages: rbush@4.0.1: resolution: {integrity: sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ==} + read-binary-file-arch@1.0.6: + resolution: {integrity: sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==} + hasBin: true + read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} - read-config-file@6.3.2: - resolution: {integrity: sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==} - engines: {node: '>=12.0.0'} - - readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} - readdir-glob@1.1.3: - resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} - readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -2215,6 +2424,13 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + + resedit@1.7.2: + resolution: {integrity: sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA==} + engines: {node: '>=12', npm: '>=6'} + resolve-alpn@1.2.1: resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} @@ -2233,6 +2449,10 @@ packages: responselike@2.0.1: resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} + restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + retry@0.12.0: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} @@ -2241,6 +2461,16 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rimraf@2.6.3: + resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + roarr@2.15.4: resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==} engines: {node: '>=8.0'} @@ -2256,9 +2486,6 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -2281,6 +2508,10 @@ packages: semver-compare@1.0.0: resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -2294,6 +2525,9 @@ packages: resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} engines: {node: '>=10'} + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -2305,6 +2539,9 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -2321,6 +2558,14 @@ packages: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + socks-proxy-agent@7.0.0: + resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} + engines: {node: '>= 10'} + + socks@2.8.7: + resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -2335,6 +2580,10 @@ packages: sprintf-js@1.1.3: resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + ssri@9.0.1: + resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -2353,9 +2602,6 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} - string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -2403,10 +2649,6 @@ packages: engines: {node: '>=14.0.0'} hasBin: true - tar-stream@2.2.0: - resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} - engines: {node: '>=6'} - tar@6.2.1: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} @@ -2414,6 +2656,10 @@ packages: temp-file@3.4.0: resolution: {integrity: sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==} + temp@0.9.4: + resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==} + engines: {node: '>=6.0.0'} + terser@5.44.1: resolution: {integrity: sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==} engines: {node: '>=10'} @@ -2426,6 +2672,9 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + tiny-async-pool@1.3.0: + resolution: {integrity: sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA==} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -2499,6 +2748,14 @@ packages: undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + unique-filename@2.0.1: + resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + unique-slug@3.0.0: + resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -2685,6 +2942,9 @@ packages: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + web-worker@1.5.0: resolution: {integrity: sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==} @@ -2705,6 +2965,9 @@ packages: resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} engines: {node: '>=18'} + which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -2719,6 +2982,10 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -2760,6 +3027,9 @@ packages: xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -2767,10 +3037,18 @@ packages: yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} + yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} @@ -2782,10 +3060,6 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - zip-stream@4.1.1: - resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==} - engines: {node: '>= 10'} - zstddec@0.1.0: resolution: {integrity: sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==} @@ -2845,12 +3119,24 @@ snapshots: dependencies: '@types/hammerjs': 2.0.46 + '@electron/asar@3.2.18': + dependencies: + commander: 5.1.0 + glob: 7.2.3 + minimatch: 3.1.2 + '@electron/asar@3.4.1': dependencies: commander: 5.1.0 glob: 7.2.3 minimatch: 3.1.2 + '@electron/fuses@1.8.0': + dependencies: + chalk: 4.1.2 + fs-extra: 9.1.0 + minimist: 1.2.8 + '@electron/get@2.0.3': dependencies: debug: 4.4.3 @@ -2865,7 +3151,23 @@ snapshots: transitivePeerDependencies: - supports-color - '@electron/notarize@2.2.1': + '@electron/node-gyp@https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2': + dependencies: + env-paths: 2.2.1 + exponential-backoff: 3.1.3 + glob: 8.1.0 + graceful-fs: 4.2.11 + make-fetch-happen: 10.2.1 + nopt: 6.0.0 + proc-log: 2.0.1 + semver: 7.7.3 + tar: 6.2.1 + which: 2.0.2 + transitivePeerDependencies: + - bluebird + - supports-color + + '@electron/notarize@2.5.0': dependencies: debug: 4.4.3 fs-extra: 9.1.0 @@ -2873,7 +3175,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@electron/osx-sign@1.0.5': + '@electron/osx-sign@1.3.1': dependencies: compare-version: 0.1.2 debug: 4.4.3 @@ -2884,18 +3186,49 @@ snapshots: transitivePeerDependencies: - supports-color - '@electron/universal@1.5.1': + '@electron/rebuild@3.7.0': dependencies: - '@electron/asar': 3.4.1 - '@malept/cross-spawn-promise': 1.1.1 + '@electron/node-gyp': https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2 + '@malept/cross-spawn-promise': 2.0.0 + chalk: 4.1.2 debug: 4.4.3 - dir-compare: 3.3.0 - fs-extra: 9.1.0 - minimatch: 3.1.2 + detect-libc: 2.1.2 + fs-extra: 10.1.0 + got: 11.8.6 + node-abi: 3.85.0 + node-api-version: 0.2.1 + ora: 5.4.1 + read-binary-file-arch: 1.0.6 + semver: 7.7.3 + tar: 6.2.1 + yargs: 17.7.2 + transitivePeerDependencies: + - bluebird + - supports-color + + '@electron/universal@2.0.1': + dependencies: + '@electron/asar': 3.2.18 + '@malept/cross-spawn-promise': 2.0.0 + debug: 4.4.3 + dir-compare: 4.2.0 + fs-extra: 11.3.3 + minimatch: 9.0.5 plist: 3.1.0 transitivePeerDependencies: - supports-color + '@electron/windows-sign@1.2.2': + dependencies: + cross-dirname: 0.1.0 + debug: 4.4.3 + fs-extra: 11.3.3 + minimist: 1.2.8 + postject: 1.0.0-alpha.6 + transitivePeerDependencies: + - supports-color + optional: true + '@esbuild/aix-ppc64@0.25.12': optional: true @@ -3020,6 +3353,8 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 + '@gar/promisify@1.1.3': {} + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.7': @@ -3043,6 +3378,12 @@ snapshots: '@intlify/shared@11.2.8': {} + '@isaacs/balanced-match@4.0.1': {} + + '@isaacs/brace-expansion@5.0.0': + dependencies: + '@isaacs/balanced-match': 4.0.1 + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -3071,7 +3412,7 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@malept/cross-spawn-promise@1.1.1': + '@malept/cross-spawn-promise@2.0.0': dependencies: cross-spawn: 7.0.6 @@ -3098,6 +3439,16 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 + '@npmcli/fs@2.1.2': + dependencies: + '@gar/promisify': 1.1.3 + semver: 7.7.3 + + '@npmcli/move-file@2.0.1': + dependencies: + mkdirp: 1.0.4 + rimraf: 3.0.2 + '@one-ini/wasm@0.1.1': {} '@petamoriken/float16@3.9.3': {} @@ -3403,6 +3754,8 @@ snapshots: '@xmldom/xmldom@0.8.11': {} + abbrev@1.1.1: {} + abbrev@2.0.0: {} acorn-jsx@5.3.2(acorn@8.15.0): @@ -3419,6 +3772,15 @@ snapshots: agent-base@7.1.4: {} + agentkeepalive@4.6.0: + dependencies: + humanize-ms: 1.2.1 + + aggregate-error@3.1.0: + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + ajv-keywords@3.5.2(ajv@6.12.6): dependencies: ajv: 6.12.6 @@ -3447,78 +3809,49 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 - app-builder-bin@4.0.0: {} + app-builder-bin@5.0.0-alpha.12: {} - app-builder-lib@24.13.3(dmg-builder@24.13.3)(electron-builder-squirrel-windows@24.13.3): + app-builder-lib@26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12): dependencies: '@develar/schema-utils': 2.6.5 - '@electron/notarize': 2.2.1 - '@electron/osx-sign': 1.0.5 - '@electron/universal': 1.5.1 + '@electron/asar': 3.2.18 + '@electron/fuses': 1.8.0 + '@electron/notarize': 2.5.0 + '@electron/osx-sign': 1.3.1 + '@electron/rebuild': 3.7.0 + '@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: 24.13.1 - builder-util-runtime: 9.2.4 + builder-util: 26.0.11 + builder-util-runtime: 9.3.1 chromium-pickle-js: 0.2.0 + config-file-ts: 0.2.8-rc1 debug: 4.4.3 - dmg-builder: 24.13.3(electron-builder-squirrel-windows@24.13.3) + dmg-builder: 26.0.12(electron-builder-squirrel-windows@26.0.12) + dotenv: 16.6.1 + dotenv-expand: 11.0.7 ejs: 3.1.10 - electron-builder-squirrel-windows: 24.13.3(dmg-builder@24.13.3) - electron-publish: 24.13.1 - form-data: 4.0.5 + electron-builder-squirrel-windows: 26.0.12(dmg-builder@26.0.12) + electron-publish: 26.0.11 fs-extra: 10.1.0 hosted-git-info: 4.1.0 is-ci: 3.0.1 isbinaryfile: 5.0.7 js-yaml: 4.1.1 + json5: 2.2.3 lazy-val: 1.0.5 - minimatch: 5.1.6 - read-config-file: 6.3.2 - sanitize-filename: 1.6.3 + minimatch: 10.1.1 + plist: 3.1.0 + resedit: 1.7.2 semver: 7.7.3 tar: 6.2.1 temp-file: 3.4.0 + tiny-async-pool: 1.3.0 transitivePeerDependencies: + - bluebird - supports-color - archiver-utils@2.1.0: - dependencies: - glob: 7.2.3 - graceful-fs: 4.2.11 - lazystream: 1.0.1 - 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.3.8 - - archiver-utils@3.0.4: - dependencies: - glob: 7.2.3 - graceful-fs: 4.2.11 - lazystream: 1.0.1 - 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.2 - - archiver@5.3.2: - dependencies: - archiver-utils: 2.1.0 - async: 3.2.6 - buffer-crc32: 0.2.13 - readable-stream: 3.6.2 - readdir-glob: 1.1.3 - tar-stream: 2.2.0 - zip-stream: 4.1.1 - arg@5.0.2: {} argparse@2.0.1: {} @@ -3570,12 +3903,6 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 - bluebird-lst@1.0.9: - dependencies: - bluebird: 3.7.2 - - bluebird@3.7.2: {} - blueimp-canvas-to-blob@3.29.0: {} boolbase@1.0.0: {} @@ -3606,8 +3933,6 @@ snapshots: buffer-crc32@0.2.13: {} - buffer-equal@1.0.1: {} - buffer-from@1.1.2: {} buffer@5.7.1: @@ -3615,36 +3940,60 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 - builder-util-runtime@9.2.4: + builder-util-runtime@9.3.1: dependencies: debug: 4.4.3 sax: 1.4.3 transitivePeerDependencies: - supports-color - builder-util@24.13.1: + builder-util@26.0.11: dependencies: 7zip-bin: 5.2.0 '@types/debug': 4.1.12 - app-builder-bin: 4.0.0 - bluebird-lst: 1.0.9 - builder-util-runtime: 9.2.4 + app-builder-bin: 5.0.0-alpha.12 + builder-util-runtime: 9.3.1 chalk: 4.1.2 cross-spawn: 7.0.6 debug: 4.4.3 fs-extra: 10.1.0 - http-proxy-agent: 5.0.0 - https-proxy-agent: 5.0.1 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 is-ci: 3.0.1 js-yaml: 4.1.1 + sanitize-filename: 1.6.3 source-map-support: 0.5.21 stat-mode: 1.0.0 temp-file: 3.4.0 + tiny-async-pool: 1.3.0 transitivePeerDependencies: - supports-color cac@6.7.14: {} + cacache@16.1.3: + dependencies: + '@npmcli/fs': 2.1.2 + '@npmcli/move-file': 2.0.1 + chownr: 2.0.0 + fs-minipass: 2.1.0 + glob: 8.1.0 + infer-owner: 1.0.4 + lru-cache: 7.18.3 + minipass: 3.3.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.1 + tar: 6.2.1 + unique-filename: 2.0.1 + transitivePeerDependencies: + - bluebird + cacheable-lookup@5.0.4: {} cacheable-request@7.0.4: @@ -3666,12 +4015,14 @@ snapshots: camelcase-css@2.0.1: {} + camelcase@5.3.1: {} + caniuse-lite@1.0.30001762: {} chai@5.3.3: dependencies: assertion-error: 2.0.1 - check-error: 2.1.1 + check-error: 2.1.3 deep-eql: 5.0.2 loupe: 3.2.1 pathval: 2.0.1 @@ -3681,7 +4032,7 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 - check-error@2.1.1: {} + check-error@2.1.3: {} chokidar@3.6.0: dependencies: @@ -3701,6 +4052,14 @@ snapshots: ci-info@3.9.0: {} + clean-stack@2.2.0: {} + + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + + cli-spinners@2.9.2: {} + cli-truncate@2.1.0: dependencies: slice-ansi: 3.0.0 @@ -3709,6 +4068,12 @@ snapshots: click-outside-vue3@4.0.1: {} + cliui@6.0.0: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -3719,6 +4084,8 @@ snapshots: dependencies: mimic-response: 1.0.1 + clone@1.0.4: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -3737,17 +4104,13 @@ snapshots: commander@5.1.0: {} + commander@9.5.0: + optional: true + compare-version@0.1.2: {} component-emitter@2.0.0: {} - compress-commons@4.1.2: - dependencies: - buffer-crc32: 0.2.13 - crc32-stream: 4.0.3 - normalize-path: 3.0.0 - readable-stream: 3.6.2 - compressorjs@1.2.1: dependencies: blueimp-canvas-to-blob: 3.29.0 @@ -3760,7 +4123,7 @@ snapshots: ini: 1.3.8 proto-list: 1.2.4 - config-file-ts@0.2.6: + config-file-ts@0.2.8-rc1: dependencies: glob: 10.5.0 typescript: 5.9.3 @@ -3768,20 +4131,14 @@ snapshots: core-util-is@1.0.2: optional: true - core-util-is@1.0.3: {} - - crc-32@1.2.2: {} - - crc32-stream@4.0.3: - dependencies: - crc-32: 1.2.2 - readable-stream: 3.6.2 - crc@3.8.0: dependencies: buffer: 5.7.1 optional: true + cross-dirname@0.1.0: + optional: true + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -3808,6 +4165,8 @@ snapshots: dependencies: ms: 2.1.3 + decamelize@1.2.0: {} + decimal.js@10.6.0: {} decompress-response@6.0.0: @@ -3818,6 +4177,10 @@ snapshots: deep-is@0.1.4: {} + defaults@1.0.4: + dependencies: + clone: 1.0.4 + defer-to-connect@2.0.1: {} define-data-property@1.1.4: @@ -3836,29 +4199,34 @@ snapshots: delayed-stream@1.0.0: {} + detect-libc@2.1.2: {} + detect-node@2.1.0: optional: true didyoumean@1.2.2: {} - dir-compare@3.3.0: + dijkstrajs@1.0.3: {} + + dir-compare@4.2.0: dependencies: - buffer-equal: 1.0.1 minimatch: 3.1.2 + p-limit: 3.1.0 dlv@1.1.3: {} - dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3): + dmg-builder@26.0.12(electron-builder-squirrel-windows@26.0.12): dependencies: - app-builder-lib: 24.13.3(dmg-builder@24.13.3)(electron-builder-squirrel-windows@24.13.3) - builder-util: 24.13.1 - builder-util-runtime: 9.2.4 + app-builder-lib: 26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12) + builder-util: 26.0.11 + builder-util-runtime: 9.3.1 fs-extra: 10.1.0 iconv-lite: 0.6.3 js-yaml: 4.1.1 optionalDependencies: dmg-license: 1.0.11 transitivePeerDependencies: + - bluebird - electron-builder-squirrel-windows - supports-color @@ -3878,9 +4246,11 @@ snapshots: optionalDependencies: '@types/trusted-types': 2.0.7 - dotenv-expand@5.1.0: {} + dotenv-expand@11.0.7: + dependencies: + dotenv: 16.6.1 - dotenv@9.0.2: {} + dotenv@16.6.1: {} dunder-proto@1.0.1: dependencies: @@ -3903,41 +4273,42 @@ snapshots: dependencies: jake: 10.9.4 - electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3): + electron-builder-squirrel-windows@26.0.12(dmg-builder@26.0.12): dependencies: - app-builder-lib: 24.13.3(dmg-builder@24.13.3)(electron-builder-squirrel-windows@24.13.3) - archiver: 5.3.2 - builder-util: 24.13.1 - fs-extra: 10.1.0 + app-builder-lib: 26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12) + builder-util: 26.0.11 + electron-winstaller: 5.4.0 transitivePeerDependencies: + - bluebird - dmg-builder - supports-color - electron-builder@24.13.3(electron-builder-squirrel-windows@24.13.3): + electron-builder@26.0.12(electron-builder-squirrel-windows@26.0.12): dependencies: - app-builder-lib: 24.13.3(dmg-builder@24.13.3)(electron-builder-squirrel-windows@24.13.3) - builder-util: 24.13.1 - builder-util-runtime: 9.2.4 + app-builder-lib: 26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12) + builder-util: 26.0.11 + builder-util-runtime: 9.3.1 chalk: 4.1.2 - dmg-builder: 24.13.3(electron-builder-squirrel-windows@24.13.3) + dmg-builder: 26.0.12(electron-builder-squirrel-windows@26.0.12) fs-extra: 10.1.0 is-ci: 3.0.1 lazy-val: 1.0.5 - read-config-file: 6.3.2 simple-update-notifier: 2.0.0 yargs: 17.7.2 transitivePeerDependencies: + - bluebird - electron-builder-squirrel-windows - supports-color electron-prompt@1.7.0: {} - electron-publish@24.13.1: + electron-publish@26.0.11: dependencies: '@types/fs-extra': 9.0.13 - builder-util: 24.13.1 - builder-util-runtime: 9.2.4 + builder-util: 26.0.11 + builder-util-runtime: 9.3.1 chalk: 4.1.2 + form-data: 4.0.5 fs-extra: 10.1.0 lazy-val: 1.0.5 mime: 2.6.0 @@ -3946,6 +4317,18 @@ snapshots: electron-to-chromium@1.5.267: {} + electron-winstaller@5.4.0: + dependencies: + '@electron/asar': 3.4.1 + debug: 4.4.3 + fs-extra: 7.0.1 + lodash: 4.17.21 + temp: 0.9.4 + optionalDependencies: + '@electron/windows-sign': 1.2.2 + transitivePeerDependencies: + - supports-color + electron@39.2.7: dependencies: '@electron/get': 2.0.3 @@ -3958,6 +4341,11 @@ snapshots: emoji-regex@9.2.2: {} + encoding@0.1.13: + dependencies: + iconv-lite: 0.6.3 + optional: true + end-of-stream@1.4.5: dependencies: once: 1.4.0 @@ -4127,6 +4515,8 @@ snapshots: expect-type@1.3.0: {} + exponential-backoff@3.1.3: {} + extract-zip@2.0.1: dependencies: debug: 4.4.3 @@ -4180,6 +4570,11 @@ snapshots: dependencies: to-regex-range: 5.0.1 + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -4209,14 +4604,24 @@ snapshots: fraction.js@5.3.4: {} - fs-constants@1.0.0: {} - fs-extra@10.1.0: dependencies: graceful-fs: 4.2.11 jsonfile: 6.2.0 universalify: 2.0.1 + fs-extra@11.3.3: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + fs-extra@8.1.0: dependencies: graceful-fs: 4.2.11 @@ -4302,6 +4707,14 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 + glob@8.1.0: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + global-agent@3.0.0: dependencies: boolean: 3.2.0 @@ -4401,6 +4814,10 @@ snapshots: transitivePeerDependencies: - supports-color + humanize-ms@1.2.1: + dependencies: + ms: 2.1.3 + iconv-corefoundation@1.1.7: dependencies: cli-truncate: 2.1.0 @@ -4422,6 +4839,10 @@ snapshots: imurmurhash@0.1.4: {} + indent-string@4.0.0: {} + + infer-owner@1.0.4: {} + inflight@1.0.6: dependencies: once: 1.4.0 @@ -4431,6 +4852,8 @@ snapshots: ini@1.3.8: {} + ip-address@10.1.0: {} + is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 @@ -4453,11 +4876,15 @@ snapshots: dependencies: is-extglob: 2.1.1 + is-interactive@1.0.0: {} + + is-lambda@1.0.1: {} + is-number@7.0.0: {} is-potential-custom-element-name@1.0.1: {} - isarray@1.0.0: {} + is-unicode-supported@0.1.0: {} isbinaryfile@4.0.10: {} @@ -4551,10 +4978,6 @@ snapshots: lazy-val@1.0.5: {} - lazystream@1.0.1: - dependencies: - readable-stream: 2.3.8 - lerc@3.0.0: {} levn@0.4.1: @@ -4566,24 +4989,23 @@ snapshots: lines-and-columns@1.2.4: {} + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + locate-path@6.0.0: dependencies: p-locate: 5.0.0 - lodash.defaults@4.2.0: {} - - lodash.difference@4.5.0: {} - - lodash.flatten@4.4.0: {} - - lodash.isplainobject@4.0.6: {} - lodash.merge@4.6.2: {} - lodash.union@4.6.0: {} - lodash@4.17.21: {} + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + long@5.3.2: {} loupe@3.2.1: {} @@ -4596,10 +5018,34 @@ snapshots: dependencies: yallist: 4.0.0 + lru-cache@7.18.3: {} + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + make-fetch-happen@10.2.1: + dependencies: + agentkeepalive: 4.6.0 + cacache: 16.1.3 + http-cache-semantics: 4.2.0 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-lambda: 1.0.1 + lru-cache: 7.18.3 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-fetch: 2.1.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.4 + promise-retry: 2.0.1 + socks-proxy-agent: 7.0.0 + ssri: 9.0.1 + transitivePeerDependencies: + - bluebird + - supports-color + matcher@3.0.0: dependencies: escape-string-regexp: 4.0.0 @@ -4626,12 +5072,18 @@ snapshots: mime@2.6.0: {} + mimic-fn@2.1.0: {} + mimic-response@1.0.1: {} mimic-response@3.1.0: {} mini-svg-data-uri@1.4.4: {} + minimatch@10.1.1: + dependencies: + '@isaacs/brace-expansion': 5.0.0 + minimatch@3.1.2: dependencies: brace-expansion: 1.1.12 @@ -4650,6 +5102,30 @@ snapshots: minimist@1.2.8: {} + minipass-collect@1.0.2: + dependencies: + minipass: 3.3.6 + + minipass-fetch@2.1.2: + dependencies: + minipass: 3.3.6 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + + minipass-flush@1.0.5: + dependencies: + minipass: 3.3.6 + + minipass-pipeline@1.2.4: + dependencies: + minipass: 3.3.6 + + minipass-sized@1.0.3: + dependencies: + minipass: 3.3.6 + minipass@3.3.6: dependencies: yallist: 4.0.0 @@ -4665,6 +5141,10 @@ snapshots: mitt@3.0.1: {} + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + mkdirp@1.0.4: {} ms@2.1.3: {} @@ -4679,11 +5159,25 @@ snapshots: natural-compare@1.4.0: {} + negotiator@0.6.4: {} + + node-abi@3.85.0: + dependencies: + semver: 7.7.3 + node-addon-api@1.7.2: optional: true + node-api-version@0.2.1: + dependencies: + semver: 7.7.3 + node-releases@2.0.27: {} + nopt@6.0.0: + dependencies: + abbrev: 1.1.1 + nopt@7.2.1: dependencies: abbrev: 2.0.0 @@ -4717,6 +5211,10 @@ snapshots: dependencies: wrappy: 1.0.2 + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -4726,16 +5224,42 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 + ora@5.4.1: + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + p-cancelable@2.1.1: {} + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + p-locate@5.0.0: dependencies: p-limit: 3.1.0 + p-map@4.0.0: + dependencies: + aggregate-error: 3.1.0 + + p-try@2.2.0: {} + package-json-from-dist@1.0.1: {} pako@2.1.0: {} @@ -4771,6 +5295,8 @@ snapshots: dependencies: resolve-protobuf-schema: 2.1.0 + pe-library@0.4.1: {} + pend@1.2.0: {} picocolors@1.1.1: {} @@ -4789,6 +5315,8 @@ snapshots: base64-js: 1.5.1 xmlbuilder: 15.1.1 + pngjs@5.0.0: {} + postcss-import@15.1.0(postcss@8.5.6): dependencies: postcss: 8.5.6 @@ -4831,6 +5359,11 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + postject@1.0.0-alpha.6: + dependencies: + commander: 9.5.0 + optional: true + prelude-ls@1.2.1: {} prettier-linter-helpers@1.0.1: @@ -4839,10 +5372,12 @@ snapshots: prettier@3.7.4: {} - process-nextick-args@2.0.1: {} + proc-log@2.0.1: {} progress@2.0.3: {} + promise-inflight@1.0.1: {} + promise-retry@2.0.1: dependencies: err-code: 2.0.3 @@ -4876,6 +5411,12 @@ snapshots: punycode@2.3.1: {} + qrcode@1.5.4: + dependencies: + dijkstrajs: 1.0.3 + pngjs: 5.0.0 + yargs: 15.4.1 + queue-microtask@1.2.3: {} quick-lru@5.1.1: {} @@ -4888,39 +5429,22 @@ snapshots: dependencies: quickselect: 3.0.0 + read-binary-file-arch@1.0.6: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + read-cache@1.0.0: dependencies: pify: 2.3.0 - read-config-file@6.3.2: - dependencies: - config-file-ts: 0.2.6 - dotenv: 9.0.2 - dotenv-expand: 5.1.0 - js-yaml: 4.1.1 - json5: 2.2.3 - lazy-val: 1.0.5 - - readable-stream@2.3.8: - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - readable-stream@3.6.2: dependencies: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - readdir-glob@1.1.3: - dependencies: - minimatch: 5.1.6 - readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -4929,6 +5453,12 @@ snapshots: require-directory@2.1.1: {} + require-main-filename@2.0.0: {} + + resedit@1.7.2: + dependencies: + pe-library: 0.4.1 + resolve-alpn@1.2.1: {} resolve-from@4.0.0: {} @@ -4947,10 +5477,23 @@ snapshots: dependencies: lowercase-keys: 2.0.0 + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + retry@0.12.0: {} reusify@1.1.0: {} + rimraf@2.6.3: + dependencies: + glob: 7.2.3 + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + roarr@2.15.4: dependencies: boolean: 3.2.0 @@ -4995,8 +5538,6 @@ snapshots: dependencies: queue-microtask: 1.2.3 - safe-buffer@5.1.2: {} - safe-buffer@5.2.1: {} safe-regex@2.1.1: @@ -5018,6 +5559,8 @@ snapshots: semver-compare@1.0.0: optional: true + semver@5.7.2: {} + semver@6.3.1: {} semver@7.7.3: {} @@ -5027,6 +5570,8 @@ snapshots: type-fest: 0.13.1 optional: true + set-blocking@2.0.0: {} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -5035,6 +5580,8 @@ snapshots: siginfo@2.0.0: {} + signal-exit@3.0.7: {} + signal-exit@4.1.0: {} simple-update-notifier@2.0.0: @@ -5048,8 +5595,20 @@ snapshots: is-fullwidth-code-point: 3.0.0 optional: true - smart-buffer@4.2.0: - optional: true + smart-buffer@4.2.0: {} + + socks-proxy-agent@7.0.0: + dependencies: + agent-base: 6.0.2 + debug: 4.4.3 + socks: 2.8.7 + transitivePeerDependencies: + - supports-color + + socks@2.8.7: + dependencies: + ip-address: 10.1.0 + smart-buffer: 4.2.0 source-map-js@1.2.1: {} @@ -5063,6 +5622,10 @@ snapshots: sprintf-js@1.1.3: optional: true + ssri@9.0.1: + dependencies: + minipass: 3.3.6 + stackback@0.0.2: {} stat-mode@1.0.0: {} @@ -5081,10 +5644,6 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.2 - string_decoder@1.1.1: - dependencies: - safe-buffer: 5.1.2 - string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 @@ -5159,14 +5718,6 @@ snapshots: - tsx - yaml - tar-stream@2.2.0: - dependencies: - bl: 4.1.0 - end-of-stream: 1.4.5 - fs-constants: 1.0.0 - inherits: 2.0.4 - readable-stream: 3.6.2 - tar@6.2.1: dependencies: chownr: 2.0.0 @@ -5181,6 +5732,11 @@ snapshots: async-exit-hook: 2.0.1 fs-extra: 10.1.0 + temp@0.9.4: + dependencies: + mkdirp: 0.5.6 + rimraf: 2.6.3 + terser@5.44.1: dependencies: '@jridgewell/source-map': 0.3.11 @@ -5196,6 +5752,10 @@ snapshots: dependencies: any-promise: 1.3.0 + tiny-async-pool@1.3.0: + dependencies: + semver: 5.7.2 + tinybench@2.9.0: {} tinyexec@0.3.2: {} @@ -5254,6 +5814,14 @@ snapshots: undici-types@7.16.0: {} + unique-filename@2.0.1: + dependencies: + unique-slug: 3.0.0 + + unique-slug@3.0.0: + dependencies: + imurmurhash: 0.1.4 + universalify@0.1.2: {} universalify@2.0.1: {} @@ -5438,6 +6006,10 @@ snapshots: dependencies: xml-name-validator: 5.0.0 + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + web-worker@1.5.0: {} webidl-conversions@7.0.0: {} @@ -5453,6 +6025,8 @@ snapshots: tr46: 5.1.1 webidl-conversions: 7.0.0 + which-module@2.0.1: {} + which@2.0.2: dependencies: isexe: 2.0.0 @@ -5464,6 +6038,12 @@ snapshots: word-wrap@1.2.5: {} + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -5490,12 +6070,33 @@ snapshots: xmlchars@2.2.0: {} + y18n@4.0.3: {} + y18n@5.0.8: {} yallist@4.0.0: {} + yargs-parser@18.1.3: + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + yargs-parser@21.1.1: {} + yargs@15.4.1: + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 + yargs@17.7.2: dependencies: cliui: 8.0.1 @@ -5513,10 +6114,4 @@ snapshots: yocto-queue@0.1.0: {} - zip-stream@4.1.1: - dependencies: - archiver-utils: 3.0.4 - compress-commons: 4.1.2 - readable-stream: 3.6.2 - zstddec@0.1.0: {} diff --git a/poetry.lock b/poetry.lock index 151e20d..78deee3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2255,4 +2255,4 @@ propcache = ">=0.2.1" [metadata] lock-version = "2.1" python-versions = ">=3.11" -content-hash = "9d03990204883e71575c8405b04839eb85e6375cf0a6abdc70ecb11df89f98d1" +content-hash = "c67b3ada4344775b47db71c46d8c43724f0631728f5b3922b48ef8859a82c76e" diff --git a/pyproject.toml b/pyproject.toml index 29d338a..c472315 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "reticulum-meshchatx" -version = "3.3.2" +version = "4.0.0" description = "A simple mesh network communications app powered by the Reticulum Network Stack" authors = [ {name = "Sudo-Ivan"} @@ -29,9 +29,9 @@ dependencies = [ "aiohttp-session>=2.12.1,<3.0.0", "cryptography>=46.0.3,<47.0.0", "requests>=2.32.5,<3.0.0", - "lxst>=0.4.5,<0.5.0", "audioop-lts>=0.2.2; python_version >= '3.13'", "ply>=3.11,<4.0", + "lxst", ] [project.scripts] @@ -43,6 +43,9 @@ Homepage = "https://git.quad4.io/RNS-Things/MeshChatX" [tool.poetry] packages = [{include = "meshchatx"}] +[tool.poetry.dependencies] +python = ">=3.11" + [tool.poetry.group.dev.dependencies] cx-freeze = ">=7.0.0" pytest = ">=9.0.2,<10.0.0" From b59c21f4837fd38187f2ecfc3b6186fda5f3d4f9 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sat, 3 Jan 2026 15:44:17 -0600 Subject: [PATCH 003/234] feat(Taskfile, workflows): add new benchmarking and integrity testing tasks, and create a Gitea workflow for automated benchmarks --- .gitea/workflows/bench.yml | 43 ++++++++++++++++++++++++++++++++++++++ Taskfile.yml | 35 +++++++++++++++++++++++++++++-- 2 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 .gitea/workflows/bench.yml diff --git a/.gitea/workflows/bench.yml b/.gitea/workflows/bench.yml new file mode 100644 index 0000000..809defb --- /dev/null +++ b/.gitea/workflows/bench.yml @@ -0,0 +1,43 @@ +name: Benchmarks + +on: + push: + branches: + - "*" + pull_request: + workflow_dispatch: + +jobs: + benchmark: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: https://git.quad4.io/actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - name: Setup Node.js + uses: https://git.quad4.io/actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 + with: + node-version: 22 + cache: pnpm + + - name: Setup Python + uses: https://git.quad4.io/actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + with: + python-version: "3.13" + + - name: Setup Task + uses: https://git.quad4.io/actions/setup-task@0ab1b2a65bc55236a3bc64cde78f80e20e8885c2 # v1 + with: + version: "3.46.3" + + - name: Setup Poetry + run: pip install poetry + + - name: Install dependencies + run: task install + + - name: Run Benchmarks + run: task bench + + - name: Run Integrity Tests + run: task test-integrity diff --git a/Taskfile.yml b/Taskfile.yml index dff6ba6..61448b4 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -106,6 +106,11 @@ tasks: cmds: - "{{.NPM}} run test" + gen-locale-template: + desc: Generate a locales.json template with empty values from en.json + cmds: + - "{{.PYTHON}} scripts/generate_locale_template.py" + test: desc: Run all tests deps: [test-python, test-frontend] @@ -114,6 +119,32 @@ tasks: desc: Run all tests with coverage reports deps: [test-python-cov, test-frontend] + bench-backend: + desc: Run comprehensive backend benchmarks + cmds: + - poetry run python tests/backend/run_comprehensive_benchmarks.py + + bench-extreme: + desc: Run extreme backend stress benchmarks (Breaking Space Mode) + cmds: + - poetry run python tests/backend/run_comprehensive_benchmarks.py --extreme + + profile-memory: + desc: Run backend memory profiling tests + cmds: + - poetry run pytest tests/backend/test_memory_profiling.py + + test-integrity: + desc: Run backend and data integrity tests + cmds: + - poetry run pytest tests/backend/test_integrity.py tests/backend/test_backend_integrity.py + + bench: + desc: Run all backend benchmarks and memory profiling + cmds: + - task: bench-backend + - task: profile-memory + compile: desc: Compile Python code to check for syntax errors cmds: @@ -213,7 +244,7 @@ tasks: deps: [build, electron-legacy] cmds: - "{{.NPM}} run electron-postinstall" - - "{{.NPM}} run dist -- --linux AppImage" + - "{{.NPM}} run dist -- --linux AppImage -c.extraMetadata.main=electron/main-legacy.js" - "./scripts/rename_legacy_artifacts.sh" build-exe-legacy: @@ -221,7 +252,7 @@ tasks: deps: [build, electron-legacy] cmds: - "{{.NPM}} run electron-postinstall" - - "{{.NPM}} run dist -- --win portable" + - "{{.NPM}} run dist -- --win portable -c.extraMetadata.main=electron/main-legacy.js" - "./scripts/rename_legacy_artifacts.sh" clean: From 46f27007700f48cc0c78fcf5e0120a42f000209c Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sat, 3 Jan 2026 15:45:05 -0600 Subject: [PATCH 004/234] feat(electron): add a new crash report HTML page for displaying error details and logs --- .../tailwind-v3.4.3-forms-v0.5.7.js | 19497 +++++++++++++++- electron/build/icon.png | Bin 111913 -> 296023 bytes electron/crash.html | 148 + electron/loading.html | 25 +- electron/main-legacy.js | 366 + electron/main.js | 338 +- electron/preload.js | 50 + 7 files changed, 20341 insertions(+), 83 deletions(-) create mode 100644 electron/crash.html create mode 100644 electron/main-legacy.js diff --git a/electron/assets/js/tailwindcss/tailwind-v3.4.3-forms-v0.5.7.js b/electron/assets/js/tailwindcss/tailwind-v3.4.3-forms-v0.5.7.js index 8369aad..5f8bd4a 100644 --- a/electron/assets/js/tailwindcss/tailwind-v3.4.3-forms-v0.5.7.js +++ b/electron/assets/js/tailwindcss/tailwind-v3.4.3-forms-v0.5.7.js @@ -1,44 +1,18907 @@ -(()=>{var Rb=Object.create;var ci=Object.defineProperty;var Mb=Object.getOwnPropertyDescriptor;var Bb=Object.getOwnPropertyNames;var Fb=Object.getPrototypeOf,Lb=Object.prototype.hasOwnProperty;var gu=r=>ci(r,"__esModule",{value:!0});var yu=r=>{if(typeof require!="undefined")return require(r);throw new Error('Dynamic require of "'+r+'" is not supported')};var C=(r,e)=>()=>(r&&(e=r(r=0)),e);var v=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),Ae=(r,e)=>{gu(r);for(var t in e)ci(r,t,{get:e[t],enumerable:!0})},Nb=(r,e,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Bb(e))!Lb.call(r,i)&&i!=="default"&&ci(r,i,{get:()=>e[i],enumerable:!(t=Mb(e,i))||t.enumerable});return r},X=r=>Nb(gu(ci(r!=null?Rb(Fb(r)):{},"default",r&&r.__esModule&&"default"in r?{get:()=>r.default,enumerable:!0}:{value:r,enumerable:!0})),r);var h,l=C(()=>{h={platform:"",env:{},versions:{node:"14.17.6"}}});var $b,te,ze=C(()=>{l();$b=0,te={readFileSync:r=>self[r]||"",statSync:()=>({mtimeMs:$b++}),promises:{readFile:r=>Promise.resolve(self[r]||"")}}});var rs=v((eE,bu)=>{l();"use strict";var wu=class{constructor(e={}){if(!(e.maxSize&&e.maxSize>0))throw new TypeError("`maxSize` must be a number greater than 0");if(typeof e.maxAge=="number"&&e.maxAge===0)throw new TypeError("`maxAge` must be a number greater than 0");this.maxSize=e.maxSize,this.maxAge=e.maxAge||1/0,this.onEviction=e.onEviction,this.cache=new Map,this.oldCache=new Map,this._size=0}_emitEvictions(e){if(typeof this.onEviction=="function")for(let[t,i]of e)this.onEviction(t,i.value)}_deleteIfExpired(e,t){return typeof t.expiry=="number"&&t.expiry<=Date.now()?(typeof this.onEviction=="function"&&this.onEviction(e,t.value),this.delete(e)):!1}_getOrDeleteIfExpired(e,t){if(this._deleteIfExpired(e,t)===!1)return t.value}_getItemValue(e,t){return t.expiry?this._getOrDeleteIfExpired(e,t):t.value}_peek(e,t){let i=t.get(e);return this._getItemValue(e,i)}_set(e,t){this.cache.set(e,t),this._size++,this._size>=this.maxSize&&(this._size=0,this._emitEvictions(this.oldCache),this.oldCache=this.cache,this.cache=new Map)}_moveToRecent(e,t){this.oldCache.delete(e),this._set(e,t)}*_entriesAscending(){for(let e of this.oldCache){let[t,i]=e;this.cache.has(t)||this._deleteIfExpired(t,i)===!1&&(yield e)}for(let e of this.cache){let[t,i]=e;this._deleteIfExpired(t,i)===!1&&(yield e)}}get(e){if(this.cache.has(e)){let t=this.cache.get(e);return this._getItemValue(e,t)}if(this.oldCache.has(e)){let t=this.oldCache.get(e);if(this._deleteIfExpired(e,t)===!1)return this._moveToRecent(e,t),t.value}}set(e,t,{maxAge:i=this.maxAge===1/0?void 0:Date.now()+this.maxAge}={}){this.cache.has(e)?this.cache.set(e,{value:t,maxAge:i}):this._set(e,{value:t,expiry:i})}has(e){return this.cache.has(e)?!this._deleteIfExpired(e,this.cache.get(e)):this.oldCache.has(e)?!this._deleteIfExpired(e,this.oldCache.get(e)):!1}peek(e){if(this.cache.has(e))return this._peek(e,this.cache);if(this.oldCache.has(e))return this._peek(e,this.oldCache)}delete(e){let t=this.cache.delete(e);return t&&this._size--,this.oldCache.delete(e)||t}clear(){this.cache.clear(),this.oldCache.clear(),this._size=0}resize(e){if(!(e&&e>0))throw new TypeError("`maxSize` must be a number greater than 0");let t=[...this._entriesAscending()],i=t.length-e;i<0?(this.cache=new Map(t),this.oldCache=new Map,this._size=t.length):(i>0&&this._emitEvictions(t.slice(0,i)),this.oldCache=new Map(t.slice(i)),this.cache=new Map,this._size=0),this.maxSize=e}*keys(){for(let[e]of this)yield e}*values(){for(let[,e]of this)yield e}*[Symbol.iterator](){for(let e of this.cache){let[t,i]=e;this._deleteIfExpired(t,i)===!1&&(yield[t,i.value])}for(let e of this.oldCache){let[t,i]=e;this.cache.has(t)||this._deleteIfExpired(t,i)===!1&&(yield[t,i.value])}}*entriesDescending(){let e=[...this.cache];for(let t=e.length-1;t>=0;--t){let i=e[t],[n,a]=i;this._deleteIfExpired(n,a)===!1&&(yield[n,a.value])}e=[...this.oldCache];for(let t=e.length-1;t>=0;--t){let i=e[t],[n,a]=i;this.cache.has(n)||this._deleteIfExpired(n,a)===!1&&(yield[n,a.value])}}*entriesAscending(){for(let[e,t]of this._entriesAscending())yield[e,t.value]}get size(){if(!this._size)return this.oldCache.size;let e=0;for(let t of this.oldCache.keys())this.cache.has(t)||e++;return Math.min(this._size+e,this.maxSize)}};bu.exports=wu});var vu,xu=C(()=>{l();vu=r=>r&&r._hash});function pi(r){return vu(r,{ignoreUnknown:!0})}var ku=C(()=>{l();xu()});function Ke(r){if(r=`${r}`,r==="0")return"0";if(/^[+-]?(\d+|\d*\.\d+)(e[+-]?\d+)?(%|\w+)?$/.test(r))return r.replace(/^[+-]?/,t=>t==="-"?"":"-");let e=["var","calc","min","max","clamp"];for(let t of e)if(r.includes(`${t}(`))return`calc(${r} * -1)`}var di=C(()=>{l()});var Su,Cu=C(()=>{l();Su=["preflight","container","accessibility","pointerEvents","visibility","position","inset","isolation","zIndex","order","gridColumn","gridColumnStart","gridColumnEnd","gridRow","gridRowStart","gridRowEnd","float","clear","margin","boxSizing","lineClamp","display","aspectRatio","size","height","maxHeight","minHeight","width","minWidth","maxWidth","flex","flexShrink","flexGrow","flexBasis","tableLayout","captionSide","borderCollapse","borderSpacing","transformOrigin","translate","rotate","skew","scale","transform","animation","cursor","touchAction","userSelect","resize","scrollSnapType","scrollSnapAlign","scrollSnapStop","scrollMargin","scrollPadding","listStylePosition","listStyleType","listStyleImage","appearance","columns","breakBefore","breakInside","breakAfter","gridAutoColumns","gridAutoFlow","gridAutoRows","gridTemplateColumns","gridTemplateRows","flexDirection","flexWrap","placeContent","placeItems","alignContent","alignItems","justifyContent","justifyItems","gap","space","divideWidth","divideStyle","divideColor","divideOpacity","placeSelf","alignSelf","justifySelf","overflow","overscrollBehavior","scrollBehavior","textOverflow","hyphens","whitespace","textWrap","wordBreak","borderRadius","borderWidth","borderStyle","borderColor","borderOpacity","backgroundColor","backgroundOpacity","backgroundImage","gradientColorStops","boxDecorationBreak","backgroundSize","backgroundAttachment","backgroundClip","backgroundPosition","backgroundRepeat","backgroundOrigin","fill","stroke","strokeWidth","objectFit","objectPosition","padding","textAlign","textIndent","verticalAlign","fontFamily","fontSize","fontWeight","textTransform","fontStyle","fontVariantNumeric","lineHeight","letterSpacing","textColor","textOpacity","textDecoration","textDecorationColor","textDecorationStyle","textDecorationThickness","textUnderlineOffset","fontSmoothing","placeholderColor","placeholderOpacity","caretColor","accentColor","opacity","backgroundBlendMode","mixBlendMode","boxShadow","boxShadowColor","outlineStyle","outlineWidth","outlineOffset","outlineColor","ringWidth","ringColor","ringOpacity","ringOffsetWidth","ringOffsetColor","blur","brightness","contrast","dropShadow","grayscale","hueRotate","invert","saturate","sepia","filter","backdropBlur","backdropBrightness","backdropContrast","backdropGrayscale","backdropHueRotate","backdropInvert","backdropOpacity","backdropSaturate","backdropSepia","backdropFilter","transitionProperty","transitionDelay","transitionDuration","transitionTimingFunction","willChange","contain","content","forcedColorAdjust"]});function Au(r,e){return r===void 0?e:Array.isArray(r)?r:[...new Set(e.filter(i=>r!==!1&&r[i]!==!1).concat(Object.keys(r).filter(i=>r[i]!==!1)))]}var _u=C(()=>{l()});var Ou={};Ae(Ou,{default:()=>_e});var _e,hi=C(()=>{l();_e=new Proxy({},{get:()=>String})});function is(r,e,t){typeof h!="undefined"&&h.env.JEST_WORKER_ID||t&&Eu.has(t)||(t&&Eu.add(t),console.warn(""),e.forEach(i=>console.warn(r,"-",i)))}function ns(r){return _e.dim(r)}var Eu,F,Oe=C(()=>{l();hi();Eu=new Set;F={info(r,e){is(_e.bold(_e.cyan("info")),...Array.isArray(r)?[r]:[e,r])},warn(r,e){["content-problems"].includes(r)||is(_e.bold(_e.yellow("warn")),...Array.isArray(r)?[r]:[e,r])},risk(r,e){is(_e.bold(_e.magenta("risk")),...Array.isArray(r)?[r]:[e,r])}}});var as={};Ae(as,{default:()=>ss});function lr({version:r,from:e,to:t}){F.warn(`${e}-color-renamed`,[`As of Tailwind CSS ${r}, \`${e}\` has been renamed to \`${t}\`.`,"Update your configuration file to silence this warning."])}var ss,mi=C(()=>{l();Oe();ss={inherit:"inherit",current:"currentColor",transparent:"transparent",black:"#000",white:"#fff",slate:{50:"#f8fafc",100:"#f1f5f9",200:"#e2e8f0",300:"#cbd5e1",400:"#94a3b8",500:"#64748b",600:"#475569",700:"#334155",800:"#1e293b",900:"#0f172a",950:"#020617"},gray:{50:"#f9fafb",100:"#f3f4f6",200:"#e5e7eb",300:"#d1d5db",400:"#9ca3af",500:"#6b7280",600:"#4b5563",700:"#374151",800:"#1f2937",900:"#111827",950:"#030712"},zinc:{50:"#fafafa",100:"#f4f4f5",200:"#e4e4e7",300:"#d4d4d8",400:"#a1a1aa",500:"#71717a",600:"#52525b",700:"#3f3f46",800:"#27272a",900:"#18181b",950:"#09090b"},neutral:{50:"#fafafa",100:"#f5f5f5",200:"#e5e5e5",300:"#d4d4d4",400:"#a3a3a3",500:"#737373",600:"#525252",700:"#404040",800:"#262626",900:"#171717",950:"#0a0a0a"},stone:{50:"#fafaf9",100:"#f5f5f4",200:"#e7e5e4",300:"#d6d3d1",400:"#a8a29e",500:"#78716c",600:"#57534e",700:"#44403c",800:"#292524",900:"#1c1917",950:"#0c0a09"},red:{50:"#fef2f2",100:"#fee2e2",200:"#fecaca",300:"#fca5a5",400:"#f87171",500:"#ef4444",600:"#dc2626",700:"#b91c1c",800:"#991b1b",900:"#7f1d1d",950:"#450a0a"},orange:{50:"#fff7ed",100:"#ffedd5",200:"#fed7aa",300:"#fdba74",400:"#fb923c",500:"#f97316",600:"#ea580c",700:"#c2410c",800:"#9a3412",900:"#7c2d12",950:"#431407"},amber:{50:"#fffbeb",100:"#fef3c7",200:"#fde68a",300:"#fcd34d",400:"#fbbf24",500:"#f59e0b",600:"#d97706",700:"#b45309",800:"#92400e",900:"#78350f",950:"#451a03"},yellow:{50:"#fefce8",100:"#fef9c3",200:"#fef08a",300:"#fde047",400:"#facc15",500:"#eab308",600:"#ca8a04",700:"#a16207",800:"#854d0e",900:"#713f12",950:"#422006"},lime:{50:"#f7fee7",100:"#ecfccb",200:"#d9f99d",300:"#bef264",400:"#a3e635",500:"#84cc16",600:"#65a30d",700:"#4d7c0f",800:"#3f6212",900:"#365314",950:"#1a2e05"},green:{50:"#f0fdf4",100:"#dcfce7",200:"#bbf7d0",300:"#86efac",400:"#4ade80",500:"#22c55e",600:"#16a34a",700:"#15803d",800:"#166534",900:"#14532d",950:"#052e16"},emerald:{50:"#ecfdf5",100:"#d1fae5",200:"#a7f3d0",300:"#6ee7b7",400:"#34d399",500:"#10b981",600:"#059669",700:"#047857",800:"#065f46",900:"#064e3b",950:"#022c22"},teal:{50:"#f0fdfa",100:"#ccfbf1",200:"#99f6e4",300:"#5eead4",400:"#2dd4bf",500:"#14b8a6",600:"#0d9488",700:"#0f766e",800:"#115e59",900:"#134e4a",950:"#042f2e"},cyan:{50:"#ecfeff",100:"#cffafe",200:"#a5f3fc",300:"#67e8f9",400:"#22d3ee",500:"#06b6d4",600:"#0891b2",700:"#0e7490",800:"#155e75",900:"#164e63",950:"#083344"},sky:{50:"#f0f9ff",100:"#e0f2fe",200:"#bae6fd",300:"#7dd3fc",400:"#38bdf8",500:"#0ea5e9",600:"#0284c7",700:"#0369a1",800:"#075985",900:"#0c4a6e",950:"#082f49"},blue:{50:"#eff6ff",100:"#dbeafe",200:"#bfdbfe",300:"#93c5fd",400:"#60a5fa",500:"#3b82f6",600:"#2563eb",700:"#1d4ed8",800:"#1e40af",900:"#1e3a8a",950:"#172554"},indigo:{50:"#eef2ff",100:"#e0e7ff",200:"#c7d2fe",300:"#a5b4fc",400:"#818cf8",500:"#6366f1",600:"#4f46e5",700:"#4338ca",800:"#3730a3",900:"#312e81",950:"#1e1b4b"},violet:{50:"#f5f3ff",100:"#ede9fe",200:"#ddd6fe",300:"#c4b5fd",400:"#a78bfa",500:"#8b5cf6",600:"#7c3aed",700:"#6d28d9",800:"#5b21b6",900:"#4c1d95",950:"#2e1065"},purple:{50:"#faf5ff",100:"#f3e8ff",200:"#e9d5ff",300:"#d8b4fe",400:"#c084fc",500:"#a855f7",600:"#9333ea",700:"#7e22ce",800:"#6b21a8",900:"#581c87",950:"#3b0764"},fuchsia:{50:"#fdf4ff",100:"#fae8ff",200:"#f5d0fe",300:"#f0abfc",400:"#e879f9",500:"#d946ef",600:"#c026d3",700:"#a21caf",800:"#86198f",900:"#701a75",950:"#4a044e"},pink:{50:"#fdf2f8",100:"#fce7f3",200:"#fbcfe8",300:"#f9a8d4",400:"#f472b6",500:"#ec4899",600:"#db2777",700:"#be185d",800:"#9d174d",900:"#831843",950:"#500724"},rose:{50:"#fff1f2",100:"#ffe4e6",200:"#fecdd3",300:"#fda4af",400:"#fb7185",500:"#f43f5e",600:"#e11d48",700:"#be123c",800:"#9f1239",900:"#881337",950:"#4c0519"},get lightBlue(){return lr({version:"v2.2",from:"lightBlue",to:"sky"}),this.sky},get warmGray(){return lr({version:"v3.0",from:"warmGray",to:"stone"}),this.stone},get trueGray(){return lr({version:"v3.0",from:"trueGray",to:"neutral"}),this.neutral},get coolGray(){return lr({version:"v3.0",from:"coolGray",to:"gray"}),this.gray},get blueGray(){return lr({version:"v3.0",from:"blueGray",to:"slate"}),this.slate}}});function os(r,...e){for(let t of e){for(let i in t)r?.hasOwnProperty?.(i)||(r[i]=t[i]);for(let i of Object.getOwnPropertySymbols(t))r?.hasOwnProperty?.(i)||(r[i]=t[i])}return r}var Tu=C(()=>{l()});function Ze(r){if(Array.isArray(r))return r;let e=r.split("[").length-1,t=r.split("]").length-1;if(e!==t)throw new Error(`Path is invalid. Has unbalanced brackets: ${r}`);return r.split(/\.(?![^\[]*\])|[\[\]]/g).filter(Boolean)}var gi=C(()=>{l()});function K(r,e){return yi.future.includes(e)?r.future==="all"||(r?.future?.[e]??Pu[e]??!1):yi.experimental.includes(e)?r.experimental==="all"||(r?.experimental?.[e]??Pu[e]??!1):!1}function Du(r){return r.experimental==="all"?yi.experimental:Object.keys(r?.experimental??{}).filter(e=>yi.experimental.includes(e)&&r.experimental[e])}function Iu(r){if(h.env.JEST_WORKER_ID===void 0&&Du(r).length>0){let e=Du(r).map(t=>_e.yellow(t)).join(", ");F.warn("experimental-flags-enabled",[`You have enabled experimental features: ${e}`,"Experimental features in Tailwind CSS are not covered by semver, may introduce breaking changes, and can change at any time."])}}var Pu,yi,je=C(()=>{l();hi();Oe();Pu={optimizeUniversalDefaults:!1,generalizedModifiers:!0,disableColorOpacityUtilitiesByDefault:!1,relativeContentPathsByDefault:!1},yi={future:["hoverOnlyWhenSupported","respectDefaultRingColorOpacity","disableColorOpacityUtilitiesByDefault","relativeContentPathsByDefault"],experimental:["optimizeUniversalDefaults","generalizedModifiers"]}});function qu(r){(()=>{if(r.purge||!r.content||!Array.isArray(r.content)&&!(typeof r.content=="object"&&r.content!==null))return!1;if(Array.isArray(r.content))return r.content.every(t=>typeof t=="string"?!0:!(typeof t?.raw!="string"||t?.extension&&typeof t?.extension!="string"));if(typeof r.content=="object"&&r.content!==null){if(Object.keys(r.content).some(t=>!["files","relative","extract","transform"].includes(t)))return!1;if(Array.isArray(r.content.files)){if(!r.content.files.every(t=>typeof t=="string"?!0:!(typeof t?.raw!="string"||t?.extension&&typeof t?.extension!="string")))return!1;if(typeof r.content.extract=="object"){for(let t of Object.values(r.content.extract))if(typeof t!="function")return!1}else if(!(r.content.extract===void 0||typeof r.content.extract=="function"))return!1;if(typeof r.content.transform=="object"){for(let t of Object.values(r.content.transform))if(typeof t!="function")return!1}else if(!(r.content.transform===void 0||typeof r.content.transform=="function"))return!1;if(typeof r.content.relative!="boolean"&&typeof r.content.relative!="undefined")return!1}return!0}return!1})()||F.warn("purge-deprecation",["The `purge`/`content` options have changed in Tailwind CSS v3.0.","Update your configuration file to eliminate this warning.","https://tailwindcss.com/docs/upgrade-guide#configure-content-sources"]),r.safelist=(()=>{let{content:t,purge:i,safelist:n}=r;return Array.isArray(n)?n:Array.isArray(t?.safelist)?t.safelist:Array.isArray(i?.safelist)?i.safelist:Array.isArray(i?.options?.safelist)?i.options.safelist:[]})(),r.blocklist=(()=>{let{blocklist:t}=r;if(Array.isArray(t)){if(t.every(i=>typeof i=="string"))return t;F.warn("blocklist-invalid",["The `blocklist` option must be an array of strings.","https://tailwindcss.com/docs/content-configuration#discarding-classes"])}return[]})(),typeof r.prefix=="function"?(F.warn("prefix-function",["As of Tailwind CSS v3.0, `prefix` cannot be a function.","Update `prefix` in your configuration to be a string to eliminate this warning.","https://tailwindcss.com/docs/upgrade-guide#prefix-cannot-be-a-function"]),r.prefix=""):r.prefix=r.prefix??"",r.content={relative:(()=>{let{content:t}=r;return t?.relative?t.relative:K(r,"relativeContentPathsByDefault")})(),files:(()=>{let{content:t,purge:i}=r;return Array.isArray(i)?i:Array.isArray(i?.content)?i.content:Array.isArray(t)?t:Array.isArray(t?.content)?t.content:Array.isArray(t?.files)?t.files:[]})(),extract:(()=>{let t=(()=>r.purge?.extract?r.purge.extract:r.content?.extract?r.content.extract:r.purge?.extract?.DEFAULT?r.purge.extract.DEFAULT:r.content?.extract?.DEFAULT?r.content.extract.DEFAULT:r.purge?.options?.extractors?r.purge.options.extractors:r.content?.options?.extractors?r.content.options.extractors:{})(),i={},n=(()=>{if(r.purge?.options?.defaultExtractor)return r.purge.options.defaultExtractor;if(r.content?.options?.defaultExtractor)return r.content.options.defaultExtractor})();if(n!==void 0&&(i.DEFAULT=n),typeof t=="function")i.DEFAULT=t;else if(Array.isArray(t))for(let{extensions:a,extractor:s}of t??[])for(let o of a)i[o]=s;else typeof t=="object"&&t!==null&&Object.assign(i,t);return i})(),transform:(()=>{let t=(()=>r.purge?.transform?r.purge.transform:r.content?.transform?r.content.transform:r.purge?.transform?.DEFAULT?r.purge.transform.DEFAULT:r.content?.transform?.DEFAULT?r.content.transform.DEFAULT:{})(),i={};return typeof t=="function"&&(i.DEFAULT=t),typeof t=="object"&&t!==null&&Object.assign(i,t),i})()};for(let t of r.content.files)if(typeof t=="string"&&/{([^,]*?)}/g.test(t)){F.warn("invalid-glob-braces",[`The glob pattern ${ns(t)} in your Tailwind CSS configuration is invalid.`,`Update it to ${ns(t.replace(/{([^,]*?)}/g,"$1"))} to silence this warning.`]);break}return r}var Ru=C(()=>{l();je();Oe()});function ie(r){if(Object.prototype.toString.call(r)!=="[object Object]")return!1;let e=Object.getPrototypeOf(r);return e===null||Object.getPrototypeOf(e)===null}var At=C(()=>{l()});function et(r){return Array.isArray(r)?r.map(e=>et(e)):typeof r=="object"&&r!==null?Object.fromEntries(Object.entries(r).map(([e,t])=>[e,et(t)])):r}var wi=C(()=>{l()});function wt(r){return r.replace(/\\,/g,"\\2c ")}var bi=C(()=>{l()});var ls,Mu=C(()=>{l();ls={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}});function ur(r,{loose:e=!1}={}){if(typeof r!="string")return null;if(r=r.trim(),r==="transparent")return{mode:"rgb",color:["0","0","0"],alpha:"0"};if(r in ls)return{mode:"rgb",color:ls[r].map(a=>a.toString())};let t=r.replace(jb,(a,s,o,u,c)=>["#",s,s,o,o,u,u,c?c+c:""].join("")).match(zb);if(t!==null)return{mode:"rgb",color:[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)].map(a=>a.toString()),alpha:t[4]?(parseInt(t[4],16)/255).toString():void 0};let i=r.match(Vb)??r.match(Ub);if(i===null)return null;let n=[i[2],i[3],i[4]].filter(Boolean).map(a=>a.toString());return n.length===2&&n[0].startsWith("var(")?{mode:i[1],color:[n[0]],alpha:n[1]}:!e&&n.length!==3||n.length<3&&!n.some(a=>/^var\(.*?\)$/.test(a))?null:{mode:i[1],color:n,alpha:i[5]?.toString?.()}}function us({mode:r,color:e,alpha:t}){let i=t!==void 0;return r==="rgba"||r==="hsla"?`${r}(${e.join(", ")}${i?`, ${t}`:""})`:`${r}(${e.join(" ")}${i?` / ${t}`:""})`}var zb,jb,tt,vi,Bu,rt,Vb,Ub,fs=C(()=>{l();Mu();zb=/^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i,jb=/^#([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i,tt=/(?:\d+|\d*\.\d+)%?/,vi=/(?:\s*,\s*|\s+)/,Bu=/\s*[,/]\s*/,rt=/var\(--(?:[^ )]*?)(?:,(?:[^ )]*?|var\(--[^ )]*?\)))?\)/,Vb=new RegExp(`^(rgba?)\\(\\s*(${tt.source}|${rt.source})(?:${vi.source}(${tt.source}|${rt.source}))?(?:${vi.source}(${tt.source}|${rt.source}))?(?:${Bu.source}(${tt.source}|${rt.source}))?\\s*\\)$`),Ub=new RegExp(`^(hsla?)\\(\\s*((?:${tt.source})(?:deg|rad|grad|turn)?|${rt.source})(?:${vi.source}(${tt.source}|${rt.source}))?(?:${vi.source}(${tt.source}|${rt.source}))?(?:${Bu.source}(${tt.source}|${rt.source}))?\\s*\\)$`)});function Ie(r,e,t){if(typeof r=="function")return r({opacityValue:e});let i=ur(r,{loose:!0});return i===null?t:us({...i,alpha:e})}function se({color:r,property:e,variable:t}){let i=[].concat(e);if(typeof r=="function")return{[t]:"1",...Object.fromEntries(i.map(a=>[a,r({opacityVariable:t,opacityValue:`var(${t})`})]))};let n=ur(r);return n===null?Object.fromEntries(i.map(a=>[a,r])):n.alpha!==void 0?Object.fromEntries(i.map(a=>[a,r])):{[t]:"1",...Object.fromEntries(i.map(a=>[a,us({...n,alpha:`var(${t})`})]))}}var fr=C(()=>{l();fs()});function ae(r,e){let t=[],i=[],n=0,a=!1;for(let s=0;s{l()});function xi(r){return ae(r,",").map(t=>{let i=t.trim(),n={raw:i},a=i.split(Gb),s=new Set;for(let o of a)Fu.lastIndex=0,!s.has("KEYWORD")&&Wb.has(o)?(n.keyword=o,s.add("KEYWORD")):Fu.test(o)?s.has("X")?s.has("Y")?s.has("BLUR")?s.has("SPREAD")||(n.spread=o,s.add("SPREAD")):(n.blur=o,s.add("BLUR")):(n.y=o,s.add("Y")):(n.x=o,s.add("X")):n.color?(n.unknown||(n.unknown=[]),n.unknown.push(o)):n.color=o;return n.valid=n.x!==void 0&&n.y!==void 0,n})}function Lu(r){return r.map(e=>e.valid?[e.keyword,e.x,e.y,e.blur,e.spread,e.color].filter(Boolean).join(" "):e.raw).join(", ")}var Wb,Gb,Fu,cs=C(()=>{l();_t();Wb=new Set(["inset","inherit","initial","revert","unset"]),Gb=/\ +(?![^(]*\))/g,Fu=/^-?(\d+|\.\d+)(.*?)$/g});function ps(r){return Hb.some(e=>new RegExp(`^${e}\\(.*\\)`).test(r))}function L(r,e=null,t=!0){let i=e&&Yb.has(e.property);return r.startsWith("--")&&!i?`var(${r})`:r.includes("url(")?r.split(/(url\(.*?\))/g).filter(Boolean).map(n=>/^url\(.*?\)$/.test(n)?n:L(n,e,!1)).join(""):(r=r.replace(/([^\\])_+/g,(n,a)=>a+" ".repeat(n.length-1)).replace(/^_/g," ").replace(/\\_/g,"_"),t&&(r=r.trim()),r=Qb(r),r)}function Qb(r){let e=["theme"],t=["min-content","max-content","fit-content","safe-area-inset-top","safe-area-inset-right","safe-area-inset-bottom","safe-area-inset-left","titlebar-area-x","titlebar-area-y","titlebar-area-width","titlebar-area-height","keyboard-inset-top","keyboard-inset-right","keyboard-inset-bottom","keyboard-inset-left","keyboard-inset-width","keyboard-inset-height","radial-gradient","linear-gradient","conic-gradient","repeating-radial-gradient","repeating-linear-gradient","repeating-conic-gradient"];return r.replace(/(calc|min|max|clamp)\(.+\)/g,i=>{let n="";function a(){let s=n.trimEnd();return s[s.length-1]}for(let s=0;si[s+p]===d)},u=function(f){let d=1/0;for(let m of f){let b=i.indexOf(m,s);b!==-1&&bo(f))){let f=t.find(d=>o(d));n+=f,s+=f.length-1}else e.some(f=>o(f))?n+=u([")"]):o("[")?n+=u(["]"]):["+","-","*","/"].includes(c)&&!["(","+","-","*","/",","].includes(a())?n+=` ${c} `:n+=c}return n.replace(/\s+/g," ")})}function ds(r){return r.startsWith("url(")}function hs(r){return!isNaN(Number(r))||ps(r)}function cr(r){return r.endsWith("%")&&hs(r.slice(0,-1))||ps(r)}function pr(r){return r==="0"||new RegExp(`^[+-]?[0-9]*.?[0-9]+(?:[eE][+-]?[0-9]+)?${Xb}$`).test(r)||ps(r)}function Nu(r){return Kb.has(r)}function $u(r){let e=xi(L(r));for(let t of e)if(!t.valid)return!1;return!0}function zu(r){let e=0;return ae(r,"_").every(i=>(i=L(i),i.startsWith("var(")?!0:ur(i,{loose:!0})!==null?(e++,!0):!1))?e>0:!1}function ju(r){let e=0;return ae(r,",").every(i=>(i=L(i),i.startsWith("var(")?!0:ds(i)||e0(i)||["element(","image(","cross-fade(","image-set("].some(n=>i.startsWith(n))?(e++,!0):!1))?e>0:!1}function e0(r){r=L(r);for(let e of Zb)if(r.startsWith(`${e}(`))return!0;return!1}function Vu(r){let e=0;return ae(r,"_").every(i=>(i=L(i),i.startsWith("var(")?!0:t0.has(i)||pr(i)||cr(i)?(e++,!0):!1))?e>0:!1}function Uu(r){let e=0;return ae(r,",").every(i=>(i=L(i),i.startsWith("var(")?!0:i.includes(" ")&&!/(['"])([^"']+)\1/g.test(i)||/^\d/g.test(i)?!1:(e++,!0)))?e>0:!1}function Wu(r){return r0.has(r)}function Gu(r){return i0.has(r)}function Hu(r){return n0.has(r)}var Hb,Yb,Jb,Xb,Kb,Zb,t0,r0,i0,n0,dr=C(()=>{l();fs();cs();_t();Hb=["min","max","clamp","calc"];Yb=new Set(["scroll-timeline-name","timeline-scope","view-timeline-name","font-palette","scroll-timeline","animation-timeline","view-timeline"]);Jb=["cm","mm","Q","in","pc","pt","px","em","ex","ch","rem","lh","rlh","vw","vh","vmin","vmax","vb","vi","svw","svh","lvw","lvh","dvw","dvh","cqw","cqh","cqi","cqb","cqmin","cqmax"],Xb=`(?:${Jb.join("|")})`;Kb=new Set(["thin","medium","thick"]);Zb=new Set(["conic-gradient","linear-gradient","radial-gradient","repeating-conic-gradient","repeating-linear-gradient","repeating-radial-gradient"]);t0=new Set(["center","top","right","bottom","left"]);r0=new Set(["serif","sans-serif","monospace","cursive","fantasy","system-ui","ui-serif","ui-sans-serif","ui-monospace","ui-rounded","math","emoji","fangsong"]);i0=new Set(["xx-small","x-small","small","medium","large","x-large","xx-large","xxx-large"]);n0=new Set(["larger","smaller"])});function Yu(r){let e=["cover","contain"];return ae(r,",").every(t=>{let i=ae(t,"_").filter(Boolean);return i.length===1&&e.includes(i[0])?!0:i.length!==1&&i.length!==2?!1:i.every(n=>pr(n)||cr(n)||n==="auto")})}var Qu=C(()=>{l();dr();_t()});function Ju(r,e){r.walkClasses(t=>{t.value=e(t.value),t.raws&&t.raws.value&&(t.raws.value=wt(t.raws.value))})}function Xu(r,e){if(!it(r))return;let t=r.slice(1,-1);if(!!e(t))return L(t)}function s0(r,e={},t){let i=e[r];if(i!==void 0)return Ke(i);if(it(r)){let n=Xu(r,t);return n===void 0?void 0:Ke(n)}}function ki(r,e={},{validate:t=()=>!0}={}){let i=e.values?.[r];return i!==void 0?i:e.supportsNegativeValues&&r.startsWith("-")?s0(r.slice(1),e.values,t):Xu(r,t)}function it(r){return r.startsWith("[")&&r.endsWith("]")}function Ku(r){let e=r.lastIndexOf("/"),t=r.lastIndexOf("[",e),i=r.indexOf("]",e);return r[e-1]==="]"||r[e+1]==="["||t!==-1&&i!==-1&&t")){let e=r;return({opacityValue:t=1})=>e.replace("",t)}return r}function Zu(r){return L(r.slice(1,-1))}function a0(r,e={},{tailwindConfig:t={}}={}){if(e.values?.[r]!==void 0)return Ot(e.values?.[r]);let[i,n]=Ku(r);if(n!==void 0){let a=e.values?.[i]??(it(i)?i.slice(1,-1):void 0);return a===void 0?void 0:(a=Ot(a),it(n)?Ie(a,Zu(n)):t.theme?.opacity?.[n]===void 0?void 0:Ie(a,t.theme.opacity[n]))}return ki(r,e,{validate:zu})}function o0(r,e={}){return e.values?.[r]}function me(r){return(e,t)=>ki(e,t,{validate:r})}function l0(r,e){let t=r.indexOf(e);return t===-1?[void 0,r]:[r.slice(0,t),r.slice(t+1)]}function gs(r,e,t,i){if(t.values&&e in t.values)for(let{type:a}of r??[]){let s=ms[a](e,t,{tailwindConfig:i});if(s!==void 0)return[s,a,null]}if(it(e)){let a=e.slice(1,-1),[s,o]=l0(a,":");if(!/^[\w-_]+$/g.test(s))o=a;else if(s!==void 0&&!ef.includes(s))return[];if(o.length>0&&ef.includes(s))return[ki(`[${o}]`,t),s,null]}let n=ys(r,e,t,i);for(let a of n)return a;return[]}function*ys(r,e,t,i){let n=K(i,"generalizedModifiers"),[a,s]=Ku(e);if(n&&t.modifiers!=null&&(t.modifiers==="any"||typeof t.modifiers=="object"&&(s&&it(s)||s in t.modifiers))||(a=e,s=void 0),s!==void 0&&a===""&&(a="DEFAULT"),s!==void 0&&typeof t.modifiers=="object"){let u=t.modifiers?.[s]??null;u!==null?s=u:it(s)&&(s=Zu(s))}for(let{type:u}of r??[]){let c=ms[u](a,t,{tailwindConfig:i});c!==void 0&&(yield[c,u,s??null])}}var ms,ef,hr=C(()=>{l();bi();fr();dr();di();Qu();je();ms={any:ki,color:a0,url:me(ds),image:me(ju),length:me(pr),percentage:me(cr),position:me(Vu),lookup:o0,"generic-name":me(Wu),"family-name":me(Uu),number:me(hs),"line-width":me(Nu),"absolute-size":me(Gu),"relative-size":me(Hu),shadow:me($u),size:me(Yu)},ef=Object.keys(ms)});function N(r){return typeof r=="function"?r({}):r}var ws=C(()=>{l()});function Et(r){return typeof r=="function"}function mr(r,...e){let t=e.pop();for(let i of e)for(let n in i){let a=t(r[n],i[n]);a===void 0?ie(r[n])&&ie(i[n])?r[n]=mr({},r[n],i[n],t):r[n]=i[n]:r[n]=a}return r}function u0(r,...e){return Et(r)?r(...e):r}function f0(r){return r.reduce((e,{extend:t})=>mr(e,t,(i,n)=>i===void 0?[n]:Array.isArray(i)?[n,...i]:[n,i]),{})}function c0(r){return{...r.reduce((e,t)=>os(e,t),{}),extend:f0(r)}}function tf(r,e){if(Array.isArray(r)&&ie(r[0]))return r.concat(e);if(Array.isArray(e)&&ie(e[0])&&ie(r))return[r,...e];if(Array.isArray(e))return e}function p0({extend:r,...e}){return mr(e,r,(t,i)=>!Et(t)&&!i.some(Et)?mr({},t,...i,tf):(n,a)=>mr({},...[t,...i].map(s=>u0(s,n,a)),tf))}function*d0(r){let e=Ze(r);if(e.length===0||(yield e,Array.isArray(r)))return;let t=/^(.*?)\s*\/\s*([^/]+)$/,i=r.match(t);if(i!==null){let[,n,a]=i,s=Ze(n);s.alpha=a,yield s}}function h0(r){let e=(t,i)=>{for(let n of d0(t)){let a=0,s=r;for(;s!=null&&a(t[i]=Et(r[i])?r[i](e,bs):r[i],t),{})}function rf(r){let e=[];return r.forEach(t=>{e=[...e,t];let i=t?.plugins??[];i.length!==0&&i.forEach(n=>{n.__isOptionsFunction&&(n=n()),e=[...e,...rf([n?.config??{}])]})}),e}function m0(r){return[...r].reduceRight((t,i)=>Et(i)?i({corePlugins:t}):Au(i,t),Su)}function g0(r){return[...r].reduceRight((t,i)=>[...t,...i],[])}function vs(r){let e=[...rf(r),{prefix:"",important:!1,separator:":"}];return qu(os({theme:h0(p0(c0(e.map(t=>t?.theme??{})))),corePlugins:m0(e.map(t=>t.corePlugins)),plugins:g0(r.map(t=>t?.plugins??[]))},...e))}var bs,nf=C(()=>{l();di();Cu();_u();mi();Tu();gi();Ru();At();wi();hr();fr();ws();bs={colors:ss,negative(r){return Object.keys(r).filter(e=>r[e]!=="0").reduce((e,t)=>{let i=Ke(r[t]);return i!==void 0&&(e[`-${t}`]=i),e},{})},breakpoints(r){return Object.keys(r).filter(e=>typeof r[e]=="string").reduce((e,t)=>({...e,[`screen-${t}`]:r[t]}),{})}}});var Si=v((i3,sf)=>{l();sf.exports={content:[],presets:[],darkMode:"media",theme:{accentColor:({theme:r})=>({...r("colors"),auto:"auto"}),animation:{none:"none",spin:"spin 1s linear infinite",ping:"ping 1s cubic-bezier(0, 0, 0.2, 1) infinite",pulse:"pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite",bounce:"bounce 1s infinite"},aria:{busy:'busy="true"',checked:'checked="true"',disabled:'disabled="true"',expanded:'expanded="true"',hidden:'hidden="true"',pressed:'pressed="true"',readonly:'readonly="true"',required:'required="true"',selected:'selected="true"'},aspectRatio:{auto:"auto",square:"1 / 1",video:"16 / 9"},backdropBlur:({theme:r})=>r("blur"),backdropBrightness:({theme:r})=>r("brightness"),backdropContrast:({theme:r})=>r("contrast"),backdropGrayscale:({theme:r})=>r("grayscale"),backdropHueRotate:({theme:r})=>r("hueRotate"),backdropInvert:({theme:r})=>r("invert"),backdropOpacity:({theme:r})=>r("opacity"),backdropSaturate:({theme:r})=>r("saturate"),backdropSepia:({theme:r})=>r("sepia"),backgroundColor:({theme:r})=>r("colors"),backgroundImage:{none:"none","gradient-to-t":"linear-gradient(to top, var(--tw-gradient-stops))","gradient-to-tr":"linear-gradient(to top right, var(--tw-gradient-stops))","gradient-to-r":"linear-gradient(to right, var(--tw-gradient-stops))","gradient-to-br":"linear-gradient(to bottom right, var(--tw-gradient-stops))","gradient-to-b":"linear-gradient(to bottom, var(--tw-gradient-stops))","gradient-to-bl":"linear-gradient(to bottom left, var(--tw-gradient-stops))","gradient-to-l":"linear-gradient(to left, var(--tw-gradient-stops))","gradient-to-tl":"linear-gradient(to top left, var(--tw-gradient-stops))"},backgroundOpacity:({theme:r})=>r("opacity"),backgroundPosition:{bottom:"bottom",center:"center",left:"left","left-bottom":"left bottom","left-top":"left top",right:"right","right-bottom":"right bottom","right-top":"right top",top:"top"},backgroundSize:{auto:"auto",cover:"cover",contain:"contain"},blur:{0:"0",none:"0",sm:"4px",DEFAULT:"8px",md:"12px",lg:"16px",xl:"24px","2xl":"40px","3xl":"64px"},borderColor:({theme:r})=>({...r("colors"),DEFAULT:r("colors.gray.200","currentColor")}),borderOpacity:({theme:r})=>r("opacity"),borderRadius:{none:"0px",sm:"0.125rem",DEFAULT:"0.25rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem","3xl":"1.5rem",full:"9999px"},borderSpacing:({theme:r})=>({...r("spacing")}),borderWidth:{DEFAULT:"1px",0:"0px",2:"2px",4:"4px",8:"8px"},boxShadow:{sm:"0 1px 2px 0 rgb(0 0 0 / 0.05)",DEFAULT:"0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",md:"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",lg:"0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",xl:"0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)","2xl":"0 25px 50px -12px rgb(0 0 0 / 0.25)",inner:"inset 0 2px 4px 0 rgb(0 0 0 / 0.05)",none:"none"},boxShadowColor:({theme:r})=>r("colors"),brightness:{0:"0",50:".5",75:".75",90:".9",95:".95",100:"1",105:"1.05",110:"1.1",125:"1.25",150:"1.5",200:"2"},caretColor:({theme:r})=>r("colors"),colors:({colors:r})=>({inherit:r.inherit,current:r.current,transparent:r.transparent,black:r.black,white:r.white,slate:r.slate,gray:r.gray,zinc:r.zinc,neutral:r.neutral,stone:r.stone,red:r.red,orange:r.orange,amber:r.amber,yellow:r.yellow,lime:r.lime,green:r.green,emerald:r.emerald,teal:r.teal,cyan:r.cyan,sky:r.sky,blue:r.blue,indigo:r.indigo,violet:r.violet,purple:r.purple,fuchsia:r.fuchsia,pink:r.pink,rose:r.rose}),columns:{auto:"auto",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12","3xs":"16rem","2xs":"18rem",xs:"20rem",sm:"24rem",md:"28rem",lg:"32rem",xl:"36rem","2xl":"42rem","3xl":"48rem","4xl":"56rem","5xl":"64rem","6xl":"72rem","7xl":"80rem"},container:{},content:{none:"none"},contrast:{0:"0",50:".5",75:".75",100:"1",125:"1.25",150:"1.5",200:"2"},cursor:{auto:"auto",default:"default",pointer:"pointer",wait:"wait",text:"text",move:"move",help:"help","not-allowed":"not-allowed",none:"none","context-menu":"context-menu",progress:"progress",cell:"cell",crosshair:"crosshair","vertical-text":"vertical-text",alias:"alias",copy:"copy","no-drop":"no-drop",grab:"grab",grabbing:"grabbing","all-scroll":"all-scroll","col-resize":"col-resize","row-resize":"row-resize","n-resize":"n-resize","e-resize":"e-resize","s-resize":"s-resize","w-resize":"w-resize","ne-resize":"ne-resize","nw-resize":"nw-resize","se-resize":"se-resize","sw-resize":"sw-resize","ew-resize":"ew-resize","ns-resize":"ns-resize","nesw-resize":"nesw-resize","nwse-resize":"nwse-resize","zoom-in":"zoom-in","zoom-out":"zoom-out"},divideColor:({theme:r})=>r("borderColor"),divideOpacity:({theme:r})=>r("borderOpacity"),divideWidth:({theme:r})=>r("borderWidth"),dropShadow:{sm:"0 1px 1px rgb(0 0 0 / 0.05)",DEFAULT:["0 1px 2px rgb(0 0 0 / 0.1)","0 1px 1px rgb(0 0 0 / 0.06)"],md:["0 4px 3px rgb(0 0 0 / 0.07)","0 2px 2px rgb(0 0 0 / 0.06)"],lg:["0 10px 8px rgb(0 0 0 / 0.04)","0 4px 3px rgb(0 0 0 / 0.1)"],xl:["0 20px 13px rgb(0 0 0 / 0.03)","0 8px 5px rgb(0 0 0 / 0.08)"],"2xl":"0 25px 25px rgb(0 0 0 / 0.15)",none:"0 0 #0000"},fill:({theme:r})=>({none:"none",...r("colors")}),flex:{1:"1 1 0%",auto:"1 1 auto",initial:"0 1 auto",none:"none"},flexBasis:({theme:r})=>({auto:"auto",...r("spacing"),"1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%","1/5":"20%","2/5":"40%","3/5":"60%","4/5":"80%","1/6":"16.666667%","2/6":"33.333333%","3/6":"50%","4/6":"66.666667%","5/6":"83.333333%","1/12":"8.333333%","2/12":"16.666667%","3/12":"25%","4/12":"33.333333%","5/12":"41.666667%","6/12":"50%","7/12":"58.333333%","8/12":"66.666667%","9/12":"75%","10/12":"83.333333%","11/12":"91.666667%",full:"100%"}),flexGrow:{0:"0",DEFAULT:"1"},flexShrink:{0:"0",DEFAULT:"1"},fontFamily:{sans:["ui-sans-serif","system-ui","sans-serif",'"Apple Color Emoji"','"Segoe UI Emoji"','"Segoe UI Symbol"','"Noto Color Emoji"'],serif:["ui-serif","Georgia","Cambria",'"Times New Roman"',"Times","serif"],mono:["ui-monospace","SFMono-Regular","Menlo","Monaco","Consolas",'"Liberation Mono"','"Courier New"',"monospace"]},fontSize:{xs:["0.75rem",{lineHeight:"1rem"}],sm:["0.875rem",{lineHeight:"1.25rem"}],base:["1rem",{lineHeight:"1.5rem"}],lg:["1.125rem",{lineHeight:"1.75rem"}],xl:["1.25rem",{lineHeight:"1.75rem"}],"2xl":["1.5rem",{lineHeight:"2rem"}],"3xl":["1.875rem",{lineHeight:"2.25rem"}],"4xl":["2.25rem",{lineHeight:"2.5rem"}],"5xl":["3rem",{lineHeight:"1"}],"6xl":["3.75rem",{lineHeight:"1"}],"7xl":["4.5rem",{lineHeight:"1"}],"8xl":["6rem",{lineHeight:"1"}],"9xl":["8rem",{lineHeight:"1"}]},fontWeight:{thin:"100",extralight:"200",light:"300",normal:"400",medium:"500",semibold:"600",bold:"700",extrabold:"800",black:"900"},gap:({theme:r})=>r("spacing"),gradientColorStops:({theme:r})=>r("colors"),gradientColorStopPositions:{"0%":"0%","5%":"5%","10%":"10%","15%":"15%","20%":"20%","25%":"25%","30%":"30%","35%":"35%","40%":"40%","45%":"45%","50%":"50%","55%":"55%","60%":"60%","65%":"65%","70%":"70%","75%":"75%","80%":"80%","85%":"85%","90%":"90%","95%":"95%","100%":"100%"},grayscale:{0:"0",DEFAULT:"100%"},gridAutoColumns:{auto:"auto",min:"min-content",max:"max-content",fr:"minmax(0, 1fr)"},gridAutoRows:{auto:"auto",min:"min-content",max:"max-content",fr:"minmax(0, 1fr)"},gridColumn:{auto:"auto","span-1":"span 1 / span 1","span-2":"span 2 / span 2","span-3":"span 3 / span 3","span-4":"span 4 / span 4","span-5":"span 5 / span 5","span-6":"span 6 / span 6","span-7":"span 7 / span 7","span-8":"span 8 / span 8","span-9":"span 9 / span 9","span-10":"span 10 / span 10","span-11":"span 11 / span 11","span-12":"span 12 / span 12","span-full":"1 / -1"},gridColumnEnd:{auto:"auto",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12",13:"13"},gridColumnStart:{auto:"auto",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12",13:"13"},gridRow:{auto:"auto","span-1":"span 1 / span 1","span-2":"span 2 / span 2","span-3":"span 3 / span 3","span-4":"span 4 / span 4","span-5":"span 5 / span 5","span-6":"span 6 / span 6","span-7":"span 7 / span 7","span-8":"span 8 / span 8","span-9":"span 9 / span 9","span-10":"span 10 / span 10","span-11":"span 11 / span 11","span-12":"span 12 / span 12","span-full":"1 / -1"},gridRowEnd:{auto:"auto",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12",13:"13"},gridRowStart:{auto:"auto",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12",13:"13"},gridTemplateColumns:{none:"none",subgrid:"subgrid",1:"repeat(1, minmax(0, 1fr))",2:"repeat(2, minmax(0, 1fr))",3:"repeat(3, minmax(0, 1fr))",4:"repeat(4, minmax(0, 1fr))",5:"repeat(5, minmax(0, 1fr))",6:"repeat(6, minmax(0, 1fr))",7:"repeat(7, minmax(0, 1fr))",8:"repeat(8, minmax(0, 1fr))",9:"repeat(9, minmax(0, 1fr))",10:"repeat(10, minmax(0, 1fr))",11:"repeat(11, minmax(0, 1fr))",12:"repeat(12, minmax(0, 1fr))"},gridTemplateRows:{none:"none",subgrid:"subgrid",1:"repeat(1, minmax(0, 1fr))",2:"repeat(2, minmax(0, 1fr))",3:"repeat(3, minmax(0, 1fr))",4:"repeat(4, minmax(0, 1fr))",5:"repeat(5, minmax(0, 1fr))",6:"repeat(6, minmax(0, 1fr))",7:"repeat(7, minmax(0, 1fr))",8:"repeat(8, minmax(0, 1fr))",9:"repeat(9, minmax(0, 1fr))",10:"repeat(10, minmax(0, 1fr))",11:"repeat(11, minmax(0, 1fr))",12:"repeat(12, minmax(0, 1fr))"},height:({theme:r})=>({auto:"auto",...r("spacing"),"1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%","1/5":"20%","2/5":"40%","3/5":"60%","4/5":"80%","1/6":"16.666667%","2/6":"33.333333%","3/6":"50%","4/6":"66.666667%","5/6":"83.333333%",full:"100%",screen:"100vh",svh:"100svh",lvh:"100lvh",dvh:"100dvh",min:"min-content",max:"max-content",fit:"fit-content"}),hueRotate:{0:"0deg",15:"15deg",30:"30deg",60:"60deg",90:"90deg",180:"180deg"},inset:({theme:r})=>({auto:"auto",...r("spacing"),"1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%",full:"100%"}),invert:{0:"0",DEFAULT:"100%"},keyframes:{spin:{to:{transform:"rotate(360deg)"}},ping:{"75%, 100%":{transform:"scale(2)",opacity:"0"}},pulse:{"50%":{opacity:".5"}},bounce:{"0%, 100%":{transform:"translateY(-25%)",animationTimingFunction:"cubic-bezier(0.8,0,1,1)"},"50%":{transform:"none",animationTimingFunction:"cubic-bezier(0,0,0.2,1)"}}},letterSpacing:{tighter:"-0.05em",tight:"-0.025em",normal:"0em",wide:"0.025em",wider:"0.05em",widest:"0.1em"},lineHeight:{none:"1",tight:"1.25",snug:"1.375",normal:"1.5",relaxed:"1.625",loose:"2",3:".75rem",4:"1rem",5:"1.25rem",6:"1.5rem",7:"1.75rem",8:"2rem",9:"2.25rem",10:"2.5rem"},listStyleType:{none:"none",disc:"disc",decimal:"decimal"},listStyleImage:{none:"none"},margin:({theme:r})=>({auto:"auto",...r("spacing")}),lineClamp:{1:"1",2:"2",3:"3",4:"4",5:"5",6:"6"},maxHeight:({theme:r})=>({...r("spacing"),none:"none",full:"100%",screen:"100vh",svh:"100svh",lvh:"100lvh",dvh:"100dvh",min:"min-content",max:"max-content",fit:"fit-content"}),maxWidth:({theme:r,breakpoints:e})=>({...r("spacing"),none:"none",xs:"20rem",sm:"24rem",md:"28rem",lg:"32rem",xl:"36rem","2xl":"42rem","3xl":"48rem","4xl":"56rem","5xl":"64rem","6xl":"72rem","7xl":"80rem",full:"100%",min:"min-content",max:"max-content",fit:"fit-content",prose:"65ch",...e(r("screens"))}),minHeight:({theme:r})=>({...r("spacing"),full:"100%",screen:"100vh",svh:"100svh",lvh:"100lvh",dvh:"100dvh",min:"min-content",max:"max-content",fit:"fit-content"}),minWidth:({theme:r})=>({...r("spacing"),full:"100%",min:"min-content",max:"max-content",fit:"fit-content"}),objectPosition:{bottom:"bottom",center:"center",left:"left","left-bottom":"left bottom","left-top":"left top",right:"right","right-bottom":"right bottom","right-top":"right top",top:"top"},opacity:{0:"0",5:"0.05",10:"0.1",15:"0.15",20:"0.2",25:"0.25",30:"0.3",35:"0.35",40:"0.4",45:"0.45",50:"0.5",55:"0.55",60:"0.6",65:"0.65",70:"0.7",75:"0.75",80:"0.8",85:"0.85",90:"0.9",95:"0.95",100:"1"},order:{first:"-9999",last:"9999",none:"0",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12"},outlineColor:({theme:r})=>r("colors"),outlineOffset:{0:"0px",1:"1px",2:"2px",4:"4px",8:"8px"},outlineWidth:{0:"0px",1:"1px",2:"2px",4:"4px",8:"8px"},padding:({theme:r})=>r("spacing"),placeholderColor:({theme:r})=>r("colors"),placeholderOpacity:({theme:r})=>r("opacity"),ringColor:({theme:r})=>({DEFAULT:r("colors.blue.500","#3b82f6"),...r("colors")}),ringOffsetColor:({theme:r})=>r("colors"),ringOffsetWidth:{0:"0px",1:"1px",2:"2px",4:"4px",8:"8px"},ringOpacity:({theme:r})=>({DEFAULT:"0.5",...r("opacity")}),ringWidth:{DEFAULT:"3px",0:"0px",1:"1px",2:"2px",4:"4px",8:"8px"},rotate:{0:"0deg",1:"1deg",2:"2deg",3:"3deg",6:"6deg",12:"12deg",45:"45deg",90:"90deg",180:"180deg"},saturate:{0:"0",50:".5",100:"1",150:"1.5",200:"2"},scale:{0:"0",50:".5",75:".75",90:".9",95:".95",100:"1",105:"1.05",110:"1.1",125:"1.25",150:"1.5"},screens:{sm:"640px",md:"768px",lg:"1024px",xl:"1280px","2xl":"1536px"},scrollMargin:({theme:r})=>({...r("spacing")}),scrollPadding:({theme:r})=>r("spacing"),sepia:{0:"0",DEFAULT:"100%"},skew:{0:"0deg",1:"1deg",2:"2deg",3:"3deg",6:"6deg",12:"12deg"},space:({theme:r})=>({...r("spacing")}),spacing:{px:"1px",0:"0px",.5:"0.125rem",1:"0.25rem",1.5:"0.375rem",2:"0.5rem",2.5:"0.625rem",3:"0.75rem",3.5:"0.875rem",4:"1rem",5:"1.25rem",6:"1.5rem",7:"1.75rem",8:"2rem",9:"2.25rem",10:"2.5rem",11:"2.75rem",12:"3rem",14:"3.5rem",16:"4rem",20:"5rem",24:"6rem",28:"7rem",32:"8rem",36:"9rem",40:"10rem",44:"11rem",48:"12rem",52:"13rem",56:"14rem",60:"15rem",64:"16rem",72:"18rem",80:"20rem",96:"24rem"},stroke:({theme:r})=>({none:"none",...r("colors")}),strokeWidth:{0:"0",1:"1",2:"2"},supports:{},data:{},textColor:({theme:r})=>r("colors"),textDecorationColor:({theme:r})=>r("colors"),textDecorationThickness:{auto:"auto","from-font":"from-font",0:"0px",1:"1px",2:"2px",4:"4px",8:"8px"},textIndent:({theme:r})=>({...r("spacing")}),textOpacity:({theme:r})=>r("opacity"),textUnderlineOffset:{auto:"auto",0:"0px",1:"1px",2:"2px",4:"4px",8:"8px"},transformOrigin:{center:"center",top:"top","top-right":"top right",right:"right","bottom-right":"bottom right",bottom:"bottom","bottom-left":"bottom left",left:"left","top-left":"top left"},transitionDelay:{0:"0s",75:"75ms",100:"100ms",150:"150ms",200:"200ms",300:"300ms",500:"500ms",700:"700ms",1e3:"1000ms"},transitionDuration:{DEFAULT:"150ms",0:"0s",75:"75ms",100:"100ms",150:"150ms",200:"200ms",300:"300ms",500:"500ms",700:"700ms",1e3:"1000ms"},transitionProperty:{none:"none",all:"all",DEFAULT:"color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter",colors:"color, background-color, border-color, text-decoration-color, fill, stroke",opacity:"opacity",shadow:"box-shadow",transform:"transform"},transitionTimingFunction:{DEFAULT:"cubic-bezier(0.4, 0, 0.2, 1)",linear:"linear",in:"cubic-bezier(0.4, 0, 1, 1)",out:"cubic-bezier(0, 0, 0.2, 1)","in-out":"cubic-bezier(0.4, 0, 0.2, 1)"},translate:({theme:r})=>({...r("spacing"),"1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%",full:"100%"}),size:({theme:r})=>({auto:"auto",...r("spacing"),"1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%","1/5":"20%","2/5":"40%","3/5":"60%","4/5":"80%","1/6":"16.666667%","2/6":"33.333333%","3/6":"50%","4/6":"66.666667%","5/6":"83.333333%","1/12":"8.333333%","2/12":"16.666667%","3/12":"25%","4/12":"33.333333%","5/12":"41.666667%","6/12":"50%","7/12":"58.333333%","8/12":"66.666667%","9/12":"75%","10/12":"83.333333%","11/12":"91.666667%",full:"100%",min:"min-content",max:"max-content",fit:"fit-content"}),width:({theme:r})=>({auto:"auto",...r("spacing"),"1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%","1/5":"20%","2/5":"40%","3/5":"60%","4/5":"80%","1/6":"16.666667%","2/6":"33.333333%","3/6":"50%","4/6":"66.666667%","5/6":"83.333333%","1/12":"8.333333%","2/12":"16.666667%","3/12":"25%","4/12":"33.333333%","5/12":"41.666667%","6/12":"50%","7/12":"58.333333%","8/12":"66.666667%","9/12":"75%","10/12":"83.333333%","11/12":"91.666667%",full:"100%",screen:"100vw",svw:"100svw",lvw:"100lvw",dvw:"100dvw",min:"min-content",max:"max-content",fit:"fit-content"}),willChange:{auto:"auto",scroll:"scroll-position",contents:"contents",transform:"transform"},zIndex:{auto:"auto",0:"0",10:"10",20:"20",30:"30",40:"40",50:"50"}},plugins:[]}});function Ci(r){let e=(r?.presets??[af.default]).slice().reverse().flatMap(n=>Ci(n instanceof Function?n():n)),t={respectDefaultRingColorOpacity:{theme:{ringColor:({theme:n})=>({DEFAULT:"#3b82f67f",...n("colors")})}},disableColorOpacityUtilitiesByDefault:{corePlugins:{backgroundOpacity:!1,borderOpacity:!1,divideOpacity:!1,placeholderOpacity:!1,ringOpacity:!1,textOpacity:!1}}},i=Object.keys(t).filter(n=>K(r,n)).map(n=>t[n]);return[r,...i,...e]}var af,of=C(()=>{l();af=X(Si());je()});var lf={};Ae(lf,{default:()=>gr});function gr(...r){let[,...e]=Ci(r[0]);return vs([...r,...e])}var xs=C(()=>{l();nf();of()});var uf={};Ae(uf,{default:()=>Z});var Z,bt=C(()=>{l();Z={resolve:r=>r,extname:r=>"."+r.split(".").pop()}});function Ai(r){return typeof r=="object"&&r!==null}function w0(r){return Object.keys(r).length===0}function ff(r){return typeof r=="string"||r instanceof String}function ks(r){return Ai(r)&&r.config===void 0&&!w0(r)?null:Ai(r)&&r.config!==void 0&&ff(r.config)?Z.resolve(r.config):Ai(r)&&r.config!==void 0&&Ai(r.config)?null:ff(r)?Z.resolve(r):b0()}function b0(){for(let r of y0)try{let e=Z.resolve(r);return te.accessSync(e),e}catch(e){}return null}var y0,cf=C(()=>{l();ze();bt();y0=["./tailwind.config.js","./tailwind.config.cjs","./tailwind.config.mjs","./tailwind.config.ts"]});var pf={};Ae(pf,{default:()=>Ss});var Ss,Cs=C(()=>{l();Ss={parse:r=>({href:r})}});var As=v(()=>{l()});var _i=v((d3,mf)=>{l();"use strict";var df=(hi(),Ou),hf=As(),Tt=class extends Error{constructor(e,t,i,n,a,s){super(e);this.name="CssSyntaxError",this.reason=e,a&&(this.file=a),n&&(this.source=n),s&&(this.plugin=s),typeof t!="undefined"&&typeof i!="undefined"&&(typeof t=="number"?(this.line=t,this.column=i):(this.line=t.line,this.column=t.column,this.endLine=i.line,this.endColumn=i.column)),this.setMessage(),Error.captureStackTrace&&Error.captureStackTrace(this,Tt)}setMessage(){this.message=this.plugin?this.plugin+": ":"",this.message+=this.file?this.file:"",typeof this.line!="undefined"&&(this.message+=":"+this.line+":"+this.column),this.message+=": "+this.reason}showSourceCode(e){if(!this.source)return"";let t=this.source;e==null&&(e=df.isColorSupported),hf&&e&&(t=hf(t));let i=t.split(/\r?\n/),n=Math.max(this.line-3,0),a=Math.min(this.line+2,i.length),s=String(a).length,o,u;if(e){let{bold:c,red:f,gray:d}=df.createColors(!0);o=p=>c(f(p)),u=p=>d(p)}else o=u=c=>c;return i.slice(n,a).map((c,f)=>{let d=n+1+f,p=" "+(" "+d).slice(-s)+" | ";if(d===this.line){let m=u(p.replace(/\d/g," "))+c.slice(0,this.column-1).replace(/[^\t]/g," ");return o(">")+u(p)+c+` - `+m+o("^")}return" "+u(p)+c}).join(` -`)}toString(){let e=this.showSourceCode();return e&&(e=` +(() => { + var Rb = Object.create; + var ci = Object.defineProperty; + var Mb = Object.getOwnPropertyDescriptor; + var Bb = Object.getOwnPropertyNames; + var Fb = Object.getPrototypeOf, + Lb = Object.prototype.hasOwnProperty; + var gu = (r) => ci(r, "__esModule", { value: !0 }); + var yu = (r) => { + if (typeof require != "undefined") return require(r); + throw new Error('Dynamic require of "' + r + '" is not supported'); + }; + var C = (r, e) => () => (r && (e = r((r = 0))), e); + var v = (r, e) => () => (e || r((e = { exports: {} }).exports, e), e.exports), + Ae = (r, e) => { + gu(r); + for (var t in e) ci(r, t, { get: e[t], enumerable: !0 }); + }, + Nb = (r, e, t) => { + if ((e && typeof e == "object") || typeof e == "function") + for (let i of Bb(e)) + !Lb.call(r, i) && + i !== "default" && + ci(r, i, { get: () => e[i], enumerable: !(t = Mb(e, i)) || t.enumerable }); + return r; + }, + X = (r) => + Nb( + gu( + ci( + r != null ? Rb(Fb(r)) : {}, + "default", + r && r.__esModule && "default" in r + ? { get: () => r.default, enumerable: !0 } + : { value: r, enumerable: !0 } + ) + ), + r + ); + var h, + l = C(() => { + h = { platform: "", env: {}, versions: { node: "14.17.6" } }; + }); + var $b, + te, + ze = C(() => { + l(); + (($b = 0), + (te = { + readFileSync: (r) => self[r] || "", + statSync: () => ({ mtimeMs: $b++ }), + promises: { readFile: (r) => Promise.resolve(self[r] || "") }, + })); + }); + var rs = v((eE, bu) => { + l(); + ("use strict"); + var wu = class { + constructor(e = {}) { + if (!(e.maxSize && e.maxSize > 0)) throw new TypeError("`maxSize` must be a number greater than 0"); + if (typeof e.maxAge == "number" && e.maxAge === 0) + throw new TypeError("`maxAge` must be a number greater than 0"); + ((this.maxSize = e.maxSize), + (this.maxAge = e.maxAge || 1 / 0), + (this.onEviction = e.onEviction), + (this.cache = new Map()), + (this.oldCache = new Map()), + (this._size = 0)); + } + _emitEvictions(e) { + if (typeof this.onEviction == "function") for (let [t, i] of e) this.onEviction(t, i.value); + } + _deleteIfExpired(e, t) { + return typeof t.expiry == "number" && t.expiry <= Date.now() + ? (typeof this.onEviction == "function" && this.onEviction(e, t.value), this.delete(e)) + : !1; + } + _getOrDeleteIfExpired(e, t) { + if (this._deleteIfExpired(e, t) === !1) return t.value; + } + _getItemValue(e, t) { + return t.expiry ? this._getOrDeleteIfExpired(e, t) : t.value; + } + _peek(e, t) { + let i = t.get(e); + return this._getItemValue(e, i); + } + _set(e, t) { + (this.cache.set(e, t), + this._size++, + this._size >= this.maxSize && + ((this._size = 0), + this._emitEvictions(this.oldCache), + (this.oldCache = this.cache), + (this.cache = new Map()))); + } + _moveToRecent(e, t) { + (this.oldCache.delete(e), this._set(e, t)); + } + *_entriesAscending() { + for (let e of this.oldCache) { + let [t, i] = e; + this.cache.has(t) || (this._deleteIfExpired(t, i) === !1 && (yield e)); + } + for (let e of this.cache) { + let [t, i] = e; + this._deleteIfExpired(t, i) === !1 && (yield e); + } + } + get(e) { + if (this.cache.has(e)) { + let t = this.cache.get(e); + return this._getItemValue(e, t); + } + if (this.oldCache.has(e)) { + let t = this.oldCache.get(e); + if (this._deleteIfExpired(e, t) === !1) return (this._moveToRecent(e, t), t.value); + } + } + set(e, t, { maxAge: i = this.maxAge === 1 / 0 ? void 0 : Date.now() + this.maxAge } = {}) { + this.cache.has(e) ? this.cache.set(e, { value: t, maxAge: i }) : this._set(e, { value: t, expiry: i }); + } + has(e) { + return this.cache.has(e) + ? !this._deleteIfExpired(e, this.cache.get(e)) + : this.oldCache.has(e) + ? !this._deleteIfExpired(e, this.oldCache.get(e)) + : !1; + } + peek(e) { + if (this.cache.has(e)) return this._peek(e, this.cache); + if (this.oldCache.has(e)) return this._peek(e, this.oldCache); + } + delete(e) { + let t = this.cache.delete(e); + return (t && this._size--, this.oldCache.delete(e) || t); + } + clear() { + (this.cache.clear(), this.oldCache.clear(), (this._size = 0)); + } + resize(e) { + if (!(e && e > 0)) throw new TypeError("`maxSize` must be a number greater than 0"); + let t = [...this._entriesAscending()], + i = t.length - e; + (i < 0 + ? ((this.cache = new Map(t)), (this.oldCache = new Map()), (this._size = t.length)) + : (i > 0 && this._emitEvictions(t.slice(0, i)), + (this.oldCache = new Map(t.slice(i))), + (this.cache = new Map()), + (this._size = 0)), + (this.maxSize = e)); + } + *keys() { + for (let [e] of this) yield e; + } + *values() { + for (let [, e] of this) yield e; + } + *[Symbol.iterator]() { + for (let e of this.cache) { + let [t, i] = e; + this._deleteIfExpired(t, i) === !1 && (yield [t, i.value]); + } + for (let e of this.oldCache) { + let [t, i] = e; + this.cache.has(t) || (this._deleteIfExpired(t, i) === !1 && (yield [t, i.value])); + } + } + *entriesDescending() { + let e = [...this.cache]; + for (let t = e.length - 1; t >= 0; --t) { + let i = e[t], + [n, a] = i; + this._deleteIfExpired(n, a) === !1 && (yield [n, a.value]); + } + e = [...this.oldCache]; + for (let t = e.length - 1; t >= 0; --t) { + let i = e[t], + [n, a] = i; + this.cache.has(n) || (this._deleteIfExpired(n, a) === !1 && (yield [n, a.value])); + } + } + *entriesAscending() { + for (let [e, t] of this._entriesAscending()) yield [e, t.value]; + } + get size() { + if (!this._size) return this.oldCache.size; + let e = 0; + for (let t of this.oldCache.keys()) this.cache.has(t) || e++; + return Math.min(this._size + e, this.maxSize); + } + }; + bu.exports = wu; + }); + var vu, + xu = C(() => { + l(); + vu = (r) => r && r._hash; + }); + function pi(r) { + return vu(r, { ignoreUnknown: !0 }); + } + var ku = C(() => { + l(); + xu(); + }); + function Ke(r) { + if (((r = `${r}`), r === "0")) return "0"; + if (/^[+-]?(\d+|\d*\.\d+)(e[+-]?\d+)?(%|\w+)?$/.test(r)) + return r.replace(/^[+-]?/, (t) => (t === "-" ? "" : "-")); + let e = ["var", "calc", "min", "max", "clamp"]; + for (let t of e) if (r.includes(`${t}(`)) return `calc(${r} * -1)`; + } + var di = C(() => { + l(); + }); + var Su, + Cu = C(() => { + l(); + Su = [ + "preflight", + "container", + "accessibility", + "pointerEvents", + "visibility", + "position", + "inset", + "isolation", + "zIndex", + "order", + "gridColumn", + "gridColumnStart", + "gridColumnEnd", + "gridRow", + "gridRowStart", + "gridRowEnd", + "float", + "clear", + "margin", + "boxSizing", + "lineClamp", + "display", + "aspectRatio", + "size", + "height", + "maxHeight", + "minHeight", + "width", + "minWidth", + "maxWidth", + "flex", + "flexShrink", + "flexGrow", + "flexBasis", + "tableLayout", + "captionSide", + "borderCollapse", + "borderSpacing", + "transformOrigin", + "translate", + "rotate", + "skew", + "scale", + "transform", + "animation", + "cursor", + "touchAction", + "userSelect", + "resize", + "scrollSnapType", + "scrollSnapAlign", + "scrollSnapStop", + "scrollMargin", + "scrollPadding", + "listStylePosition", + "listStyleType", + "listStyleImage", + "appearance", + "columns", + "breakBefore", + "breakInside", + "breakAfter", + "gridAutoColumns", + "gridAutoFlow", + "gridAutoRows", + "gridTemplateColumns", + "gridTemplateRows", + "flexDirection", + "flexWrap", + "placeContent", + "placeItems", + "alignContent", + "alignItems", + "justifyContent", + "justifyItems", + "gap", + "space", + "divideWidth", + "divideStyle", + "divideColor", + "divideOpacity", + "placeSelf", + "alignSelf", + "justifySelf", + "overflow", + "overscrollBehavior", + "scrollBehavior", + "textOverflow", + "hyphens", + "whitespace", + "textWrap", + "wordBreak", + "borderRadius", + "borderWidth", + "borderStyle", + "borderColor", + "borderOpacity", + "backgroundColor", + "backgroundOpacity", + "backgroundImage", + "gradientColorStops", + "boxDecorationBreak", + "backgroundSize", + "backgroundAttachment", + "backgroundClip", + "backgroundPosition", + "backgroundRepeat", + "backgroundOrigin", + "fill", + "stroke", + "strokeWidth", + "objectFit", + "objectPosition", + "padding", + "textAlign", + "textIndent", + "verticalAlign", + "fontFamily", + "fontSize", + "fontWeight", + "textTransform", + "fontStyle", + "fontVariantNumeric", + "lineHeight", + "letterSpacing", + "textColor", + "textOpacity", + "textDecoration", + "textDecorationColor", + "textDecorationStyle", + "textDecorationThickness", + "textUnderlineOffset", + "fontSmoothing", + "placeholderColor", + "placeholderOpacity", + "caretColor", + "accentColor", + "opacity", + "backgroundBlendMode", + "mixBlendMode", + "boxShadow", + "boxShadowColor", + "outlineStyle", + "outlineWidth", + "outlineOffset", + "outlineColor", + "ringWidth", + "ringColor", + "ringOpacity", + "ringOffsetWidth", + "ringOffsetColor", + "blur", + "brightness", + "contrast", + "dropShadow", + "grayscale", + "hueRotate", + "invert", + "saturate", + "sepia", + "filter", + "backdropBlur", + "backdropBrightness", + "backdropContrast", + "backdropGrayscale", + "backdropHueRotate", + "backdropInvert", + "backdropOpacity", + "backdropSaturate", + "backdropSepia", + "backdropFilter", + "transitionProperty", + "transitionDelay", + "transitionDuration", + "transitionTimingFunction", + "willChange", + "contain", + "content", + "forcedColorAdjust", + ]; + }); + function Au(r, e) { + return r === void 0 + ? e + : Array.isArray(r) + ? r + : [ + ...new Set( + e.filter((i) => r !== !1 && r[i] !== !1).concat(Object.keys(r).filter((i) => r[i] !== !1)) + ), + ]; + } + var _u = C(() => { + l(); + }); + var Ou = {}; + Ae(Ou, { default: () => _e }); + var _e, + hi = C(() => { + l(); + _e = new Proxy({}, { get: () => String }); + }); + function is(r, e, t) { + (typeof h != "undefined" && h.env.JEST_WORKER_ID) || + (t && Eu.has(t)) || + (t && Eu.add(t), console.warn(""), e.forEach((i) => console.warn(r, "-", i))); + } + function ns(r) { + return _e.dim(r); + } + var Eu, + F, + Oe = C(() => { + l(); + hi(); + Eu = new Set(); + F = { + info(r, e) { + is(_e.bold(_e.cyan("info")), ...(Array.isArray(r) ? [r] : [e, r])); + }, + warn(r, e) { + ["content-problems"].includes(r) || + is(_e.bold(_e.yellow("warn")), ...(Array.isArray(r) ? [r] : [e, r])); + }, + risk(r, e) { + is(_e.bold(_e.magenta("risk")), ...(Array.isArray(r) ? [r] : [e, r])); + }, + }; + }); + var as = {}; + Ae(as, { default: () => ss }); + function lr({ version: r, from: e, to: t }) { + F.warn(`${e}-color-renamed`, [ + `As of Tailwind CSS ${r}, \`${e}\` has been renamed to \`${t}\`.`, + "Update your configuration file to silence this warning.", + ]); + } + var ss, + mi = C(() => { + l(); + Oe(); + ss = { + inherit: "inherit", + current: "currentColor", + transparent: "transparent", + black: "#000", + white: "#fff", + slate: { + 50: "#f8fafc", + 100: "#f1f5f9", + 200: "#e2e8f0", + 300: "#cbd5e1", + 400: "#94a3b8", + 500: "#64748b", + 600: "#475569", + 700: "#334155", + 800: "#1e293b", + 900: "#0f172a", + 950: "#020617", + }, + gray: { + 50: "#f9fafb", + 100: "#f3f4f6", + 200: "#e5e7eb", + 300: "#d1d5db", + 400: "#9ca3af", + 500: "#6b7280", + 600: "#4b5563", + 700: "#374151", + 800: "#1f2937", + 900: "#111827", + 950: "#030712", + }, + zinc: { + 50: "#fafafa", + 100: "#f4f4f5", + 200: "#e4e4e7", + 300: "#d4d4d8", + 400: "#a1a1aa", + 500: "#71717a", + 600: "#52525b", + 700: "#3f3f46", + 800: "#27272a", + 900: "#18181b", + 950: "#09090b", + }, + neutral: { + 50: "#fafafa", + 100: "#f5f5f5", + 200: "#e5e5e5", + 300: "#d4d4d4", + 400: "#a3a3a3", + 500: "#737373", + 600: "#525252", + 700: "#404040", + 800: "#262626", + 900: "#171717", + 950: "#0a0a0a", + }, + stone: { + 50: "#fafaf9", + 100: "#f5f5f4", + 200: "#e7e5e4", + 300: "#d6d3d1", + 400: "#a8a29e", + 500: "#78716c", + 600: "#57534e", + 700: "#44403c", + 800: "#292524", + 900: "#1c1917", + 950: "#0c0a09", + }, + red: { + 50: "#fef2f2", + 100: "#fee2e2", + 200: "#fecaca", + 300: "#fca5a5", + 400: "#f87171", + 500: "#ef4444", + 600: "#dc2626", + 700: "#b91c1c", + 800: "#991b1b", + 900: "#7f1d1d", + 950: "#450a0a", + }, + orange: { + 50: "#fff7ed", + 100: "#ffedd5", + 200: "#fed7aa", + 300: "#fdba74", + 400: "#fb923c", + 500: "#f97316", + 600: "#ea580c", + 700: "#c2410c", + 800: "#9a3412", + 900: "#7c2d12", + 950: "#431407", + }, + amber: { + 50: "#fffbeb", + 100: "#fef3c7", + 200: "#fde68a", + 300: "#fcd34d", + 400: "#fbbf24", + 500: "#f59e0b", + 600: "#d97706", + 700: "#b45309", + 800: "#92400e", + 900: "#78350f", + 950: "#451a03", + }, + yellow: { + 50: "#fefce8", + 100: "#fef9c3", + 200: "#fef08a", + 300: "#fde047", + 400: "#facc15", + 500: "#eab308", + 600: "#ca8a04", + 700: "#a16207", + 800: "#854d0e", + 900: "#713f12", + 950: "#422006", + }, + lime: { + 50: "#f7fee7", + 100: "#ecfccb", + 200: "#d9f99d", + 300: "#bef264", + 400: "#a3e635", + 500: "#84cc16", + 600: "#65a30d", + 700: "#4d7c0f", + 800: "#3f6212", + 900: "#365314", + 950: "#1a2e05", + }, + green: { + 50: "#f0fdf4", + 100: "#dcfce7", + 200: "#bbf7d0", + 300: "#86efac", + 400: "#4ade80", + 500: "#22c55e", + 600: "#16a34a", + 700: "#15803d", + 800: "#166534", + 900: "#14532d", + 950: "#052e16", + }, + emerald: { + 50: "#ecfdf5", + 100: "#d1fae5", + 200: "#a7f3d0", + 300: "#6ee7b7", + 400: "#34d399", + 500: "#10b981", + 600: "#059669", + 700: "#047857", + 800: "#065f46", + 900: "#064e3b", + 950: "#022c22", + }, + teal: { + 50: "#f0fdfa", + 100: "#ccfbf1", + 200: "#99f6e4", + 300: "#5eead4", + 400: "#2dd4bf", + 500: "#14b8a6", + 600: "#0d9488", + 700: "#0f766e", + 800: "#115e59", + 900: "#134e4a", + 950: "#042f2e", + }, + cyan: { + 50: "#ecfeff", + 100: "#cffafe", + 200: "#a5f3fc", + 300: "#67e8f9", + 400: "#22d3ee", + 500: "#06b6d4", + 600: "#0891b2", + 700: "#0e7490", + 800: "#155e75", + 900: "#164e63", + 950: "#083344", + }, + sky: { + 50: "#f0f9ff", + 100: "#e0f2fe", + 200: "#bae6fd", + 300: "#7dd3fc", + 400: "#38bdf8", + 500: "#0ea5e9", + 600: "#0284c7", + 700: "#0369a1", + 800: "#075985", + 900: "#0c4a6e", + 950: "#082f49", + }, + blue: { + 50: "#eff6ff", + 100: "#dbeafe", + 200: "#bfdbfe", + 300: "#93c5fd", + 400: "#60a5fa", + 500: "#3b82f6", + 600: "#2563eb", + 700: "#1d4ed8", + 800: "#1e40af", + 900: "#1e3a8a", + 950: "#172554", + }, + indigo: { + 50: "#eef2ff", + 100: "#e0e7ff", + 200: "#c7d2fe", + 300: "#a5b4fc", + 400: "#818cf8", + 500: "#6366f1", + 600: "#4f46e5", + 700: "#4338ca", + 800: "#3730a3", + 900: "#312e81", + 950: "#1e1b4b", + }, + violet: { + 50: "#f5f3ff", + 100: "#ede9fe", + 200: "#ddd6fe", + 300: "#c4b5fd", + 400: "#a78bfa", + 500: "#8b5cf6", + 600: "#7c3aed", + 700: "#6d28d9", + 800: "#5b21b6", + 900: "#4c1d95", + 950: "#2e1065", + }, + purple: { + 50: "#faf5ff", + 100: "#f3e8ff", + 200: "#e9d5ff", + 300: "#d8b4fe", + 400: "#c084fc", + 500: "#a855f7", + 600: "#9333ea", + 700: "#7e22ce", + 800: "#6b21a8", + 900: "#581c87", + 950: "#3b0764", + }, + fuchsia: { + 50: "#fdf4ff", + 100: "#fae8ff", + 200: "#f5d0fe", + 300: "#f0abfc", + 400: "#e879f9", + 500: "#d946ef", + 600: "#c026d3", + 700: "#a21caf", + 800: "#86198f", + 900: "#701a75", + 950: "#4a044e", + }, + pink: { + 50: "#fdf2f8", + 100: "#fce7f3", + 200: "#fbcfe8", + 300: "#f9a8d4", + 400: "#f472b6", + 500: "#ec4899", + 600: "#db2777", + 700: "#be185d", + 800: "#9d174d", + 900: "#831843", + 950: "#500724", + }, + rose: { + 50: "#fff1f2", + 100: "#ffe4e6", + 200: "#fecdd3", + 300: "#fda4af", + 400: "#fb7185", + 500: "#f43f5e", + 600: "#e11d48", + 700: "#be123c", + 800: "#9f1239", + 900: "#881337", + 950: "#4c0519", + }, + get lightBlue() { + return (lr({ version: "v2.2", from: "lightBlue", to: "sky" }), this.sky); + }, + get warmGray() { + return (lr({ version: "v3.0", from: "warmGray", to: "stone" }), this.stone); + }, + get trueGray() { + return (lr({ version: "v3.0", from: "trueGray", to: "neutral" }), this.neutral); + }, + get coolGray() { + return (lr({ version: "v3.0", from: "coolGray", to: "gray" }), this.gray); + }, + get blueGray() { + return (lr({ version: "v3.0", from: "blueGray", to: "slate" }), this.slate); + }, + }; + }); + function os(r, ...e) { + for (let t of e) { + for (let i in t) r?.hasOwnProperty?.(i) || (r[i] = t[i]); + for (let i of Object.getOwnPropertySymbols(t)) r?.hasOwnProperty?.(i) || (r[i] = t[i]); + } + return r; + } + var Tu = C(() => { + l(); + }); + function Ze(r) { + if (Array.isArray(r)) return r; + let e = r.split("[").length - 1, + t = r.split("]").length - 1; + if (e !== t) throw new Error(`Path is invalid. Has unbalanced brackets: ${r}`); + return r.split(/\.(?![^\[]*\])|[\[\]]/g).filter(Boolean); + } + var gi = C(() => { + l(); + }); + function K(r, e) { + return yi.future.includes(e) + ? r.future === "all" || (r?.future?.[e] ?? Pu[e] ?? !1) + : yi.experimental.includes(e) + ? r.experimental === "all" || (r?.experimental?.[e] ?? Pu[e] ?? !1) + : !1; + } + function Du(r) { + return r.experimental === "all" + ? yi.experimental + : Object.keys(r?.experimental ?? {}).filter((e) => yi.experimental.includes(e) && r.experimental[e]); + } + function Iu(r) { + if (h.env.JEST_WORKER_ID === void 0 && Du(r).length > 0) { + let e = Du(r) + .map((t) => _e.yellow(t)) + .join(", "); + F.warn("experimental-flags-enabled", [ + `You have enabled experimental features: ${e}`, + "Experimental features in Tailwind CSS are not covered by semver, may introduce breaking changes, and can change at any time.", + ]); + } + } + var Pu, + yi, + je = C(() => { + l(); + hi(); + Oe(); + ((Pu = { + optimizeUniversalDefaults: !1, + generalizedModifiers: !0, + disableColorOpacityUtilitiesByDefault: !1, + relativeContentPathsByDefault: !1, + }), + (yi = { + future: [ + "hoverOnlyWhenSupported", + "respectDefaultRingColorOpacity", + "disableColorOpacityUtilitiesByDefault", + "relativeContentPathsByDefault", + ], + experimental: ["optimizeUniversalDefaults", "generalizedModifiers"], + })); + }); + function qu(r) { + ((() => { + if ( + r.purge || + !r.content || + (!Array.isArray(r.content) && !(typeof r.content == "object" && r.content !== null)) + ) + return !1; + if (Array.isArray(r.content)) + return r.content.every((t) => + typeof t == "string" + ? !0 + : !(typeof t?.raw != "string" || (t?.extension && typeof t?.extension != "string")) + ); + if (typeof r.content == "object" && r.content !== null) { + if (Object.keys(r.content).some((t) => !["files", "relative", "extract", "transform"].includes(t))) + return !1; + if (Array.isArray(r.content.files)) { + if ( + !r.content.files.every((t) => + typeof t == "string" + ? !0 + : !(typeof t?.raw != "string" || (t?.extension && typeof t?.extension != "string")) + ) + ) + return !1; + if (typeof r.content.extract == "object") { + for (let t of Object.values(r.content.extract)) if (typeof t != "function") return !1; + } else if (!(r.content.extract === void 0 || typeof r.content.extract == "function")) return !1; + if (typeof r.content.transform == "object") { + for (let t of Object.values(r.content.transform)) if (typeof t != "function") return !1; + } else if (!(r.content.transform === void 0 || typeof r.content.transform == "function")) return !1; + if (typeof r.content.relative != "boolean" && typeof r.content.relative != "undefined") return !1; + } + return !0; + } + return !1; + })() || + F.warn("purge-deprecation", [ + "The `purge`/`content` options have changed in Tailwind CSS v3.0.", + "Update your configuration file to eliminate this warning.", + "https://tailwindcss.com/docs/upgrade-guide#configure-content-sources", + ]), + (r.safelist = (() => { + let { content: t, purge: i, safelist: n } = r; + return Array.isArray(n) + ? n + : Array.isArray(t?.safelist) + ? t.safelist + : Array.isArray(i?.safelist) + ? i.safelist + : Array.isArray(i?.options?.safelist) + ? i.options.safelist + : []; + })()), + (r.blocklist = (() => { + let { blocklist: t } = r; + if (Array.isArray(t)) { + if (t.every((i) => typeof i == "string")) return t; + F.warn("blocklist-invalid", [ + "The `blocklist` option must be an array of strings.", + "https://tailwindcss.com/docs/content-configuration#discarding-classes", + ]); + } + return []; + })()), + typeof r.prefix == "function" + ? (F.warn("prefix-function", [ + "As of Tailwind CSS v3.0, `prefix` cannot be a function.", + "Update `prefix` in your configuration to be a string to eliminate this warning.", + "https://tailwindcss.com/docs/upgrade-guide#prefix-cannot-be-a-function", + ]), + (r.prefix = "")) + : (r.prefix = r.prefix ?? ""), + (r.content = { + relative: (() => { + let { content: t } = r; + return t?.relative ? t.relative : K(r, "relativeContentPathsByDefault"); + })(), + files: (() => { + let { content: t, purge: i } = r; + return Array.isArray(i) + ? i + : Array.isArray(i?.content) + ? i.content + : Array.isArray(t) + ? t + : Array.isArray(t?.content) + ? t.content + : Array.isArray(t?.files) + ? t.files + : []; + })(), + extract: (() => { + let t = (() => + r.purge?.extract + ? r.purge.extract + : r.content?.extract + ? r.content.extract + : r.purge?.extract?.DEFAULT + ? r.purge.extract.DEFAULT + : r.content?.extract?.DEFAULT + ? r.content.extract.DEFAULT + : r.purge?.options?.extractors + ? r.purge.options.extractors + : r.content?.options?.extractors + ? r.content.options.extractors + : {})(), + i = {}, + n = (() => { + if (r.purge?.options?.defaultExtractor) return r.purge.options.defaultExtractor; + if (r.content?.options?.defaultExtractor) return r.content.options.defaultExtractor; + })(); + if ((n !== void 0 && (i.DEFAULT = n), typeof t == "function")) i.DEFAULT = t; + else if (Array.isArray(t)) + for (let { extensions: a, extractor: s } of t ?? []) for (let o of a) i[o] = s; + else typeof t == "object" && t !== null && Object.assign(i, t); + return i; + })(), + transform: (() => { + let t = (() => + r.purge?.transform + ? r.purge.transform + : r.content?.transform + ? r.content.transform + : r.purge?.transform?.DEFAULT + ? r.purge.transform.DEFAULT + : r.content?.transform?.DEFAULT + ? r.content.transform.DEFAULT + : {})(), + i = {}; + return ( + typeof t == "function" && (i.DEFAULT = t), + typeof t == "object" && t !== null && Object.assign(i, t), + i + ); + })(), + })); + for (let t of r.content.files) + if (typeof t == "string" && /{([^,]*?)}/g.test(t)) { + F.warn("invalid-glob-braces", [ + `The glob pattern ${ns(t)} in your Tailwind CSS configuration is invalid.`, + `Update it to ${ns(t.replace(/{([^,]*?)}/g, "$1"))} to silence this warning.`, + ]); + break; + } + return r; + } + var Ru = C(() => { + l(); + je(); + Oe(); + }); + function ie(r) { + if (Object.prototype.toString.call(r) !== "[object Object]") return !1; + let e = Object.getPrototypeOf(r); + return e === null || Object.getPrototypeOf(e) === null; + } + var At = C(() => { + l(); + }); + function et(r) { + return Array.isArray(r) + ? r.map((e) => et(e)) + : typeof r == "object" && r !== null + ? Object.fromEntries(Object.entries(r).map(([e, t]) => [e, et(t)])) + : r; + } + var wi = C(() => { + l(); + }); + function wt(r) { + return r.replace(/\\,/g, "\\2c "); + } + var bi = C(() => { + l(); + }); + var ls, + Mu = C(() => { + l(); + ls = { + aliceblue: [240, 248, 255], + antiquewhite: [250, 235, 215], + aqua: [0, 255, 255], + aquamarine: [127, 255, 212], + azure: [240, 255, 255], + beige: [245, 245, 220], + bisque: [255, 228, 196], + black: [0, 0, 0], + blanchedalmond: [255, 235, 205], + blue: [0, 0, 255], + blueviolet: [138, 43, 226], + brown: [165, 42, 42], + burlywood: [222, 184, 135], + cadetblue: [95, 158, 160], + chartreuse: [127, 255, 0], + chocolate: [210, 105, 30], + coral: [255, 127, 80], + cornflowerblue: [100, 149, 237], + cornsilk: [255, 248, 220], + crimson: [220, 20, 60], + cyan: [0, 255, 255], + darkblue: [0, 0, 139], + darkcyan: [0, 139, 139], + darkgoldenrod: [184, 134, 11], + darkgray: [169, 169, 169], + darkgreen: [0, 100, 0], + darkgrey: [169, 169, 169], + darkkhaki: [189, 183, 107], + darkmagenta: [139, 0, 139], + darkolivegreen: [85, 107, 47], + darkorange: [255, 140, 0], + darkorchid: [153, 50, 204], + darkred: [139, 0, 0], + darksalmon: [233, 150, 122], + darkseagreen: [143, 188, 143], + darkslateblue: [72, 61, 139], + darkslategray: [47, 79, 79], + darkslategrey: [47, 79, 79], + darkturquoise: [0, 206, 209], + darkviolet: [148, 0, 211], + deeppink: [255, 20, 147], + deepskyblue: [0, 191, 255], + dimgray: [105, 105, 105], + dimgrey: [105, 105, 105], + dodgerblue: [30, 144, 255], + firebrick: [178, 34, 34], + floralwhite: [255, 250, 240], + forestgreen: [34, 139, 34], + fuchsia: [255, 0, 255], + gainsboro: [220, 220, 220], + ghostwhite: [248, 248, 255], + gold: [255, 215, 0], + goldenrod: [218, 165, 32], + gray: [128, 128, 128], + green: [0, 128, 0], + greenyellow: [173, 255, 47], + grey: [128, 128, 128], + honeydew: [240, 255, 240], + hotpink: [255, 105, 180], + indianred: [205, 92, 92], + indigo: [75, 0, 130], + ivory: [255, 255, 240], + khaki: [240, 230, 140], + lavender: [230, 230, 250], + lavenderblush: [255, 240, 245], + lawngreen: [124, 252, 0], + lemonchiffon: [255, 250, 205], + lightblue: [173, 216, 230], + lightcoral: [240, 128, 128], + lightcyan: [224, 255, 255], + lightgoldenrodyellow: [250, 250, 210], + lightgray: [211, 211, 211], + lightgreen: [144, 238, 144], + lightgrey: [211, 211, 211], + lightpink: [255, 182, 193], + lightsalmon: [255, 160, 122], + lightseagreen: [32, 178, 170], + lightskyblue: [135, 206, 250], + lightslategray: [119, 136, 153], + lightslategrey: [119, 136, 153], + lightsteelblue: [176, 196, 222], + lightyellow: [255, 255, 224], + lime: [0, 255, 0], + limegreen: [50, 205, 50], + linen: [250, 240, 230], + magenta: [255, 0, 255], + maroon: [128, 0, 0], + mediumaquamarine: [102, 205, 170], + mediumblue: [0, 0, 205], + mediumorchid: [186, 85, 211], + mediumpurple: [147, 112, 219], + mediumseagreen: [60, 179, 113], + mediumslateblue: [123, 104, 238], + mediumspringgreen: [0, 250, 154], + mediumturquoise: [72, 209, 204], + mediumvioletred: [199, 21, 133], + midnightblue: [25, 25, 112], + mintcream: [245, 255, 250], + mistyrose: [255, 228, 225], + moccasin: [255, 228, 181], + navajowhite: [255, 222, 173], + navy: [0, 0, 128], + oldlace: [253, 245, 230], + olive: [128, 128, 0], + olivedrab: [107, 142, 35], + orange: [255, 165, 0], + orangered: [255, 69, 0], + orchid: [218, 112, 214], + palegoldenrod: [238, 232, 170], + palegreen: [152, 251, 152], + paleturquoise: [175, 238, 238], + palevioletred: [219, 112, 147], + papayawhip: [255, 239, 213], + peachpuff: [255, 218, 185], + peru: [205, 133, 63], + pink: [255, 192, 203], + plum: [221, 160, 221], + powderblue: [176, 224, 230], + purple: [128, 0, 128], + rebeccapurple: [102, 51, 153], + red: [255, 0, 0], + rosybrown: [188, 143, 143], + royalblue: [65, 105, 225], + saddlebrown: [139, 69, 19], + salmon: [250, 128, 114], + sandybrown: [244, 164, 96], + seagreen: [46, 139, 87], + seashell: [255, 245, 238], + sienna: [160, 82, 45], + silver: [192, 192, 192], + skyblue: [135, 206, 235], + slateblue: [106, 90, 205], + slategray: [112, 128, 144], + slategrey: [112, 128, 144], + snow: [255, 250, 250], + springgreen: [0, 255, 127], + steelblue: [70, 130, 180], + tan: [210, 180, 140], + teal: [0, 128, 128], + thistle: [216, 191, 216], + tomato: [255, 99, 71], + turquoise: [64, 224, 208], + violet: [238, 130, 238], + wheat: [245, 222, 179], + white: [255, 255, 255], + whitesmoke: [245, 245, 245], + yellow: [255, 255, 0], + yellowgreen: [154, 205, 50], + }; + }); + function ur(r, { loose: e = !1 } = {}) { + if (typeof r != "string") return null; + if (((r = r.trim()), r === "transparent")) return { mode: "rgb", color: ["0", "0", "0"], alpha: "0" }; + if (r in ls) return { mode: "rgb", color: ls[r].map((a) => a.toString()) }; + let t = r.replace(jb, (a, s, o, u, c) => ["#", s, s, o, o, u, u, c ? c + c : ""].join("")).match(zb); + if (t !== null) + return { + mode: "rgb", + color: [parseInt(t[1], 16), parseInt(t[2], 16), parseInt(t[3], 16)].map((a) => a.toString()), + alpha: t[4] ? (parseInt(t[4], 16) / 255).toString() : void 0, + }; + let i = r.match(Vb) ?? r.match(Ub); + if (i === null) return null; + let n = [i[2], i[3], i[4]].filter(Boolean).map((a) => a.toString()); + return n.length === 2 && n[0].startsWith("var(") + ? { mode: i[1], color: [n[0]], alpha: n[1] } + : (!e && n.length !== 3) || (n.length < 3 && !n.some((a) => /^var\(.*?\)$/.test(a))) + ? null + : { mode: i[1], color: n, alpha: i[5]?.toString?.() }; + } + function us({ mode: r, color: e, alpha: t }) { + let i = t !== void 0; + return r === "rgba" || r === "hsla" + ? `${r}(${e.join(", ")}${i ? `, ${t}` : ""})` + : `${r}(${e.join(" ")}${i ? ` / ${t}` : ""})`; + } + var zb, + jb, + tt, + vi, + Bu, + rt, + Vb, + Ub, + fs = C(() => { + l(); + Mu(); + ((zb = /^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i), + (jb = /^#([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i), + (tt = /(?:\d+|\d*\.\d+)%?/), + (vi = /(?:\s*,\s*|\s+)/), + (Bu = /\s*[,/]\s*/), + (rt = /var\(--(?:[^ )]*?)(?:,(?:[^ )]*?|var\(--[^ )]*?\)))?\)/), + (Vb = new RegExp( + `^(rgba?)\\(\\s*(${tt.source}|${rt.source})(?:${vi.source}(${tt.source}|${rt.source}))?(?:${vi.source}(${tt.source}|${rt.source}))?(?:${Bu.source}(${tt.source}|${rt.source}))?\\s*\\)$` + )), + (Ub = new RegExp( + `^(hsla?)\\(\\s*((?:${tt.source})(?:deg|rad|grad|turn)?|${rt.source})(?:${vi.source}(${tt.source}|${rt.source}))?(?:${vi.source}(${tt.source}|${rt.source}))?(?:${Bu.source}(${tt.source}|${rt.source}))?\\s*\\)$` + ))); + }); + function Ie(r, e, t) { + if (typeof r == "function") return r({ opacityValue: e }); + let i = ur(r, { loose: !0 }); + return i === null ? t : us({ ...i, alpha: e }); + } + function se({ color: r, property: e, variable: t }) { + let i = [].concat(e); + if (typeof r == "function") + return { + [t]: "1", + ...Object.fromEntries(i.map((a) => [a, r({ opacityVariable: t, opacityValue: `var(${t})` })])), + }; + let n = ur(r); + return n === null + ? Object.fromEntries(i.map((a) => [a, r])) + : n.alpha !== void 0 + ? Object.fromEntries(i.map((a) => [a, r])) + : { [t]: "1", ...Object.fromEntries(i.map((a) => [a, us({ ...n, alpha: `var(${t})` })])) }; + } + var fr = C(() => { + l(); + fs(); + }); + function ae(r, e) { + let t = [], + i = [], + n = 0, + a = !1; + for (let s = 0; s < r.length; s++) { + let o = r[s]; + (t.length === 0 && + o === e[0] && + !a && + (e.length === 1 || r.slice(s, s + e.length) === e) && + (i.push(r.slice(n, s)), (n = s + e.length)), + a ? (a = !1) : o === "\\" && (a = !0), + o === "(" || o === "[" || o === "{" + ? t.push(o) + : ((o === ")" && t[t.length - 1] === "(") || + (o === "]" && t[t.length - 1] === "[") || + (o === "}" && t[t.length - 1] === "{")) && + t.pop()); + } + return (i.push(r.slice(n)), i); + } + var _t = C(() => { + l(); + }); + function xi(r) { + return ae(r, ",").map((t) => { + let i = t.trim(), + n = { raw: i }, + a = i.split(Gb), + s = new Set(); + for (let o of a) + ((Fu.lastIndex = 0), + !s.has("KEYWORD") && Wb.has(o) + ? ((n.keyword = o), s.add("KEYWORD")) + : Fu.test(o) + ? s.has("X") + ? s.has("Y") + ? s.has("BLUR") + ? s.has("SPREAD") || ((n.spread = o), s.add("SPREAD")) + : ((n.blur = o), s.add("BLUR")) + : ((n.y = o), s.add("Y")) + : ((n.x = o), s.add("X")) + : n.color + ? (n.unknown || (n.unknown = []), n.unknown.push(o)) + : (n.color = o)); + return ((n.valid = n.x !== void 0 && n.y !== void 0), n); + }); + } + function Lu(r) { + return r + .map((e) => (e.valid ? [e.keyword, e.x, e.y, e.blur, e.spread, e.color].filter(Boolean).join(" ") : e.raw)) + .join(", "); + } + var Wb, + Gb, + Fu, + cs = C(() => { + l(); + _t(); + ((Wb = new Set(["inset", "inherit", "initial", "revert", "unset"])), + (Gb = /\ +(?![^(]*\))/g), + (Fu = /^-?(\d+|\.\d+)(.*?)$/g)); + }); + function ps(r) { + return Hb.some((e) => new RegExp(`^${e}\\(.*\\)`).test(r)); + } + function L(r, e = null, t = !0) { + let i = e && Yb.has(e.property); + return r.startsWith("--") && !i + ? `var(${r})` + : r.includes("url(") + ? r + .split(/(url\(.*?\))/g) + .filter(Boolean) + .map((n) => (/^url\(.*?\)$/.test(n) ? n : L(n, e, !1))) + .join("") + : ((r = r + .replace(/([^\\])_+/g, (n, a) => a + " ".repeat(n.length - 1)) + .replace(/^_/g, " ") + .replace(/\\_/g, "_")), + t && (r = r.trim()), + (r = Qb(r)), + r); + } + function Qb(r) { + let e = ["theme"], + t = [ + "min-content", + "max-content", + "fit-content", + "safe-area-inset-top", + "safe-area-inset-right", + "safe-area-inset-bottom", + "safe-area-inset-left", + "titlebar-area-x", + "titlebar-area-y", + "titlebar-area-width", + "titlebar-area-height", + "keyboard-inset-top", + "keyboard-inset-right", + "keyboard-inset-bottom", + "keyboard-inset-left", + "keyboard-inset-width", + "keyboard-inset-height", + "radial-gradient", + "linear-gradient", + "conic-gradient", + "repeating-radial-gradient", + "repeating-linear-gradient", + "repeating-conic-gradient", + ]; + return r.replace(/(calc|min|max|clamp)\(.+\)/g, (i) => { + let n = ""; + function a() { + let s = n.trimEnd(); + return s[s.length - 1]; + } + for (let s = 0; s < i.length; s++) { + let o = function (f) { + return f.split("").every((d, p) => i[s + p] === d); + }, + u = function (f) { + let d = 1 / 0; + for (let m of f) { + let b = i.indexOf(m, s); + b !== -1 && b < d && (d = b); + } + let p = i.slice(s, d); + return ((s += p.length - 1), p); + }, + c = i[s]; + if (o("var")) n += u([")", ","]); + else if (t.some((f) => o(f))) { + let f = t.find((d) => o(d)); + ((n += f), (s += f.length - 1)); + } else + e.some((f) => o(f)) + ? (n += u([")"])) + : o("[") + ? (n += u(["]"])) + : ["+", "-", "*", "/"].includes(c) && !["(", "+", "-", "*", "/", ","].includes(a()) + ? (n += ` ${c} `) + : (n += c); + } + return n.replace(/\s+/g, " "); + }); + } + function ds(r) { + return r.startsWith("url("); + } + function hs(r) { + return !isNaN(Number(r)) || ps(r); + } + function cr(r) { + return (r.endsWith("%") && hs(r.slice(0, -1))) || ps(r); + } + function pr(r) { + return r === "0" || new RegExp(`^[+-]?[0-9]*.?[0-9]+(?:[eE][+-]?[0-9]+)?${Xb}$`).test(r) || ps(r); + } + function Nu(r) { + return Kb.has(r); + } + function $u(r) { + let e = xi(L(r)); + for (let t of e) if (!t.valid) return !1; + return !0; + } + function zu(r) { + let e = 0; + return ae(r, "_").every( + (i) => ((i = L(i)), i.startsWith("var(") ? !0 : ur(i, { loose: !0 }) !== null ? (e++, !0) : !1) + ) + ? e > 0 + : !1; + } + function ju(r) { + let e = 0; + return ae(r, ",").every( + (i) => ( + (i = L(i)), + i.startsWith("var(") + ? !0 + : ds(i) || e0(i) || ["element(", "image(", "cross-fade(", "image-set("].some((n) => i.startsWith(n)) + ? (e++, !0) + : !1 + ) + ) + ? e > 0 + : !1; + } + function e0(r) { + r = L(r); + for (let e of Zb) if (r.startsWith(`${e}(`)) return !0; + return !1; + } + function Vu(r) { + let e = 0; + return ae(r, "_").every( + (i) => ((i = L(i)), i.startsWith("var(") ? !0 : t0.has(i) || pr(i) || cr(i) ? (e++, !0) : !1) + ) + ? e > 0 + : !1; + } + function Uu(r) { + let e = 0; + return ae(r, ",").every( + (i) => ( + (i = L(i)), + i.startsWith("var(") + ? !0 + : (i.includes(" ") && !/(['"])([^"']+)\1/g.test(i)) || /^\d/g.test(i) + ? !1 + : (e++, !0) + ) + ) + ? e > 0 + : !1; + } + function Wu(r) { + return r0.has(r); + } + function Gu(r) { + return i0.has(r); + } + function Hu(r) { + return n0.has(r); + } + var Hb, + Yb, + Jb, + Xb, + Kb, + Zb, + t0, + r0, + i0, + n0, + dr = C(() => { + l(); + fs(); + cs(); + _t(); + Hb = ["min", "max", "clamp", "calc"]; + Yb = new Set([ + "scroll-timeline-name", + "timeline-scope", + "view-timeline-name", + "font-palette", + "scroll-timeline", + "animation-timeline", + "view-timeline", + ]); + ((Jb = [ + "cm", + "mm", + "Q", + "in", + "pc", + "pt", + "px", + "em", + "ex", + "ch", + "rem", + "lh", + "rlh", + "vw", + "vh", + "vmin", + "vmax", + "vb", + "vi", + "svw", + "svh", + "lvw", + "lvh", + "dvw", + "dvh", + "cqw", + "cqh", + "cqi", + "cqb", + "cqmin", + "cqmax", + ]), + (Xb = `(?:${Jb.join("|")})`)); + Kb = new Set(["thin", "medium", "thick"]); + Zb = new Set([ + "conic-gradient", + "linear-gradient", + "radial-gradient", + "repeating-conic-gradient", + "repeating-linear-gradient", + "repeating-radial-gradient", + ]); + t0 = new Set(["center", "top", "right", "bottom", "left"]); + r0 = new Set([ + "serif", + "sans-serif", + "monospace", + "cursive", + "fantasy", + "system-ui", + "ui-serif", + "ui-sans-serif", + "ui-monospace", + "ui-rounded", + "math", + "emoji", + "fangsong", + ]); + i0 = new Set(["xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "xxx-large"]); + n0 = new Set(["larger", "smaller"]); + }); + function Yu(r) { + let e = ["cover", "contain"]; + return ae(r, ",").every((t) => { + let i = ae(t, "_").filter(Boolean); + return i.length === 1 && e.includes(i[0]) + ? !0 + : i.length !== 1 && i.length !== 2 + ? !1 + : i.every((n) => pr(n) || cr(n) || n === "auto"); + }); + } + var Qu = C(() => { + l(); + dr(); + _t(); + }); + function Ju(r, e) { + r.walkClasses((t) => { + ((t.value = e(t.value)), t.raws && t.raws.value && (t.raws.value = wt(t.raws.value))); + }); + } + function Xu(r, e) { + if (!it(r)) return; + let t = r.slice(1, -1); + if (!!e(t)) return L(t); + } + function s0(r, e = {}, t) { + let i = e[r]; + if (i !== void 0) return Ke(i); + if (it(r)) { + let n = Xu(r, t); + return n === void 0 ? void 0 : Ke(n); + } + } + function ki(r, e = {}, { validate: t = () => !0 } = {}) { + let i = e.values?.[r]; + return i !== void 0 + ? i + : e.supportsNegativeValues && r.startsWith("-") + ? s0(r.slice(1), e.values, t) + : Xu(r, t); + } + function it(r) { + return r.startsWith("[") && r.endsWith("]"); + } + function Ku(r) { + let e = r.lastIndexOf("/"), + t = r.lastIndexOf("[", e), + i = r.indexOf("]", e); + return ( + r[e - 1] === "]" || + r[e + 1] === "[" || + (t !== -1 && i !== -1 && t < e && e < i && (e = r.lastIndexOf("/", t))), + e === -1 || e === r.length - 1 + ? [r, void 0] + : it(r) && !r.includes("]/[") + ? [r, void 0] + : [r.slice(0, e), r.slice(e + 1)] + ); + } + function Ot(r) { + if (typeof r == "string" && r.includes("")) { + let e = r; + return ({ opacityValue: t = 1 }) => e.replace("", t); + } + return r; + } + function Zu(r) { + return L(r.slice(1, -1)); + } + function a0(r, e = {}, { tailwindConfig: t = {} } = {}) { + if (e.values?.[r] !== void 0) return Ot(e.values?.[r]); + let [i, n] = Ku(r); + if (n !== void 0) { + let a = e.values?.[i] ?? (it(i) ? i.slice(1, -1) : void 0); + return a === void 0 + ? void 0 + : ((a = Ot(a)), + it(n) ? Ie(a, Zu(n)) : t.theme?.opacity?.[n] === void 0 ? void 0 : Ie(a, t.theme.opacity[n])); + } + return ki(r, e, { validate: zu }); + } + function o0(r, e = {}) { + return e.values?.[r]; + } + function me(r) { + return (e, t) => ki(e, t, { validate: r }); + } + function l0(r, e) { + let t = r.indexOf(e); + return t === -1 ? [void 0, r] : [r.slice(0, t), r.slice(t + 1)]; + } + function gs(r, e, t, i) { + if (t.values && e in t.values) + for (let { type: a } of r ?? []) { + let s = ms[a](e, t, { tailwindConfig: i }); + if (s !== void 0) return [s, a, null]; + } + if (it(e)) { + let a = e.slice(1, -1), + [s, o] = l0(a, ":"); + if (!/^[\w-_]+$/g.test(s)) o = a; + else if (s !== void 0 && !ef.includes(s)) return []; + if (o.length > 0 && ef.includes(s)) return [ki(`[${o}]`, t), s, null]; + } + let n = ys(r, e, t, i); + for (let a of n) return a; + return []; + } + function* ys(r, e, t, i) { + let n = K(i, "generalizedModifiers"), + [a, s] = Ku(e); + if ( + ((n && + t.modifiers != null && + (t.modifiers === "any" || (typeof t.modifiers == "object" && ((s && it(s)) || s in t.modifiers)))) || + ((a = e), (s = void 0)), + s !== void 0 && a === "" && (a = "DEFAULT"), + s !== void 0 && typeof t.modifiers == "object") + ) { + let u = t.modifiers?.[s] ?? null; + u !== null ? (s = u) : it(s) && (s = Zu(s)); + } + for (let { type: u } of r ?? []) { + let c = ms[u](a, t, { tailwindConfig: i }); + c !== void 0 && (yield [c, u, s ?? null]); + } + } + var ms, + ef, + hr = C(() => { + l(); + bi(); + fr(); + dr(); + di(); + Qu(); + je(); + ((ms = { + any: ki, + color: a0, + url: me(ds), + image: me(ju), + length: me(pr), + percentage: me(cr), + position: me(Vu), + lookup: o0, + "generic-name": me(Wu), + "family-name": me(Uu), + number: me(hs), + "line-width": me(Nu), + "absolute-size": me(Gu), + "relative-size": me(Hu), + shadow: me($u), + size: me(Yu), + }), + (ef = Object.keys(ms))); + }); + function N(r) { + return typeof r == "function" ? r({}) : r; + } + var ws = C(() => { + l(); + }); + function Et(r) { + return typeof r == "function"; + } + function mr(r, ...e) { + let t = e.pop(); + for (let i of e) + for (let n in i) { + let a = t(r[n], i[n]); + a === void 0 ? (ie(r[n]) && ie(i[n]) ? (r[n] = mr({}, r[n], i[n], t)) : (r[n] = i[n])) : (r[n] = a); + } + return r; + } + function u0(r, ...e) { + return Et(r) ? r(...e) : r; + } + function f0(r) { + return r.reduce( + (e, { extend: t }) => mr(e, t, (i, n) => (i === void 0 ? [n] : Array.isArray(i) ? [n, ...i] : [n, i])), + {} + ); + } + function c0(r) { + return { ...r.reduce((e, t) => os(e, t), {}), extend: f0(r) }; + } + function tf(r, e) { + if (Array.isArray(r) && ie(r[0])) return r.concat(e); + if (Array.isArray(e) && ie(e[0]) && ie(r)) return [r, ...e]; + if (Array.isArray(e)) return e; + } + function p0({ extend: r, ...e }) { + return mr(e, r, (t, i) => + !Et(t) && !i.some(Et) ? mr({}, t, ...i, tf) : (n, a) => mr({}, ...[t, ...i].map((s) => u0(s, n, a)), tf) + ); + } + function* d0(r) { + let e = Ze(r); + if (e.length === 0 || (yield e, Array.isArray(r))) return; + let t = /^(.*?)\s*\/\s*([^/]+)$/, + i = r.match(t); + if (i !== null) { + let [, n, a] = i, + s = Ze(n); + ((s.alpha = a), yield s); + } + } + function h0(r) { + let e = (t, i) => { + for (let n of d0(t)) { + let a = 0, + s = r; + for (; s != null && a < n.length; ) + ((s = s[n[a++]]), (s = Et(s) && (n.alpha === void 0 || a <= n.length - 1) ? s(e, bs) : s)); + if (s !== void 0) { + if (n.alpha !== void 0) { + let o = Ot(s); + return Ie(o, n.alpha, N(o)); + } + return ie(s) ? et(s) : s; + } + } + return i; + }; + return ( + Object.assign(e, { theme: e, ...bs }), + Object.keys(r).reduce((t, i) => ((t[i] = Et(r[i]) ? r[i](e, bs) : r[i]), t), {}) + ); + } + function rf(r) { + let e = []; + return ( + r.forEach((t) => { + e = [...e, t]; + let i = t?.plugins ?? []; + i.length !== 0 && + i.forEach((n) => { + (n.__isOptionsFunction && (n = n()), (e = [...e, ...rf([n?.config ?? {}])])); + }); + }), + e + ); + } + function m0(r) { + return [...r].reduceRight((t, i) => (Et(i) ? i({ corePlugins: t }) : Au(i, t)), Su); + } + function g0(r) { + return [...r].reduceRight((t, i) => [...t, ...i], []); + } + function vs(r) { + let e = [...rf(r), { prefix: "", important: !1, separator: ":" }]; + return qu( + os( + { + theme: h0(p0(c0(e.map((t) => t?.theme ?? {})))), + corePlugins: m0(e.map((t) => t.corePlugins)), + plugins: g0(r.map((t) => t?.plugins ?? [])), + }, + ...e + ) + ); + } + var bs, + nf = C(() => { + l(); + di(); + Cu(); + _u(); + mi(); + Tu(); + gi(); + Ru(); + At(); + wi(); + hr(); + fr(); + ws(); + bs = { + colors: ss, + negative(r) { + return Object.keys(r) + .filter((e) => r[e] !== "0") + .reduce((e, t) => { + let i = Ke(r[t]); + return (i !== void 0 && (e[`-${t}`] = i), e); + }, {}); + }, + breakpoints(r) { + return Object.keys(r) + .filter((e) => typeof r[e] == "string") + .reduce((e, t) => ({ ...e, [`screen-${t}`]: r[t] }), {}); + }, + }; + }); + var Si = v((i3, sf) => { + l(); + sf.exports = { + content: [], + presets: [], + darkMode: "media", + theme: { + accentColor: ({ theme: r }) => ({ ...r("colors"), auto: "auto" }), + animation: { + none: "none", + spin: "spin 1s linear infinite", + ping: "ping 1s cubic-bezier(0, 0, 0.2, 1) infinite", + pulse: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite", + bounce: "bounce 1s infinite", + }, + aria: { + busy: 'busy="true"', + checked: 'checked="true"', + disabled: 'disabled="true"', + expanded: 'expanded="true"', + hidden: 'hidden="true"', + pressed: 'pressed="true"', + readonly: 'readonly="true"', + required: 'required="true"', + selected: 'selected="true"', + }, + aspectRatio: { auto: "auto", square: "1 / 1", video: "16 / 9" }, + backdropBlur: ({ theme: r }) => r("blur"), + backdropBrightness: ({ theme: r }) => r("brightness"), + backdropContrast: ({ theme: r }) => r("contrast"), + backdropGrayscale: ({ theme: r }) => r("grayscale"), + backdropHueRotate: ({ theme: r }) => r("hueRotate"), + backdropInvert: ({ theme: r }) => r("invert"), + backdropOpacity: ({ theme: r }) => r("opacity"), + backdropSaturate: ({ theme: r }) => r("saturate"), + backdropSepia: ({ theme: r }) => r("sepia"), + backgroundColor: ({ theme: r }) => r("colors"), + backgroundImage: { + none: "none", + "gradient-to-t": "linear-gradient(to top, var(--tw-gradient-stops))", + "gradient-to-tr": "linear-gradient(to top right, var(--tw-gradient-stops))", + "gradient-to-r": "linear-gradient(to right, var(--tw-gradient-stops))", + "gradient-to-br": "linear-gradient(to bottom right, var(--tw-gradient-stops))", + "gradient-to-b": "linear-gradient(to bottom, var(--tw-gradient-stops))", + "gradient-to-bl": "linear-gradient(to bottom left, var(--tw-gradient-stops))", + "gradient-to-l": "linear-gradient(to left, var(--tw-gradient-stops))", + "gradient-to-tl": "linear-gradient(to top left, var(--tw-gradient-stops))", + }, + backgroundOpacity: ({ theme: r }) => r("opacity"), + backgroundPosition: { + bottom: "bottom", + center: "center", + left: "left", + "left-bottom": "left bottom", + "left-top": "left top", + right: "right", + "right-bottom": "right bottom", + "right-top": "right top", + top: "top", + }, + backgroundSize: { auto: "auto", cover: "cover", contain: "contain" }, + blur: { + 0: "0", + none: "0", + sm: "4px", + DEFAULT: "8px", + md: "12px", + lg: "16px", + xl: "24px", + "2xl": "40px", + "3xl": "64px", + }, + borderColor: ({ theme: r }) => ({ ...r("colors"), DEFAULT: r("colors.gray.200", "currentColor") }), + borderOpacity: ({ theme: r }) => r("opacity"), + borderRadius: { + none: "0px", + sm: "0.125rem", + DEFAULT: "0.25rem", + md: "0.375rem", + lg: "0.5rem", + xl: "0.75rem", + "2xl": "1rem", + "3xl": "1.5rem", + full: "9999px", + }, + borderSpacing: ({ theme: r }) => ({ ...r("spacing") }), + borderWidth: { DEFAULT: "1px", 0: "0px", 2: "2px", 4: "4px", 8: "8px" }, + boxShadow: { + sm: "0 1px 2px 0 rgb(0 0 0 / 0.05)", + DEFAULT: "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)", + md: "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)", + lg: "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)", + xl: "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)", + "2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)", + inner: "inset 0 2px 4px 0 rgb(0 0 0 / 0.05)", + none: "none", + }, + boxShadowColor: ({ theme: r }) => r("colors"), + brightness: { + 0: "0", + 50: ".5", + 75: ".75", + 90: ".9", + 95: ".95", + 100: "1", + 105: "1.05", + 110: "1.1", + 125: "1.25", + 150: "1.5", + 200: "2", + }, + caretColor: ({ theme: r }) => r("colors"), + colors: ({ colors: r }) => ({ + inherit: r.inherit, + current: r.current, + transparent: r.transparent, + black: r.black, + white: r.white, + slate: r.slate, + gray: r.gray, + zinc: r.zinc, + neutral: r.neutral, + stone: r.stone, + red: r.red, + orange: r.orange, + amber: r.amber, + yellow: r.yellow, + lime: r.lime, + green: r.green, + emerald: r.emerald, + teal: r.teal, + cyan: r.cyan, + sky: r.sky, + blue: r.blue, + indigo: r.indigo, + violet: r.violet, + purple: r.purple, + fuchsia: r.fuchsia, + pink: r.pink, + rose: r.rose, + }), + columns: { + auto: "auto", + 1: "1", + 2: "2", + 3: "3", + 4: "4", + 5: "5", + 6: "6", + 7: "7", + 8: "8", + 9: "9", + 10: "10", + 11: "11", + 12: "12", + "3xs": "16rem", + "2xs": "18rem", + xs: "20rem", + sm: "24rem", + md: "28rem", + lg: "32rem", + xl: "36rem", + "2xl": "42rem", + "3xl": "48rem", + "4xl": "56rem", + "5xl": "64rem", + "6xl": "72rem", + "7xl": "80rem", + }, + container: {}, + content: { none: "none" }, + contrast: { 0: "0", 50: ".5", 75: ".75", 100: "1", 125: "1.25", 150: "1.5", 200: "2" }, + cursor: { + auto: "auto", + default: "default", + pointer: "pointer", + wait: "wait", + text: "text", + move: "move", + help: "help", + "not-allowed": "not-allowed", + none: "none", + "context-menu": "context-menu", + progress: "progress", + cell: "cell", + crosshair: "crosshair", + "vertical-text": "vertical-text", + alias: "alias", + copy: "copy", + "no-drop": "no-drop", + grab: "grab", + grabbing: "grabbing", + "all-scroll": "all-scroll", + "col-resize": "col-resize", + "row-resize": "row-resize", + "n-resize": "n-resize", + "e-resize": "e-resize", + "s-resize": "s-resize", + "w-resize": "w-resize", + "ne-resize": "ne-resize", + "nw-resize": "nw-resize", + "se-resize": "se-resize", + "sw-resize": "sw-resize", + "ew-resize": "ew-resize", + "ns-resize": "ns-resize", + "nesw-resize": "nesw-resize", + "nwse-resize": "nwse-resize", + "zoom-in": "zoom-in", + "zoom-out": "zoom-out", + }, + divideColor: ({ theme: r }) => r("borderColor"), + divideOpacity: ({ theme: r }) => r("borderOpacity"), + divideWidth: ({ theme: r }) => r("borderWidth"), + dropShadow: { + sm: "0 1px 1px rgb(0 0 0 / 0.05)", + DEFAULT: ["0 1px 2px rgb(0 0 0 / 0.1)", "0 1px 1px rgb(0 0 0 / 0.06)"], + md: ["0 4px 3px rgb(0 0 0 / 0.07)", "0 2px 2px rgb(0 0 0 / 0.06)"], + lg: ["0 10px 8px rgb(0 0 0 / 0.04)", "0 4px 3px rgb(0 0 0 / 0.1)"], + xl: ["0 20px 13px rgb(0 0 0 / 0.03)", "0 8px 5px rgb(0 0 0 / 0.08)"], + "2xl": "0 25px 25px rgb(0 0 0 / 0.15)", + none: "0 0 #0000", + }, + fill: ({ theme: r }) => ({ none: "none", ...r("colors") }), + flex: { 1: "1 1 0%", auto: "1 1 auto", initial: "0 1 auto", none: "none" }, + flexBasis: ({ theme: r }) => ({ + auto: "auto", + ...r("spacing"), + "1/2": "50%", + "1/3": "33.333333%", + "2/3": "66.666667%", + "1/4": "25%", + "2/4": "50%", + "3/4": "75%", + "1/5": "20%", + "2/5": "40%", + "3/5": "60%", + "4/5": "80%", + "1/6": "16.666667%", + "2/6": "33.333333%", + "3/6": "50%", + "4/6": "66.666667%", + "5/6": "83.333333%", + "1/12": "8.333333%", + "2/12": "16.666667%", + "3/12": "25%", + "4/12": "33.333333%", + "5/12": "41.666667%", + "6/12": "50%", + "7/12": "58.333333%", + "8/12": "66.666667%", + "9/12": "75%", + "10/12": "83.333333%", + "11/12": "91.666667%", + full: "100%", + }), + flexGrow: { 0: "0", DEFAULT: "1" }, + flexShrink: { 0: "0", DEFAULT: "1" }, + fontFamily: { + sans: [ + "ui-sans-serif", + "system-ui", + "sans-serif", + '"Apple Color Emoji"', + '"Segoe UI Emoji"', + '"Segoe UI Symbol"', + '"Noto Color Emoji"', + ], + serif: ["ui-serif", "Georgia", "Cambria", '"Times New Roman"', "Times", "serif"], + mono: [ + "ui-monospace", + "SFMono-Regular", + "Menlo", + "Monaco", + "Consolas", + '"Liberation Mono"', + '"Courier New"', + "monospace", + ], + }, + fontSize: { + xs: ["0.75rem", { lineHeight: "1rem" }], + sm: ["0.875rem", { lineHeight: "1.25rem" }], + base: ["1rem", { lineHeight: "1.5rem" }], + lg: ["1.125rem", { lineHeight: "1.75rem" }], + xl: ["1.25rem", { lineHeight: "1.75rem" }], + "2xl": ["1.5rem", { lineHeight: "2rem" }], + "3xl": ["1.875rem", { lineHeight: "2.25rem" }], + "4xl": ["2.25rem", { lineHeight: "2.5rem" }], + "5xl": ["3rem", { lineHeight: "1" }], + "6xl": ["3.75rem", { lineHeight: "1" }], + "7xl": ["4.5rem", { lineHeight: "1" }], + "8xl": ["6rem", { lineHeight: "1" }], + "9xl": ["8rem", { lineHeight: "1" }], + }, + fontWeight: { + thin: "100", + extralight: "200", + light: "300", + normal: "400", + medium: "500", + semibold: "600", + bold: "700", + extrabold: "800", + black: "900", + }, + gap: ({ theme: r }) => r("spacing"), + gradientColorStops: ({ theme: r }) => r("colors"), + gradientColorStopPositions: { + "0%": "0%", + "5%": "5%", + "10%": "10%", + "15%": "15%", + "20%": "20%", + "25%": "25%", + "30%": "30%", + "35%": "35%", + "40%": "40%", + "45%": "45%", + "50%": "50%", + "55%": "55%", + "60%": "60%", + "65%": "65%", + "70%": "70%", + "75%": "75%", + "80%": "80%", + "85%": "85%", + "90%": "90%", + "95%": "95%", + "100%": "100%", + }, + grayscale: { 0: "0", DEFAULT: "100%" }, + gridAutoColumns: { auto: "auto", min: "min-content", max: "max-content", fr: "minmax(0, 1fr)" }, + gridAutoRows: { auto: "auto", min: "min-content", max: "max-content", fr: "minmax(0, 1fr)" }, + gridColumn: { + auto: "auto", + "span-1": "span 1 / span 1", + "span-2": "span 2 / span 2", + "span-3": "span 3 / span 3", + "span-4": "span 4 / span 4", + "span-5": "span 5 / span 5", + "span-6": "span 6 / span 6", + "span-7": "span 7 / span 7", + "span-8": "span 8 / span 8", + "span-9": "span 9 / span 9", + "span-10": "span 10 / span 10", + "span-11": "span 11 / span 11", + "span-12": "span 12 / span 12", + "span-full": "1 / -1", + }, + gridColumnEnd: { + auto: "auto", + 1: "1", + 2: "2", + 3: "3", + 4: "4", + 5: "5", + 6: "6", + 7: "7", + 8: "8", + 9: "9", + 10: "10", + 11: "11", + 12: "12", + 13: "13", + }, + gridColumnStart: { + auto: "auto", + 1: "1", + 2: "2", + 3: "3", + 4: "4", + 5: "5", + 6: "6", + 7: "7", + 8: "8", + 9: "9", + 10: "10", + 11: "11", + 12: "12", + 13: "13", + }, + gridRow: { + auto: "auto", + "span-1": "span 1 / span 1", + "span-2": "span 2 / span 2", + "span-3": "span 3 / span 3", + "span-4": "span 4 / span 4", + "span-5": "span 5 / span 5", + "span-6": "span 6 / span 6", + "span-7": "span 7 / span 7", + "span-8": "span 8 / span 8", + "span-9": "span 9 / span 9", + "span-10": "span 10 / span 10", + "span-11": "span 11 / span 11", + "span-12": "span 12 / span 12", + "span-full": "1 / -1", + }, + gridRowEnd: { + auto: "auto", + 1: "1", + 2: "2", + 3: "3", + 4: "4", + 5: "5", + 6: "6", + 7: "7", + 8: "8", + 9: "9", + 10: "10", + 11: "11", + 12: "12", + 13: "13", + }, + gridRowStart: { + auto: "auto", + 1: "1", + 2: "2", + 3: "3", + 4: "4", + 5: "5", + 6: "6", + 7: "7", + 8: "8", + 9: "9", + 10: "10", + 11: "11", + 12: "12", + 13: "13", + }, + gridTemplateColumns: { + none: "none", + subgrid: "subgrid", + 1: "repeat(1, minmax(0, 1fr))", + 2: "repeat(2, minmax(0, 1fr))", + 3: "repeat(3, minmax(0, 1fr))", + 4: "repeat(4, minmax(0, 1fr))", + 5: "repeat(5, minmax(0, 1fr))", + 6: "repeat(6, minmax(0, 1fr))", + 7: "repeat(7, minmax(0, 1fr))", + 8: "repeat(8, minmax(0, 1fr))", + 9: "repeat(9, minmax(0, 1fr))", + 10: "repeat(10, minmax(0, 1fr))", + 11: "repeat(11, minmax(0, 1fr))", + 12: "repeat(12, minmax(0, 1fr))", + }, + gridTemplateRows: { + none: "none", + subgrid: "subgrid", + 1: "repeat(1, minmax(0, 1fr))", + 2: "repeat(2, minmax(0, 1fr))", + 3: "repeat(3, minmax(0, 1fr))", + 4: "repeat(4, minmax(0, 1fr))", + 5: "repeat(5, minmax(0, 1fr))", + 6: "repeat(6, minmax(0, 1fr))", + 7: "repeat(7, minmax(0, 1fr))", + 8: "repeat(8, minmax(0, 1fr))", + 9: "repeat(9, minmax(0, 1fr))", + 10: "repeat(10, minmax(0, 1fr))", + 11: "repeat(11, minmax(0, 1fr))", + 12: "repeat(12, minmax(0, 1fr))", + }, + height: ({ theme: r }) => ({ + auto: "auto", + ...r("spacing"), + "1/2": "50%", + "1/3": "33.333333%", + "2/3": "66.666667%", + "1/4": "25%", + "2/4": "50%", + "3/4": "75%", + "1/5": "20%", + "2/5": "40%", + "3/5": "60%", + "4/5": "80%", + "1/6": "16.666667%", + "2/6": "33.333333%", + "3/6": "50%", + "4/6": "66.666667%", + "5/6": "83.333333%", + full: "100%", + screen: "100vh", + svh: "100svh", + lvh: "100lvh", + dvh: "100dvh", + min: "min-content", + max: "max-content", + fit: "fit-content", + }), + hueRotate: { 0: "0deg", 15: "15deg", 30: "30deg", 60: "60deg", 90: "90deg", 180: "180deg" }, + inset: ({ theme: r }) => ({ + auto: "auto", + ...r("spacing"), + "1/2": "50%", + "1/3": "33.333333%", + "2/3": "66.666667%", + "1/4": "25%", + "2/4": "50%", + "3/4": "75%", + full: "100%", + }), + invert: { 0: "0", DEFAULT: "100%" }, + keyframes: { + spin: { to: { transform: "rotate(360deg)" } }, + ping: { "75%, 100%": { transform: "scale(2)", opacity: "0" } }, + pulse: { "50%": { opacity: ".5" } }, + bounce: { + "0%, 100%": { + transform: "translateY(-25%)", + animationTimingFunction: "cubic-bezier(0.8,0,1,1)", + }, + "50%": { transform: "none", animationTimingFunction: "cubic-bezier(0,0,0.2,1)" }, + }, + }, + letterSpacing: { + tighter: "-0.05em", + tight: "-0.025em", + normal: "0em", + wide: "0.025em", + wider: "0.05em", + widest: "0.1em", + }, + lineHeight: { + none: "1", + tight: "1.25", + snug: "1.375", + normal: "1.5", + relaxed: "1.625", + loose: "2", + 3: ".75rem", + 4: "1rem", + 5: "1.25rem", + 6: "1.5rem", + 7: "1.75rem", + 8: "2rem", + 9: "2.25rem", + 10: "2.5rem", + }, + listStyleType: { none: "none", disc: "disc", decimal: "decimal" }, + listStyleImage: { none: "none" }, + margin: ({ theme: r }) => ({ auto: "auto", ...r("spacing") }), + lineClamp: { 1: "1", 2: "2", 3: "3", 4: "4", 5: "5", 6: "6" }, + maxHeight: ({ theme: r }) => ({ + ...r("spacing"), + none: "none", + full: "100%", + screen: "100vh", + svh: "100svh", + lvh: "100lvh", + dvh: "100dvh", + min: "min-content", + max: "max-content", + fit: "fit-content", + }), + maxWidth: ({ theme: r, breakpoints: e }) => ({ + ...r("spacing"), + none: "none", + xs: "20rem", + sm: "24rem", + md: "28rem", + lg: "32rem", + xl: "36rem", + "2xl": "42rem", + "3xl": "48rem", + "4xl": "56rem", + "5xl": "64rem", + "6xl": "72rem", + "7xl": "80rem", + full: "100%", + min: "min-content", + max: "max-content", + fit: "fit-content", + prose: "65ch", + ...e(r("screens")), + }), + minHeight: ({ theme: r }) => ({ + ...r("spacing"), + full: "100%", + screen: "100vh", + svh: "100svh", + lvh: "100lvh", + dvh: "100dvh", + min: "min-content", + max: "max-content", + fit: "fit-content", + }), + minWidth: ({ theme: r }) => ({ + ...r("spacing"), + full: "100%", + min: "min-content", + max: "max-content", + fit: "fit-content", + }), + objectPosition: { + bottom: "bottom", + center: "center", + left: "left", + "left-bottom": "left bottom", + "left-top": "left top", + right: "right", + "right-bottom": "right bottom", + "right-top": "right top", + top: "top", + }, + opacity: { + 0: "0", + 5: "0.05", + 10: "0.1", + 15: "0.15", + 20: "0.2", + 25: "0.25", + 30: "0.3", + 35: "0.35", + 40: "0.4", + 45: "0.45", + 50: "0.5", + 55: "0.55", + 60: "0.6", + 65: "0.65", + 70: "0.7", + 75: "0.75", + 80: "0.8", + 85: "0.85", + 90: "0.9", + 95: "0.95", + 100: "1", + }, + order: { + first: "-9999", + last: "9999", + none: "0", + 1: "1", + 2: "2", + 3: "3", + 4: "4", + 5: "5", + 6: "6", + 7: "7", + 8: "8", + 9: "9", + 10: "10", + 11: "11", + 12: "12", + }, + outlineColor: ({ theme: r }) => r("colors"), + outlineOffset: { 0: "0px", 1: "1px", 2: "2px", 4: "4px", 8: "8px" }, + outlineWidth: { 0: "0px", 1: "1px", 2: "2px", 4: "4px", 8: "8px" }, + padding: ({ theme: r }) => r("spacing"), + placeholderColor: ({ theme: r }) => r("colors"), + placeholderOpacity: ({ theme: r }) => r("opacity"), + ringColor: ({ theme: r }) => ({ DEFAULT: r("colors.blue.500", "#3b82f6"), ...r("colors") }), + ringOffsetColor: ({ theme: r }) => r("colors"), + ringOffsetWidth: { 0: "0px", 1: "1px", 2: "2px", 4: "4px", 8: "8px" }, + ringOpacity: ({ theme: r }) => ({ DEFAULT: "0.5", ...r("opacity") }), + ringWidth: { DEFAULT: "3px", 0: "0px", 1: "1px", 2: "2px", 4: "4px", 8: "8px" }, + rotate: { + 0: "0deg", + 1: "1deg", + 2: "2deg", + 3: "3deg", + 6: "6deg", + 12: "12deg", + 45: "45deg", + 90: "90deg", + 180: "180deg", + }, + saturate: { 0: "0", 50: ".5", 100: "1", 150: "1.5", 200: "2" }, + scale: { + 0: "0", + 50: ".5", + 75: ".75", + 90: ".9", + 95: ".95", + 100: "1", + 105: "1.05", + 110: "1.1", + 125: "1.25", + 150: "1.5", + }, + screens: { sm: "640px", md: "768px", lg: "1024px", xl: "1280px", "2xl": "1536px" }, + scrollMargin: ({ theme: r }) => ({ ...r("spacing") }), + scrollPadding: ({ theme: r }) => r("spacing"), + sepia: { 0: "0", DEFAULT: "100%" }, + skew: { 0: "0deg", 1: "1deg", 2: "2deg", 3: "3deg", 6: "6deg", 12: "12deg" }, + space: ({ theme: r }) => ({ ...r("spacing") }), + spacing: { + px: "1px", + 0: "0px", + 0.5: "0.125rem", + 1: "0.25rem", + 1.5: "0.375rem", + 2: "0.5rem", + 2.5: "0.625rem", + 3: "0.75rem", + 3.5: "0.875rem", + 4: "1rem", + 5: "1.25rem", + 6: "1.5rem", + 7: "1.75rem", + 8: "2rem", + 9: "2.25rem", + 10: "2.5rem", + 11: "2.75rem", + 12: "3rem", + 14: "3.5rem", + 16: "4rem", + 20: "5rem", + 24: "6rem", + 28: "7rem", + 32: "8rem", + 36: "9rem", + 40: "10rem", + 44: "11rem", + 48: "12rem", + 52: "13rem", + 56: "14rem", + 60: "15rem", + 64: "16rem", + 72: "18rem", + 80: "20rem", + 96: "24rem", + }, + stroke: ({ theme: r }) => ({ none: "none", ...r("colors") }), + strokeWidth: { 0: "0", 1: "1", 2: "2" }, + supports: {}, + data: {}, + textColor: ({ theme: r }) => r("colors"), + textDecorationColor: ({ theme: r }) => r("colors"), + textDecorationThickness: { + auto: "auto", + "from-font": "from-font", + 0: "0px", + 1: "1px", + 2: "2px", + 4: "4px", + 8: "8px", + }, + textIndent: ({ theme: r }) => ({ ...r("spacing") }), + textOpacity: ({ theme: r }) => r("opacity"), + textUnderlineOffset: { auto: "auto", 0: "0px", 1: "1px", 2: "2px", 4: "4px", 8: "8px" }, + transformOrigin: { + center: "center", + top: "top", + "top-right": "top right", + right: "right", + "bottom-right": "bottom right", + bottom: "bottom", + "bottom-left": "bottom left", + left: "left", + "top-left": "top left", + }, + transitionDelay: { + 0: "0s", + 75: "75ms", + 100: "100ms", + 150: "150ms", + 200: "200ms", + 300: "300ms", + 500: "500ms", + 700: "700ms", + 1e3: "1000ms", + }, + transitionDuration: { + DEFAULT: "150ms", + 0: "0s", + 75: "75ms", + 100: "100ms", + 150: "150ms", + 200: "200ms", + 300: "300ms", + 500: "500ms", + 700: "700ms", + 1e3: "1000ms", + }, + transitionProperty: { + none: "none", + all: "all", + DEFAULT: + "color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter", + colors: "color, background-color, border-color, text-decoration-color, fill, stroke", + opacity: "opacity", + shadow: "box-shadow", + transform: "transform", + }, + transitionTimingFunction: { + DEFAULT: "cubic-bezier(0.4, 0, 0.2, 1)", + linear: "linear", + in: "cubic-bezier(0.4, 0, 1, 1)", + out: "cubic-bezier(0, 0, 0.2, 1)", + "in-out": "cubic-bezier(0.4, 0, 0.2, 1)", + }, + translate: ({ theme: r }) => ({ + ...r("spacing"), + "1/2": "50%", + "1/3": "33.333333%", + "2/3": "66.666667%", + "1/4": "25%", + "2/4": "50%", + "3/4": "75%", + full: "100%", + }), + size: ({ theme: r }) => ({ + auto: "auto", + ...r("spacing"), + "1/2": "50%", + "1/3": "33.333333%", + "2/3": "66.666667%", + "1/4": "25%", + "2/4": "50%", + "3/4": "75%", + "1/5": "20%", + "2/5": "40%", + "3/5": "60%", + "4/5": "80%", + "1/6": "16.666667%", + "2/6": "33.333333%", + "3/6": "50%", + "4/6": "66.666667%", + "5/6": "83.333333%", + "1/12": "8.333333%", + "2/12": "16.666667%", + "3/12": "25%", + "4/12": "33.333333%", + "5/12": "41.666667%", + "6/12": "50%", + "7/12": "58.333333%", + "8/12": "66.666667%", + "9/12": "75%", + "10/12": "83.333333%", + "11/12": "91.666667%", + full: "100%", + min: "min-content", + max: "max-content", + fit: "fit-content", + }), + width: ({ theme: r }) => ({ + auto: "auto", + ...r("spacing"), + "1/2": "50%", + "1/3": "33.333333%", + "2/3": "66.666667%", + "1/4": "25%", + "2/4": "50%", + "3/4": "75%", + "1/5": "20%", + "2/5": "40%", + "3/5": "60%", + "4/5": "80%", + "1/6": "16.666667%", + "2/6": "33.333333%", + "3/6": "50%", + "4/6": "66.666667%", + "5/6": "83.333333%", + "1/12": "8.333333%", + "2/12": "16.666667%", + "3/12": "25%", + "4/12": "33.333333%", + "5/12": "41.666667%", + "6/12": "50%", + "7/12": "58.333333%", + "8/12": "66.666667%", + "9/12": "75%", + "10/12": "83.333333%", + "11/12": "91.666667%", + full: "100%", + screen: "100vw", + svw: "100svw", + lvw: "100lvw", + dvw: "100dvw", + min: "min-content", + max: "max-content", + fit: "fit-content", + }), + willChange: { auto: "auto", scroll: "scroll-position", contents: "contents", transform: "transform" }, + zIndex: { auto: "auto", 0: "0", 10: "10", 20: "20", 30: "30", 40: "40", 50: "50" }, + }, + plugins: [], + }; + }); + function Ci(r) { + let e = (r?.presets ?? [af.default]) + .slice() + .reverse() + .flatMap((n) => Ci(n instanceof Function ? n() : n)), + t = { + respectDefaultRingColorOpacity: { + theme: { ringColor: ({ theme: n }) => ({ DEFAULT: "#3b82f67f", ...n("colors") }) }, + }, + disableColorOpacityUtilitiesByDefault: { + corePlugins: { + backgroundOpacity: !1, + borderOpacity: !1, + divideOpacity: !1, + placeholderOpacity: !1, + ringOpacity: !1, + textOpacity: !1, + }, + }, + }, + i = Object.keys(t) + .filter((n) => K(r, n)) + .map((n) => t[n]); + return [r, ...i, ...e]; + } + var af, + of = C(() => { + l(); + af = X(Si()); + je(); + }); + var lf = {}; + Ae(lf, { default: () => gr }); + function gr(...r) { + let [, ...e] = Ci(r[0]); + return vs([...r, ...e]); + } + var xs = C(() => { + l(); + nf(); + of(); + }); + var uf = {}; + Ae(uf, { default: () => Z }); + var Z, + bt = C(() => { + l(); + Z = { resolve: (r) => r, extname: (r) => "." + r.split(".").pop() }; + }); + function Ai(r) { + return typeof r == "object" && r !== null; + } + function w0(r) { + return Object.keys(r).length === 0; + } + function ff(r) { + return typeof r == "string" || r instanceof String; + } + function ks(r) { + return Ai(r) && r.config === void 0 && !w0(r) + ? null + : Ai(r) && r.config !== void 0 && ff(r.config) + ? Z.resolve(r.config) + : Ai(r) && r.config !== void 0 && Ai(r.config) + ? null + : ff(r) + ? Z.resolve(r) + : b0(); + } + function b0() { + for (let r of y0) + try { + let e = Z.resolve(r); + return (te.accessSync(e), e); + } catch (e) {} + return null; + } + var y0, + cf = C(() => { + l(); + ze(); + bt(); + y0 = ["./tailwind.config.js", "./tailwind.config.cjs", "./tailwind.config.mjs", "./tailwind.config.ts"]; + }); + var pf = {}; + Ae(pf, { default: () => Ss }); + var Ss, + Cs = C(() => { + l(); + Ss = { parse: (r) => ({ href: r }) }; + }); + var As = v(() => { + l(); + }); + var _i = v((d3, mf) => { + l(); + ("use strict"); + var df = (hi(), Ou), + hf = As(), + Tt = class extends Error { + constructor(e, t, i, n, a, s) { + super(e); + ((this.name = "CssSyntaxError"), + (this.reason = e), + a && (this.file = a), + n && (this.source = n), + s && (this.plugin = s), + typeof t != "undefined" && + typeof i != "undefined" && + (typeof t == "number" + ? ((this.line = t), (this.column = i)) + : ((this.line = t.line), + (this.column = t.column), + (this.endLine = i.line), + (this.endColumn = i.column))), + this.setMessage(), + Error.captureStackTrace && Error.captureStackTrace(this, Tt)); + } + setMessage() { + ((this.message = this.plugin ? this.plugin + ": " : ""), + (this.message += this.file ? this.file : ""), + typeof this.line != "undefined" && (this.message += ":" + this.line + ":" + this.column), + (this.message += ": " + this.reason)); + } + showSourceCode(e) { + if (!this.source) return ""; + let t = this.source; + (e == null && (e = df.isColorSupported), hf && e && (t = hf(t))); + let i = t.split(/\r?\n/), + n = Math.max(this.line - 3, 0), + a = Math.min(this.line + 2, i.length), + s = String(a).length, + o, + u; + if (e) { + let { bold: c, red: f, gray: d } = df.createColors(!0); + ((o = (p) => c(f(p))), (u = (p) => d(p))); + } else o = u = (c) => c; + return i.slice(n, a).map((c, f) => { + let d = n + 1 + f, + p = " " + (" " + d).slice(-s) + " | "; + if (d === this.line) { + let m = u(p.replace(/\d/g, " ")) + c.slice(0, this.column - 1).replace(/[^\t]/g, " "); + return ( + o(">") + + u(p) + + c + + ` + ` + + m + + o("^") + ); + } + return " " + u(p) + c; + }).join(` +`); + } + toString() { + let e = this.showSourceCode(); + return ( + e && + (e = + ` -`+e+` -`),this.name+": "+this.message+e}};mf.exports=Tt;Tt.default=Tt});var Oi=v((h3,_s)=>{l();"use strict";_s.exports.isClean=Symbol("isClean");_s.exports.my=Symbol("my")});var Os=v((m3,yf)=>{l();"use strict";var gf={colon:": ",indent:" ",beforeDecl:` -`,beforeRule:` -`,beforeOpen:" ",beforeClose:` -`,beforeComment:` -`,after:` -`,emptyBody:"",commentLeft:" ",commentRight:" ",semicolon:!1};function v0(r){return r[0].toUpperCase()+r.slice(1)}var Ei=class{constructor(e){this.builder=e}stringify(e,t){if(!this[e.type])throw new Error("Unknown AST node type "+e.type+". Maybe you need to change PostCSS stringifier.");this[e.type](e,t)}document(e){this.body(e)}root(e){this.body(e),e.raws.after&&this.builder(e.raws.after)}comment(e){let t=this.raw(e,"left","commentLeft"),i=this.raw(e,"right","commentRight");this.builder("/*"+t+e.text+i+"*/",e)}decl(e,t){let i=this.raw(e,"between","colon"),n=e.prop+i+this.rawValue(e,"value");e.important&&(n+=e.raws.important||" !important"),t&&(n+=";"),this.builder(n,e)}rule(e){this.block(e,this.rawValue(e,"selector")),e.raws.ownSemicolon&&this.builder(e.raws.ownSemicolon,e,"end")}atrule(e,t){let i="@"+e.name,n=e.params?this.rawValue(e,"params"):"";if(typeof e.raws.afterName!="undefined"?i+=e.raws.afterName:n&&(i+=" "),e.nodes)this.block(e,i+n);else{let a=(e.raws.between||"")+(t?";":"");this.builder(i+n+a,e)}}body(e){let t=e.nodes.length-1;for(;t>0&&e.nodes[t].type==="comment";)t-=1;let i=this.raw(e,"semicolon");for(let n=0;n{if(n=u.raws[t],typeof n!="undefined")return!1})}return typeof n=="undefined"&&(n=gf[i]),s.rawCache[i]=n,n}rawSemicolon(e){let t;return e.walk(i=>{if(i.nodes&&i.nodes.length&&i.last.type==="decl"&&(t=i.raws.semicolon,typeof t!="undefined"))return!1}),t}rawEmptyBody(e){let t;return e.walk(i=>{if(i.nodes&&i.nodes.length===0&&(t=i.raws.after,typeof t!="undefined"))return!1}),t}rawIndent(e){if(e.raws.indent)return e.raws.indent;let t;return e.walk(i=>{let n=i.parent;if(n&&n!==e&&n.parent&&n.parent===e&&typeof i.raws.before!="undefined"){let a=i.raws.before.split(` -`);return t=a[a.length-1],t=t.replace(/\S/g,""),!1}}),t}rawBeforeComment(e,t){let i;return e.walkComments(n=>{if(typeof n.raws.before!="undefined")return i=n.raws.before,i.includes(` -`)&&(i=i.replace(/[^\n]+$/,"")),!1}),typeof i=="undefined"?i=this.raw(t,null,"beforeDecl"):i&&(i=i.replace(/\S/g,"")),i}rawBeforeDecl(e,t){let i;return e.walkDecls(n=>{if(typeof n.raws.before!="undefined")return i=n.raws.before,i.includes(` -`)&&(i=i.replace(/[^\n]+$/,"")),!1}),typeof i=="undefined"?i=this.raw(t,null,"beforeRule"):i&&(i=i.replace(/\S/g,"")),i}rawBeforeRule(e){let t;return e.walk(i=>{if(i.nodes&&(i.parent!==e||e.first!==i)&&typeof i.raws.before!="undefined")return t=i.raws.before,t.includes(` -`)&&(t=t.replace(/[^\n]+$/,"")),!1}),t&&(t=t.replace(/\S/g,"")),t}rawBeforeClose(e){let t;return e.walk(i=>{if(i.nodes&&i.nodes.length>0&&typeof i.raws.after!="undefined")return t=i.raws.after,t.includes(` -`)&&(t=t.replace(/[^\n]+$/,"")),!1}),t&&(t=t.replace(/\S/g,"")),t}rawBeforeOpen(e){let t;return e.walk(i=>{if(i.type!=="decl"&&(t=i.raws.between,typeof t!="undefined"))return!1}),t}rawColon(e){let t;return e.walkDecls(i=>{if(typeof i.raws.between!="undefined")return t=i.raws.between.replace(/[^\s:]/g,""),!1}),t}beforeAfter(e,t){let i;e.type==="decl"?i=this.raw(e,null,"beforeDecl"):e.type==="comment"?i=this.raw(e,null,"beforeComment"):t==="before"?i=this.raw(e,null,"beforeRule"):i=this.raw(e,null,"beforeClose");let n=e.parent,a=0;for(;n&&n.type!=="root";)a+=1,n=n.parent;if(i.includes(` -`)){let s=this.raw(e,null,"indent");if(s.length)for(let o=0;o{l();"use strict";var x0=Os();function Es(r,e){new x0(e).stringify(r)}wf.exports=Es;Es.default=Es});var wr=v((y3,bf)=>{l();"use strict";var{isClean:Ti,my:k0}=Oi(),S0=_i(),C0=Os(),A0=yr();function Ts(r,e){let t=new r.constructor;for(let i in r){if(!Object.prototype.hasOwnProperty.call(r,i)||i==="proxyCache")continue;let n=r[i],a=typeof n;i==="parent"&&a==="object"?e&&(t[i]=e):i==="source"?t[i]=n:Array.isArray(n)?t[i]=n.map(s=>Ts(s,t)):(a==="object"&&n!==null&&(n=Ts(n)),t[i]=n)}return t}var Pi=class{constructor(e={}){this.raws={},this[Ti]=!1,this[k0]=!0;for(let t in e)if(t==="nodes"){this.nodes=[];for(let i of e[t])typeof i.clone=="function"?this.append(i.clone()):this.append(i)}else this[t]=e[t]}error(e,t={}){if(this.source){let{start:i,end:n}=this.rangeBy(t);return this.source.input.error(e,{line:i.line,column:i.column},{line:n.line,column:n.column},t)}return new S0(e)}warn(e,t,i){let n={node:this};for(let a in i)n[a]=i[a];return e.warn(t,n)}remove(){return this.parent&&this.parent.removeChild(this),this.parent=void 0,this}toString(e=A0){e.stringify&&(e=e.stringify);let t="";return e(this,i=>{t+=i}),t}assign(e={}){for(let t in e)this[t]=e[t];return this}clone(e={}){let t=Ts(this);for(let i in e)t[i]=e[i];return t}cloneBefore(e={}){let t=this.clone(e);return this.parent.insertBefore(this,t),t}cloneAfter(e={}){let t=this.clone(e);return this.parent.insertAfter(this,t),t}replaceWith(...e){if(this.parent){let t=this,i=!1;for(let n of e)n===this?i=!0:i?(this.parent.insertAfter(t,n),t=n):this.parent.insertBefore(t,n);i||this.remove()}return this}next(){if(!this.parent)return;let e=this.parent.index(this);return this.parent.nodes[e+1]}prev(){if(!this.parent)return;let e=this.parent.index(this);return this.parent.nodes[e-1]}before(e){return this.parent.insertBefore(this,e),this}after(e){return this.parent.insertAfter(this,e),this}root(){let e=this;for(;e.parent&&e.parent.type!=="document";)e=e.parent;return e}raw(e,t){return new C0().raw(this,e,t)}cleanRaws(e){delete this.raws.before,delete this.raws.after,e||delete this.raws.between}toJSON(e,t){let i={},n=t==null;t=t||new Map;let a=0;for(let s in this){if(!Object.prototype.hasOwnProperty.call(this,s)||s==="parent"||s==="proxyCache")continue;let o=this[s];if(Array.isArray(o))i[s]=o.map(u=>typeof u=="object"&&u.toJSON?u.toJSON(null,t):u);else if(typeof o=="object"&&o.toJSON)i[s]=o.toJSON(null,t);else if(s==="source"){let u=t.get(o.input);u==null&&(u=a,t.set(o.input,a),a++),i[s]={inputId:u,start:o.start,end:o.end}}else i[s]=o}return n&&(i.inputs=[...t.keys()].map(s=>s.toJSON())),i}positionInside(e){let t=this.toString(),i=this.source.start.column,n=this.source.start.line;for(let a=0;ae.root().toProxy():e[t]}}}toProxy(){return this.proxyCache||(this.proxyCache=new Proxy(this,this.getProxyProcessor())),this.proxyCache}addToError(e){if(e.postcssNode=this,e.stack&&this.source&&/\n\s{4}at /.test(e.stack)){let t=this.source;e.stack=e.stack.replace(/\n\s{4}at /,`$&${t.input.from}:${t.start.line}:${t.start.column}$&`)}return e}markDirty(){if(this[Ti]){this[Ti]=!1;let e=this;for(;e=e.parent;)e[Ti]=!1}}get proxyOf(){return this}};bf.exports=Pi;Pi.default=Pi});var br=v((w3,vf)=>{l();"use strict";var _0=wr(),Di=class extends _0{constructor(e){e&&typeof e.value!="undefined"&&typeof e.value!="string"&&(e={...e,value:String(e.value)});super(e);this.type="decl"}get variable(){return this.prop.startsWith("--")||this.prop[0]==="$"}};vf.exports=Di;Di.default=Di});var Ps=v((b3,xf)=>{l();xf.exports=function(r,e){return{generate:()=>{let t="";return r(e,i=>{t+=i}),[t]}}}});var vr=v((v3,kf)=>{l();"use strict";var O0=wr(),Ii=class extends O0{constructor(e){super(e);this.type="comment"}};kf.exports=Ii;Ii.default=Ii});var nt=v((x3,Df)=>{l();"use strict";var{isClean:Sf,my:Cf}=Oi(),Af=br(),_f=vr(),E0=wr(),Of,Ds,Is,Ef;function Tf(r){return r.map(e=>(e.nodes&&(e.nodes=Tf(e.nodes)),delete e.source,e))}function Pf(r){if(r[Sf]=!1,r.proxyOf.nodes)for(let e of r.proxyOf.nodes)Pf(e)}var we=class extends E0{push(e){return e.parent=this,this.proxyOf.nodes.push(e),this}each(e){if(!this.proxyOf.nodes)return;let t=this.getIterator(),i,n;for(;this.indexes[t]{let n;try{n=e(t,i)}catch(a){throw t.addToError(a)}return n!==!1&&t.walk&&(n=t.walk(e)),n})}walkDecls(e,t){return t?e instanceof RegExp?this.walk((i,n)=>{if(i.type==="decl"&&e.test(i.prop))return t(i,n)}):this.walk((i,n)=>{if(i.type==="decl"&&i.prop===e)return t(i,n)}):(t=e,this.walk((i,n)=>{if(i.type==="decl")return t(i,n)}))}walkRules(e,t){return t?e instanceof RegExp?this.walk((i,n)=>{if(i.type==="rule"&&e.test(i.selector))return t(i,n)}):this.walk((i,n)=>{if(i.type==="rule"&&i.selector===e)return t(i,n)}):(t=e,this.walk((i,n)=>{if(i.type==="rule")return t(i,n)}))}walkAtRules(e,t){return t?e instanceof RegExp?this.walk((i,n)=>{if(i.type==="atrule"&&e.test(i.name))return t(i,n)}):this.walk((i,n)=>{if(i.type==="atrule"&&i.name===e)return t(i,n)}):(t=e,this.walk((i,n)=>{if(i.type==="atrule")return t(i,n)}))}walkComments(e){return this.walk((t,i)=>{if(t.type==="comment")return e(t,i)})}append(...e){for(let t of e){let i=this.normalize(t,this.last);for(let n of i)this.proxyOf.nodes.push(n)}return this.markDirty(),this}prepend(...e){e=e.reverse();for(let t of e){let i=this.normalize(t,this.first,"prepend").reverse();for(let n of i)this.proxyOf.nodes.unshift(n);for(let n in this.indexes)this.indexes[n]=this.indexes[n]+i.length}return this.markDirty(),this}cleanRaws(e){if(super.cleanRaws(e),this.nodes)for(let t of this.nodes)t.cleanRaws(e)}insertBefore(e,t){let i=this.index(e),n=i===0?"prepend":!1,a=this.normalize(t,this.proxyOf.nodes[i],n).reverse();i=this.index(e);for(let o of a)this.proxyOf.nodes.splice(i,0,o);let s;for(let o in this.indexes)s=this.indexes[o],i<=s&&(this.indexes[o]=s+a.length);return this.markDirty(),this}insertAfter(e,t){let i=this.index(e),n=this.normalize(t,this.proxyOf.nodes[i]).reverse();i=this.index(e);for(let s of n)this.proxyOf.nodes.splice(i+1,0,s);let a;for(let s in this.indexes)a=this.indexes[s],i=e&&(this.indexes[i]=t-1);return this.markDirty(),this}removeAll(){for(let e of this.proxyOf.nodes)e.parent=void 0;return this.proxyOf.nodes=[],this.markDirty(),this}replaceValues(e,t,i){return i||(i=t,t={}),this.walkDecls(n=>{t.props&&!t.props.includes(n.prop)||t.fast&&!n.value.includes(t.fast)||(n.value=n.value.replace(e,i))}),this.markDirty(),this}every(e){return this.nodes.every(e)}some(e){return this.nodes.some(e)}index(e){return typeof e=="number"?e:(e.proxyOf&&(e=e.proxyOf),this.proxyOf.nodes.indexOf(e))}get first(){if(!!this.proxyOf.nodes)return this.proxyOf.nodes[0]}get last(){if(!!this.proxyOf.nodes)return this.proxyOf.nodes[this.proxyOf.nodes.length-1]}normalize(e,t){if(typeof e=="string")e=Tf(Of(e).nodes);else if(Array.isArray(e)){e=e.slice(0);for(let n of e)n.parent&&n.parent.removeChild(n,"ignore")}else if(e.type==="root"&&this.type!=="document"){e=e.nodes.slice(0);for(let n of e)n.parent&&n.parent.removeChild(n,"ignore")}else if(e.type)e=[e];else if(e.prop){if(typeof e.value=="undefined")throw new Error("Value field is missed in node creation");typeof e.value!="string"&&(e.value=String(e.value)),e=[new Af(e)]}else if(e.selector)e=[new Ds(e)];else if(e.name)e=[new Is(e)];else if(e.text)e=[new _f(e)];else throw new Error("Unknown node type in node creation");return e.map(n=>(n[Cf]||we.rebuild(n),n=n.proxyOf,n.parent&&n.parent.removeChild(n),n[Sf]&&Pf(n),typeof n.raws.before=="undefined"&&t&&typeof t.raws.before!="undefined"&&(n.raws.before=t.raws.before.replace(/\S/g,"")),n.parent=this.proxyOf,n))}getProxyProcessor(){return{set(e,t,i){return e[t]===i||(e[t]=i,(t==="name"||t==="params"||t==="selector")&&e.markDirty()),!0},get(e,t){return t==="proxyOf"?e:e[t]?t==="each"||typeof t=="string"&&t.startsWith("walk")?(...i)=>e[t](...i.map(n=>typeof n=="function"?(a,s)=>n(a.toProxy(),s):n)):t==="every"||t==="some"?i=>e[t]((n,...a)=>i(n.toProxy(),...a)):t==="root"?()=>e.root().toProxy():t==="nodes"?e.nodes.map(i=>i.toProxy()):t==="first"||t==="last"?e[t].toProxy():e[t]:e[t]}}}getIterator(){this.lastEach||(this.lastEach=0),this.indexes||(this.indexes={}),this.lastEach+=1;let e=this.lastEach;return this.indexes[e]=0,e}};we.registerParse=r=>{Of=r};we.registerRule=r=>{Ds=r};we.registerAtRule=r=>{Is=r};we.registerRoot=r=>{Ef=r};Df.exports=we;we.default=we;we.rebuild=r=>{r.type==="atrule"?Object.setPrototypeOf(r,Is.prototype):r.type==="rule"?Object.setPrototypeOf(r,Ds.prototype):r.type==="decl"?Object.setPrototypeOf(r,Af.prototype):r.type==="comment"?Object.setPrototypeOf(r,_f.prototype):r.type==="root"&&Object.setPrototypeOf(r,Ef.prototype),r[Cf]=!0,r.nodes&&r.nodes.forEach(e=>{we.rebuild(e)})}});var qi=v((k3,Rf)=>{l();"use strict";var T0=nt(),If,qf,Pt=class extends T0{constructor(e){super({type:"document",...e});this.nodes||(this.nodes=[])}toResult(e={}){return new If(new qf,this,e).stringify()}};Pt.registerLazyResult=r=>{If=r};Pt.registerProcessor=r=>{qf=r};Rf.exports=Pt;Pt.default=Pt});var qs=v((S3,Bf)=>{l();"use strict";var Mf={};Bf.exports=function(e){Mf[e]||(Mf[e]=!0,typeof console!="undefined"&&console.warn&&console.warn(e))}});var Rs=v((C3,Ff)=>{l();"use strict";var Ri=class{constructor(e,t={}){if(this.type="warning",this.text=e,t.node&&t.node.source){let i=t.node.rangeBy(t);this.line=i.start.line,this.column=i.start.column,this.endLine=i.end.line,this.endColumn=i.end.column}for(let i in t)this[i]=t[i]}toString(){return this.node?this.node.error(this.text,{plugin:this.plugin,index:this.index,word:this.word}).message:this.plugin?this.plugin+": "+this.text:this.text}};Ff.exports=Ri;Ri.default=Ri});var Bi=v((A3,Lf)=>{l();"use strict";var P0=Rs(),Mi=class{constructor(e,t,i){this.processor=e,this.messages=[],this.root=t,this.opts=i,this.css=void 0,this.map=void 0}toString(){return this.css}warn(e,t={}){t.plugin||this.lastPlugin&&this.lastPlugin.postcssPlugin&&(t.plugin=this.lastPlugin.postcssPlugin);let i=new P0(e,t);return this.messages.push(i),i}warnings(){return this.messages.filter(e=>e.type==="warning")}get content(){return this.css}};Lf.exports=Mi;Mi.default=Mi});var Vf=v((_3,jf)=>{l();"use strict";var Ms="'".charCodeAt(0),Nf='"'.charCodeAt(0),Fi="\\".charCodeAt(0),$f="/".charCodeAt(0),Li=` -`.charCodeAt(0),xr=" ".charCodeAt(0),Ni="\f".charCodeAt(0),$i=" ".charCodeAt(0),zi="\r".charCodeAt(0),D0="[".charCodeAt(0),I0="]".charCodeAt(0),q0="(".charCodeAt(0),R0=")".charCodeAt(0),M0="{".charCodeAt(0),B0="}".charCodeAt(0),F0=";".charCodeAt(0),L0="*".charCodeAt(0),N0=":".charCodeAt(0),$0="@".charCodeAt(0),ji=/[\t\n\f\r "#'()/;[\\\]{}]/g,Vi=/[\t\n\f\r !"#'():;@[\\\]{}]|\/(?=\*)/g,z0=/.[\n"'(/\\]/,zf=/[\da-f]/i;jf.exports=function(e,t={}){let i=e.css.valueOf(),n=t.ignoreErrors,a,s,o,u,c,f,d,p,m,b,x=i.length,y=0,w=[],k=[];function S(){return y}function _(R){throw e.error("Unclosed "+R,y)}function E(){return k.length===0&&y>=x}function I(R){if(k.length)return k.pop();if(y>=x)return;let J=R?R.ignoreUnclosed:!1;switch(a=i.charCodeAt(y),a){case Li:case xr:case $i:case zi:case Ni:{s=y;do s+=1,a=i.charCodeAt(s);while(a===xr||a===Li||a===$i||a===zi||a===Ni);b=["space",i.slice(y,s)],y=s-1;break}case D0:case I0:case M0:case B0:case N0:case F0:case R0:{let ue=String.fromCharCode(a);b=[ue,ue,y];break}case q0:{if(p=w.length?w.pop()[1]:"",m=i.charCodeAt(y+1),p==="url"&&m!==Ms&&m!==Nf&&m!==xr&&m!==Li&&m!==$i&&m!==Ni&&m!==zi){s=y;do{if(f=!1,s=i.indexOf(")",s+1),s===-1)if(n||J){s=y;break}else _("bracket");for(d=s;i.charCodeAt(d-1)===Fi;)d-=1,f=!f}while(f);b=["brackets",i.slice(y,s+1),y,s],y=s}else s=i.indexOf(")",y+1),u=i.slice(y,s+1),s===-1||z0.test(u)?b=["(","(",y]:(b=["brackets",u,y,s],y=s);break}case Ms:case Nf:{o=a===Ms?"'":'"',s=y;do{if(f=!1,s=i.indexOf(o,s+1),s===-1)if(n||J){s=y+1;break}else _("string");for(d=s;i.charCodeAt(d-1)===Fi;)d-=1,f=!f}while(f);b=["string",i.slice(y,s+1),y,s],y=s;break}case $0:{ji.lastIndex=y+1,ji.test(i),ji.lastIndex===0?s=i.length-1:s=ji.lastIndex-2,b=["at-word",i.slice(y,s+1),y,s],y=s;break}case Fi:{for(s=y,c=!0;i.charCodeAt(s+1)===Fi;)s+=1,c=!c;if(a=i.charCodeAt(s+1),c&&a!==$f&&a!==xr&&a!==Li&&a!==$i&&a!==zi&&a!==Ni&&(s+=1,zf.test(i.charAt(s)))){for(;zf.test(i.charAt(s+1));)s+=1;i.charCodeAt(s+1)===xr&&(s+=1)}b=["word",i.slice(y,s+1),y,s],y=s;break}default:{a===$f&&i.charCodeAt(y+1)===L0?(s=i.indexOf("*/",y+2)+1,s===0&&(n||J?s=i.length:_("comment")),b=["comment",i.slice(y,s+1),y,s],y=s):(Vi.lastIndex=y+1,Vi.test(i),Vi.lastIndex===0?s=i.length-1:s=Vi.lastIndex-2,b=["word",i.slice(y,s+1),y,s],w.push(b),y=s);break}}return y++,b}function q(R){k.push(R)}return{back:q,nextToken:I,endOfFile:E,position:S}}});var Ui=v((O3,Wf)=>{l();"use strict";var Uf=nt(),kr=class extends Uf{constructor(e){super(e);this.type="atrule"}append(...e){return this.proxyOf.nodes||(this.nodes=[]),super.append(...e)}prepend(...e){return this.proxyOf.nodes||(this.nodes=[]),super.prepend(...e)}};Wf.exports=kr;kr.default=kr;Uf.registerAtRule(kr)});var Dt=v((E3,Qf)=>{l();"use strict";var Gf=nt(),Hf,Yf,vt=class extends Gf{constructor(e){super(e);this.type="root",this.nodes||(this.nodes=[])}removeChild(e,t){let i=this.index(e);return!t&&i===0&&this.nodes.length>1&&(this.nodes[1].raws.before=this.nodes[i].raws.before),super.removeChild(e)}normalize(e,t,i){let n=super.normalize(e);if(t){if(i==="prepend")this.nodes.length>1?t.raws.before=this.nodes[1].raws.before:delete t.raws.before;else if(this.first!==t)for(let a of n)a.raws.before=t.raws.before}return n}toResult(e={}){return new Hf(new Yf,this,e).stringify()}};vt.registerLazyResult=r=>{Hf=r};vt.registerProcessor=r=>{Yf=r};Qf.exports=vt;vt.default=vt;Gf.registerRoot(vt)});var Bs=v((T3,Jf)=>{l();"use strict";var Sr={split(r,e,t){let i=[],n="",a=!1,s=0,o=!1,u="",c=!1;for(let f of r)c?c=!1:f==="\\"?c=!0:o?f===u&&(o=!1):f==='"'||f==="'"?(o=!0,u=f):f==="("?s+=1:f===")"?s>0&&(s-=1):s===0&&e.includes(f)&&(a=!0),a?(n!==""&&i.push(n.trim()),n="",a=!1):n+=f;return(t||n!=="")&&i.push(n.trim()),i},space(r){let e=[" ",` -`," "];return Sr.split(r,e)},comma(r){return Sr.split(r,[","],!0)}};Jf.exports=Sr;Sr.default=Sr});var Wi=v((P3,Kf)=>{l();"use strict";var Xf=nt(),j0=Bs(),Cr=class extends Xf{constructor(e){super(e);this.type="rule",this.nodes||(this.nodes=[])}get selectors(){return j0.comma(this.selector)}set selectors(e){let t=this.selector?this.selector.match(/,\s*/):null,i=t?t[0]:","+this.raw("between","beforeOpen");this.selector=e.join(i)}};Kf.exports=Cr;Cr.default=Cr;Xf.registerRule(Cr)});var ic=v((D3,rc)=>{l();"use strict";var V0=br(),U0=Vf(),W0=vr(),G0=Ui(),H0=Dt(),Zf=Wi(),ec={empty:!0,space:!0};function Y0(r){for(let e=r.length-1;e>=0;e--){let t=r[e],i=t[3]||t[2];if(i)return i}}var tc=class{constructor(e){this.input=e,this.root=new H0,this.current=this.root,this.spaces="",this.semicolon=!1,this.customProperty=!1,this.createTokenizer(),this.root.source={input:e,start:{offset:0,line:1,column:1}}}createTokenizer(){this.tokenizer=U0(this.input)}parse(){let e;for(;!this.tokenizer.endOfFile();)switch(e=this.tokenizer.nextToken(),e[0]){case"space":this.spaces+=e[1];break;case";":this.freeSemicolon(e);break;case"}":this.end(e);break;case"comment":this.comment(e);break;case"at-word":this.atrule(e);break;case"{":this.emptyRule(e);break;default:this.other(e);break}this.endFile()}comment(e){let t=new W0;this.init(t,e[2]),t.source.end=this.getPosition(e[3]||e[2]);let i=e[1].slice(2,-2);if(/^\s*$/.test(i))t.text="",t.raws.left=i,t.raws.right="";else{let n=i.match(/^(\s*)([^]*\S)(\s*)$/);t.text=n[2],t.raws.left=n[1],t.raws.right=n[3]}}emptyRule(e){let t=new Zf;this.init(t,e[2]),t.selector="",t.raws.between="",this.current=t}other(e){let t=!1,i=null,n=!1,a=null,s=[],o=e[1].startsWith("--"),u=[],c=e;for(;c;){if(i=c[0],u.push(c),i==="("||i==="[")a||(a=c),s.push(i==="("?")":"]");else if(o&&n&&i==="{")a||(a=c),s.push("}");else if(s.length===0)if(i===";")if(n){this.decl(u,o);return}else break;else if(i==="{"){this.rule(u);return}else if(i==="}"){this.tokenizer.back(u.pop()),t=!0;break}else i===":"&&(n=!0);else i===s[s.length-1]&&(s.pop(),s.length===0&&(a=null));c=this.tokenizer.nextToken()}if(this.tokenizer.endOfFile()&&(t=!0),s.length>0&&this.unclosedBracket(a),t&&n){if(!o)for(;u.length&&(c=u[u.length-1][0],!(c!=="space"&&c!=="comment"));)this.tokenizer.back(u.pop());this.decl(u,o)}else this.unknownWord(u)}rule(e){e.pop();let t=new Zf;this.init(t,e[0][2]),t.raws.between=this.spacesAndCommentsFromEnd(e),this.raw(t,"selector",e),this.current=t}decl(e,t){let i=new V0;this.init(i,e[0][2]);let n=e[e.length-1];for(n[0]===";"&&(this.semicolon=!0,e.pop()),i.source.end=this.getPosition(n[3]||n[2]||Y0(e));e[0][0]!=="word";)e.length===1&&this.unknownWord(e),i.raws.before+=e.shift()[1];for(i.source.start=this.getPosition(e[0][2]),i.prop="";e.length;){let c=e[0][0];if(c===":"||c==="space"||c==="comment")break;i.prop+=e.shift()[1]}i.raws.between="";let a;for(;e.length;)if(a=e.shift(),a[0]===":"){i.raws.between+=a[1];break}else a[0]==="word"&&/\w/.test(a[1])&&this.unknownWord([a]),i.raws.between+=a[1];(i.prop[0]==="_"||i.prop[0]==="*")&&(i.raws.before+=i.prop[0],i.prop=i.prop.slice(1));let s=[],o;for(;e.length&&(o=e[0][0],!(o!=="space"&&o!=="comment"));)s.push(e.shift());this.precheckMissedSemicolon(e);for(let c=e.length-1;c>=0;c--){if(a=e[c],a[1].toLowerCase()==="!important"){i.important=!0;let f=this.stringFrom(e,c);f=this.spacesFromEnd(e)+f,f!==" !important"&&(i.raws.important=f);break}else if(a[1].toLowerCase()==="important"){let f=e.slice(0),d="";for(let p=c;p>0;p--){let m=f[p][0];if(d.trim().indexOf("!")===0&&m!=="space")break;d=f.pop()[1]+d}d.trim().indexOf("!")===0&&(i.important=!0,i.raws.important=d,e=f)}if(a[0]!=="space"&&a[0]!=="comment")break}e.some(c=>c[0]!=="space"&&c[0]!=="comment")&&(i.raws.between+=s.map(c=>c[1]).join(""),s=[]),this.raw(i,"value",s.concat(e),t),i.value.includes(":")&&!t&&this.checkMissedSemicolon(e)}atrule(e){let t=new G0;t.name=e[1].slice(1),t.name===""&&this.unnamedAtrule(t,e),this.init(t,e[2]);let i,n,a,s=!1,o=!1,u=[],c=[];for(;!this.tokenizer.endOfFile();){if(e=this.tokenizer.nextToken(),i=e[0],i==="("||i==="["?c.push(i==="("?")":"]"):i==="{"&&c.length>0?c.push("}"):i===c[c.length-1]&&c.pop(),c.length===0)if(i===";"){t.source.end=this.getPosition(e[2]),this.semicolon=!0;break}else if(i==="{"){o=!0;break}else if(i==="}"){if(u.length>0){for(a=u.length-1,n=u[a];n&&n[0]==="space";)n=u[--a];n&&(t.source.end=this.getPosition(n[3]||n[2]))}this.end(e);break}else u.push(e);else u.push(e);if(this.tokenizer.endOfFile()){s=!0;break}}t.raws.between=this.spacesAndCommentsFromEnd(u),u.length?(t.raws.afterName=this.spacesAndCommentsFromStart(u),this.raw(t,"params",u),s&&(e=u[u.length-1],t.source.end=this.getPosition(e[3]||e[2]),this.spaces=t.raws.between,t.raws.between="")):(t.raws.afterName="",t.params=""),o&&(t.nodes=[],this.current=t)}end(e){this.current.nodes&&this.current.nodes.length&&(this.current.raws.semicolon=this.semicolon),this.semicolon=!1,this.current.raws.after=(this.current.raws.after||"")+this.spaces,this.spaces="",this.current.parent?(this.current.source.end=this.getPosition(e[2]),this.current=this.current.parent):this.unexpectedClose(e)}endFile(){this.current.parent&&this.unclosedBlock(),this.current.nodes&&this.current.nodes.length&&(this.current.raws.semicolon=this.semicolon),this.current.raws.after=(this.current.raws.after||"")+this.spaces}freeSemicolon(e){if(this.spaces+=e[1],this.current.nodes){let t=this.current.nodes[this.current.nodes.length-1];t&&t.type==="rule"&&!t.raws.ownSemicolon&&(t.raws.ownSemicolon=this.spaces,this.spaces="")}}getPosition(e){let t=this.input.fromOffset(e);return{offset:e,line:t.line,column:t.col}}init(e,t){this.current.push(e),e.source={start:this.getPosition(t),input:this.input},e.raws.before=this.spaces,this.spaces="",e.type!=="comment"&&(this.semicolon=!1)}raw(e,t,i,n){let a,s,o=i.length,u="",c=!0,f,d;for(let p=0;pm+b[1],"");e.raws[t]={value:u,raw:p}}e[t]=u}spacesAndCommentsFromEnd(e){let t,i="";for(;e.length&&(t=e[e.length-1][0],!(t!=="space"&&t!=="comment"));)i=e.pop()[1]+i;return i}spacesAndCommentsFromStart(e){let t,i="";for(;e.length&&(t=e[0][0],!(t!=="space"&&t!=="comment"));)i+=e.shift()[1];return i}spacesFromEnd(e){let t,i="";for(;e.length&&(t=e[e.length-1][0],t==="space");)i=e.pop()[1]+i;return i}stringFrom(e,t){let i="";for(let n=t;n=0&&(n=e[a],!(n[0]!=="space"&&(i+=1,i===2)));a--);throw this.input.error("Missed semicolon",n[0]==="word"?n[3]+1:n[2])}};rc.exports=tc});var nc=v(()=>{l()});var ac=v((R3,sc)=>{l();var Q0="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict",J0=(r,e=21)=>(t=e)=>{let i="",n=t;for(;n--;)i+=r[Math.random()*r.length|0];return i},X0=(r=21)=>{let e="",t=r;for(;t--;)e+=Q0[Math.random()*64|0];return e};sc.exports={nanoid:X0,customAlphabet:J0}});var Fs=v((M3,oc)=>{l();oc.exports={}});var Hi=v((B3,cc)=>{l();"use strict";var{SourceMapConsumer:K0,SourceMapGenerator:Z0}=nc(),{fileURLToPath:lc,pathToFileURL:Gi}=(Cs(),pf),{resolve:Ls,isAbsolute:Ns}=(bt(),uf),{nanoid:ev}=ac(),$s=As(),uc=_i(),tv=Fs(),zs=Symbol("fromOffsetCache"),rv=Boolean(K0&&Z0),fc=Boolean(Ls&&Ns),Ar=class{constructor(e,t={}){if(e===null||typeof e=="undefined"||typeof e=="object"&&!e.toString)throw new Error(`PostCSS received ${e} instead of CSS string`);if(this.css=e.toString(),this.css[0]==="\uFEFF"||this.css[0]==="\uFFFE"?(this.hasBOM=!0,this.css=this.css.slice(1)):this.hasBOM=!1,t.from&&(!fc||/^\w+:\/\//.test(t.from)||Ns(t.from)?this.file=t.from:this.file=Ls(t.from)),fc&&rv){let i=new tv(this.css,t);if(i.text){this.map=i;let n=i.consumer().file;!this.file&&n&&(this.file=this.mapResolve(n))}}this.file||(this.id=""),this.map&&(this.map.file=this.from)}fromOffset(e){let t,i;if(this[zs])i=this[zs];else{let a=this.css.split(` -`);i=new Array(a.length);let s=0;for(let o=0,u=a.length;o=t)n=i.length-1;else{let a=i.length-2,s;for(;n>1),e=i[s+1])n=s+1;else{n=s;break}}return{line:n+1,col:e-i[n]+1}}error(e,t,i,n={}){let a,s,o;if(t&&typeof t=="object"){let c=t,f=i;if(typeof c.offset=="number"){let d=this.fromOffset(c.offset);t=d.line,i=d.col}else t=c.line,i=c.column;if(typeof f.offset=="number"){let d=this.fromOffset(f.offset);s=d.line,o=d.col}else s=f.line,o=f.column}else if(!i){let c=this.fromOffset(t);t=c.line,i=c.col}let u=this.origin(t,i,s,o);return u?a=new uc(e,u.endLine===void 0?u.line:{line:u.line,column:u.column},u.endLine===void 0?u.column:{line:u.endLine,column:u.endColumn},u.source,u.file,n.plugin):a=new uc(e,s===void 0?t:{line:t,column:i},s===void 0?i:{line:s,column:o},this.css,this.file,n.plugin),a.input={line:t,column:i,endLine:s,endColumn:o,source:this.css},this.file&&(Gi&&(a.input.url=Gi(this.file).toString()),a.input.file=this.file),a}origin(e,t,i,n){if(!this.map)return!1;let a=this.map.consumer(),s=a.originalPositionFor({line:e,column:t});if(!s.source)return!1;let o;typeof i=="number"&&(o=a.originalPositionFor({line:i,column:n}));let u;Ns(s.source)?u=Gi(s.source):u=new URL(s.source,this.map.consumer().sourceRoot||Gi(this.map.mapFile));let c={url:u.toString(),line:s.line,column:s.column,endLine:o&&o.line,endColumn:o&&o.column};if(u.protocol==="file:")if(lc)c.file=lc(u);else throw new Error("file: protocol is not available in this PostCSS build");let f=a.sourceContentFor(s.source);return f&&(c.source=f),c}mapResolve(e){return/^\w+:\/\//.test(e)?e:Ls(this.map.consumer().sourceRoot||this.map.root||".",e)}get from(){return this.file||this.id}toJSON(){let e={};for(let t of["hasBOM","css","file","id"])this[t]!=null&&(e[t]=this[t]);return this.map&&(e.map={...this.map},e.map.consumerCache&&(e.map.consumerCache=void 0)),e}};cc.exports=Ar;Ar.default=Ar;$s&&$s.registerInput&&$s.registerInput(Ar)});var Qi=v((F3,pc)=>{l();"use strict";var iv=nt(),nv=ic(),sv=Hi();function Yi(r,e){let t=new sv(r,e),i=new nv(t);try{i.parse()}catch(n){throw n}return i.root}pc.exports=Yi;Yi.default=Yi;iv.registerParse(Yi)});var Us=v((N3,gc)=>{l();"use strict";var{isClean:qe,my:av}=Oi(),ov=Ps(),lv=yr(),uv=nt(),fv=qi(),L3=qs(),dc=Bi(),cv=Qi(),pv=Dt(),dv={document:"Document",root:"Root",atrule:"AtRule",rule:"Rule",decl:"Declaration",comment:"Comment"},hv={postcssPlugin:!0,prepare:!0,Once:!0,Document:!0,Root:!0,Declaration:!0,Rule:!0,AtRule:!0,Comment:!0,DeclarationExit:!0,RuleExit:!0,AtRuleExit:!0,CommentExit:!0,RootExit:!0,DocumentExit:!0,OnceExit:!0},mv={postcssPlugin:!0,prepare:!0,Once:!0},It=0;function _r(r){return typeof r=="object"&&typeof r.then=="function"}function hc(r){let e=!1,t=dv[r.type];return r.type==="decl"?e=r.prop.toLowerCase():r.type==="atrule"&&(e=r.name.toLowerCase()),e&&r.append?[t,t+"-"+e,It,t+"Exit",t+"Exit-"+e]:e?[t,t+"-"+e,t+"Exit",t+"Exit-"+e]:r.append?[t,It,t+"Exit"]:[t,t+"Exit"]}function mc(r){let e;return r.type==="document"?e=["Document",It,"DocumentExit"]:r.type==="root"?e=["Root",It,"RootExit"]:e=hc(r),{node:r,events:e,eventIndex:0,visitors:[],visitorIndex:0,iterator:0}}function js(r){return r[qe]=!1,r.nodes&&r.nodes.forEach(e=>js(e)),r}var Vs={},Ve=class{constructor(e,t,i){this.stringified=!1,this.processed=!1;let n;if(typeof t=="object"&&t!==null&&(t.type==="root"||t.type==="document"))n=js(t);else if(t instanceof Ve||t instanceof dc)n=js(t.root),t.map&&(typeof i.map=="undefined"&&(i.map={}),i.map.inline||(i.map.inline=!1),i.map.prev=t.map);else{let a=cv;i.syntax&&(a=i.syntax.parse),i.parser&&(a=i.parser),a.parse&&(a=a.parse);try{n=a(t,i)}catch(s){this.processed=!0,this.error=s}n&&!n[av]&&uv.rebuild(n)}this.result=new dc(e,n,i),this.helpers={...Vs,result:this.result,postcss:Vs},this.plugins=this.processor.plugins.map(a=>typeof a=="object"&&a.prepare?{...a,...a.prepare(this.result)}:a)}get[Symbol.toStringTag](){return"LazyResult"}get processor(){return this.result.processor}get opts(){return this.result.opts}get css(){return this.stringify().css}get content(){return this.stringify().content}get map(){return this.stringify().map}get root(){return this.sync().root}get messages(){return this.sync().messages}warnings(){return this.sync().warnings()}toString(){return this.css}then(e,t){return this.async().then(e,t)}catch(e){return this.async().catch(e)}finally(e){return this.async().then(e,e)}async(){return this.error?Promise.reject(this.error):this.processed?Promise.resolve(this.result):(this.processing||(this.processing=this.runAsync()),this.processing)}sync(){if(this.error)throw this.error;if(this.processed)return this.result;if(this.processed=!0,this.processing)throw this.getAsyncError();for(let e of this.plugins){let t=this.runOnRoot(e);if(_r(t))throw this.getAsyncError()}if(this.prepareVisitors(),this.hasListener){let e=this.result.root;for(;!e[qe];)e[qe]=!0,this.walkSync(e);if(this.listeners.OnceExit)if(e.type==="document")for(let t of e.nodes)this.visitSync(this.listeners.OnceExit,t);else this.visitSync(this.listeners.OnceExit,e)}return this.result}stringify(){if(this.error)throw this.error;if(this.stringified)return this.result;this.stringified=!0,this.sync();let e=this.result.opts,t=lv;e.syntax&&(t=e.syntax.stringify),e.stringifier&&(t=e.stringifier),t.stringify&&(t=t.stringify);let n=new ov(t,this.result.root,this.result.opts).generate();return this.result.css=n[0],this.result.map=n[1],this.result}walkSync(e){e[qe]=!0;let t=hc(e);for(let i of t)if(i===It)e.nodes&&e.each(n=>{n[qe]||this.walkSync(n)});else{let n=this.listeners[i];if(n&&this.visitSync(n,e.toProxy()))return}}visitSync(e,t){for(let[i,n]of e){this.result.lastPlugin=i;let a;try{a=n(t,this.helpers)}catch(s){throw this.handleError(s,t.proxyOf)}if(t.type!=="root"&&t.type!=="document"&&!t.parent)return!0;if(_r(a))throw this.getAsyncError()}}runOnRoot(e){this.result.lastPlugin=e;try{if(typeof e=="object"&&e.Once){if(this.result.root.type==="document"){let t=this.result.root.nodes.map(i=>e.Once(i,this.helpers));return _r(t[0])?Promise.all(t):t}return e.Once(this.result.root,this.helpers)}else if(typeof e=="function")return e(this.result.root,this.result)}catch(t){throw this.handleError(t)}}getAsyncError(){throw new Error("Use process(css).then(cb) to work with async plugins")}handleError(e,t){let i=this.result.lastPlugin;try{t&&t.addToError(e),this.error=e,e.name==="CssSyntaxError"&&!e.plugin?(e.plugin=i.postcssPlugin,e.setMessage()):i.postcssVersion}catch(n){console&&console.error&&console.error(n)}return e}async runAsync(){this.plugin=0;for(let e=0;e0;){let i=this.visitTick(t);if(_r(i))try{await i}catch(n){let a=t[t.length-1].node;throw this.handleError(n,a)}}}if(this.listeners.OnceExit)for(let[t,i]of this.listeners.OnceExit){this.result.lastPlugin=t;try{if(e.type==="document"){let n=e.nodes.map(a=>i(a,this.helpers));await Promise.all(n)}else await i(e,this.helpers)}catch(n){throw this.handleError(n)}}}return this.processed=!0,this.stringify()}prepareVisitors(){this.listeners={};let e=(t,i,n)=>{this.listeners[i]||(this.listeners[i]=[]),this.listeners[i].push([t,n])};for(let t of this.plugins)if(typeof t=="object")for(let i in t){if(!hv[i]&&/^[A-Z]/.test(i))throw new Error(`Unknown event ${i} in ${t.postcssPlugin}. Try to update PostCSS (${this.processor.version} now).`);if(!mv[i])if(typeof t[i]=="object")for(let n in t[i])n==="*"?e(t,i,t[i][n]):e(t,i+"-"+n.toLowerCase(),t[i][n]);else typeof t[i]=="function"&&e(t,i,t[i])}this.hasListener=Object.keys(this.listeners).length>0}visitTick(e){let t=e[e.length-1],{node:i,visitors:n}=t;if(i.type!=="root"&&i.type!=="document"&&!i.parent){e.pop();return}if(n.length>0&&t.visitorIndex{Vs=r};gc.exports=Ve;Ve.default=Ve;pv.registerLazyResult(Ve);fv.registerLazyResult(Ve)});var wc=v((z3,yc)=>{l();"use strict";var gv=Ps(),yv=yr(),$3=qs(),wv=Qi(),bv=Bi(),Ji=class{constructor(e,t,i){t=t.toString(),this.stringified=!1,this._processor=e,this._css=t,this._opts=i,this._map=void 0;let n,a=yv;this.result=new bv(this._processor,n,this._opts),this.result.css=t;let s=this;Object.defineProperty(this.result,"root",{get(){return s.root}});let o=new gv(a,n,this._opts,t);if(o.isMap()){let[u,c]=o.generate();u&&(this.result.css=u),c&&(this.result.map=c)}}get[Symbol.toStringTag](){return"NoWorkResult"}get processor(){return this.result.processor}get opts(){return this.result.opts}get css(){return this.result.css}get content(){return this.result.css}get map(){return this.result.map}get root(){if(this._root)return this._root;let e,t=wv;try{e=t(this._css,this._opts)}catch(i){this.error=i}if(this.error)throw this.error;return this._root=e,e}get messages(){return[]}warnings(){return[]}toString(){return this._css}then(e,t){return this.async().then(e,t)}catch(e){return this.async().catch(e)}finally(e){return this.async().then(e,e)}async(){return this.error?Promise.reject(this.error):Promise.resolve(this.result)}sync(){if(this.error)throw this.error;return this.result}};yc.exports=Ji;Ji.default=Ji});var vc=v((j3,bc)=>{l();"use strict";var vv=wc(),xv=Us(),kv=qi(),Sv=Dt(),qt=class{constructor(e=[]){this.version="8.4.24",this.plugins=this.normalize(e)}use(e){return this.plugins=this.plugins.concat(this.normalize([e])),this}process(e,t={}){return this.plugins.length===0&&typeof t.parser=="undefined"&&typeof t.stringifier=="undefined"&&typeof t.syntax=="undefined"?new vv(this,e,t):new xv(this,e,t)}normalize(e){let t=[];for(let i of e)if(i.postcss===!0?i=i():i.postcss&&(i=i.postcss),typeof i=="object"&&Array.isArray(i.plugins))t=t.concat(i.plugins);else if(typeof i=="object"&&i.postcssPlugin)t.push(i);else if(typeof i=="function")t.push(i);else if(!(typeof i=="object"&&(i.parse||i.stringify)))throw new Error(i+" is not a PostCSS plugin");return t}};bc.exports=qt;qt.default=qt;Sv.registerProcessor(qt);kv.registerProcessor(qt)});var kc=v((V3,xc)=>{l();"use strict";var Cv=br(),Av=Fs(),_v=vr(),Ov=Ui(),Ev=Hi(),Tv=Dt(),Pv=Wi();function Or(r,e){if(Array.isArray(r))return r.map(n=>Or(n));let{inputs:t,...i}=r;if(t){e=[];for(let n of t){let a={...n,__proto__:Ev.prototype};a.map&&(a.map={...a.map,__proto__:Av.prototype}),e.push(a)}}if(i.nodes&&(i.nodes=r.nodes.map(n=>Or(n,e))),i.source){let{inputId:n,...a}=i.source;i.source=a,n!=null&&(i.source.input=e[n])}if(i.type==="root")return new Tv(i);if(i.type==="decl")return new Cv(i);if(i.type==="rule")return new Pv(i);if(i.type==="comment")return new _v(i);if(i.type==="atrule")return new Ov(i);throw new Error("Unknown node type: "+r.type)}xc.exports=Or;Or.default=Or});var ge=v((U3,Tc)=>{l();"use strict";var Dv=_i(),Sc=br(),Iv=Us(),qv=nt(),Ws=vc(),Rv=yr(),Mv=kc(),Cc=qi(),Bv=Rs(),Ac=vr(),_c=Ui(),Fv=Bi(),Lv=Hi(),Nv=Qi(),$v=Bs(),Oc=Wi(),Ec=Dt(),zv=wr();function z(...r){return r.length===1&&Array.isArray(r[0])&&(r=r[0]),new Ws(r)}z.plugin=function(e,t){let i=!1;function n(...s){console&&console.warn&&!i&&(i=!0,console.warn(e+`: postcss.plugin was deprecated. Migration guide: -https://evilmartians.com/chronicles/postcss-8-plugin-migration`),h.env.LANG&&h.env.LANG.startsWith("cn")&&console.warn(e+`: \u91CC\u9762 postcss.plugin \u88AB\u5F03\u7528. \u8FC1\u79FB\u6307\u5357: -https://www.w3ctech.com/topic/2226`));let o=t(...s);return o.postcssPlugin=e,o.postcssVersion=new Ws().version,o}let a;return Object.defineProperty(n,"postcss",{get(){return a||(a=n()),a}}),n.process=function(s,o,u){return z([n(u)]).process(s,o)},n};z.stringify=Rv;z.parse=Nv;z.fromJSON=Mv;z.list=$v;z.comment=r=>new Ac(r);z.atRule=r=>new _c(r);z.decl=r=>new Sc(r);z.rule=r=>new Oc(r);z.root=r=>new Ec(r);z.document=r=>new Cc(r);z.CssSyntaxError=Dv;z.Declaration=Sc;z.Container=qv;z.Processor=Ws;z.Document=Cc;z.Comment=Ac;z.Warning=Bv;z.AtRule=_c;z.Result=Fv;z.Input=Lv;z.Rule=Oc;z.Root=Ec;z.Node=zv;Iv.registerPostcss(z);Tc.exports=z;z.default=z});var U,j,W3,G3,H3,Y3,Q3,J3,X3,K3,Z3,eT,tT,rT,iT,nT,sT,aT,oT,lT,uT,fT,cT,pT,dT,hT,st=C(()=>{l();U=X(ge()),j=U.default,W3=U.default.stringify,G3=U.default.fromJSON,H3=U.default.plugin,Y3=U.default.parse,Q3=U.default.list,J3=U.default.document,X3=U.default.comment,K3=U.default.atRule,Z3=U.default.rule,eT=U.default.decl,tT=U.default.root,rT=U.default.CssSyntaxError,iT=U.default.Declaration,nT=U.default.Container,sT=U.default.Processor,aT=U.default.Document,oT=U.default.Comment,lT=U.default.Warning,uT=U.default.AtRule,fT=U.default.Result,cT=U.default.Input,pT=U.default.Rule,dT=U.default.Root,hT=U.default.Node});var Gs=v((gT,Pc)=>{l();Pc.exports=function(r,e,t,i,n){for(e=e.split?e.split("."):e,i=0;i{l();"use strict";Xi.__esModule=!0;Xi.default=Uv;function jv(r){for(var e=r.toLowerCase(),t="",i=!1,n=0;n<6&&e[n]!==void 0;n++){var a=e.charCodeAt(n),s=a>=97&&a<=102||a>=48&&a<=57;if(i=a===32,!s)break;t+=e[n]}if(t.length!==0){var o=parseInt(t,16),u=o>=55296&&o<=57343;return u||o===0||o>1114111?["\uFFFD",t.length+(i?1:0)]:[String.fromCodePoint(o),t.length+(i?1:0)]}}var Vv=/\\/;function Uv(r){var e=Vv.test(r);if(!e)return r;for(var t="",i=0;i{l();"use strict";Zi.__esModule=!0;Zi.default=Wv;function Wv(r){for(var e=arguments.length,t=new Array(e>1?e-1:0),i=1;i0;){var n=t.shift();if(!r[n])return;r=r[n]}return r}Ic.exports=Zi.default});var Mc=v((en,Rc)=>{l();"use strict";en.__esModule=!0;en.default=Gv;function Gv(r){for(var e=arguments.length,t=new Array(e>1?e-1:0),i=1;i0;){var n=t.shift();r[n]||(r[n]={}),r=r[n]}}Rc.exports=en.default});var Fc=v((tn,Bc)=>{l();"use strict";tn.__esModule=!0;tn.default=Hv;function Hv(r){for(var e="",t=r.indexOf("/*"),i=0;t>=0;){e=e+r.slice(i,t);var n=r.indexOf("*/",t+2);if(n<0)return e;i=n+2,t=r.indexOf("/*",i)}return e=e+r.slice(i),e}Bc.exports=tn.default});var Er=v(Re=>{l();"use strict";Re.__esModule=!0;Re.unesc=Re.stripComments=Re.getProp=Re.ensureObject=void 0;var Yv=rn(Ki());Re.unesc=Yv.default;var Qv=rn(qc());Re.getProp=Qv.default;var Jv=rn(Mc());Re.ensureObject=Jv.default;var Xv=rn(Fc());Re.stripComments=Xv.default;function rn(r){return r&&r.__esModule?r:{default:r}}});var Ue=v((Tr,$c)=>{l();"use strict";Tr.__esModule=!0;Tr.default=void 0;var Lc=Er();function Nc(r,e){for(var t=0;ti||this.source.end.linen||this.source.end.line===i&&this.source.end.column{l();"use strict";W.__esModule=!0;W.UNIVERSAL=W.TAG=W.STRING=W.SELECTOR=W.ROOT=W.PSEUDO=W.NESTING=W.ID=W.COMMENT=W.COMBINATOR=W.CLASS=W.ATTRIBUTE=void 0;var tx="tag";W.TAG=tx;var rx="string";W.STRING=rx;var ix="selector";W.SELECTOR=ix;var nx="root";W.ROOT=nx;var sx="pseudo";W.PSEUDO=sx;var ax="nesting";W.NESTING=ax;var ox="id";W.ID=ox;var lx="comment";W.COMMENT=lx;var ux="combinator";W.COMBINATOR=ux;var fx="class";W.CLASS=fx;var cx="attribute";W.ATTRIBUTE=cx;var px="universal";W.UNIVERSAL=px});var nn=v((Pr,Uc)=>{l();"use strict";Pr.__esModule=!0;Pr.default=void 0;var dx=mx(Ue()),We=hx(ne());function zc(r){if(typeof WeakMap!="function")return null;var e=new WeakMap,t=new WeakMap;return(zc=function(n){return n?t:e})(r)}function hx(r,e){if(!e&&r&&r.__esModule)return r;if(r===null||typeof r!="object"&&typeof r!="function")return{default:r};var t=zc(e);if(t&&t.has(r))return t.get(r);var i={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in r)if(a!=="default"&&Object.prototype.hasOwnProperty.call(r,a)){var s=n?Object.getOwnPropertyDescriptor(r,a):null;s&&(s.get||s.set)?Object.defineProperty(i,a,s):i[a]=r[a]}return i.default=r,t&&t.set(r,i),i}function mx(r){return r&&r.__esModule?r:{default:r}}function gx(r,e){var t=typeof Symbol!="undefined"&&r[Symbol.iterator]||r["@@iterator"];if(t)return(t=t.call(r)).next.bind(t);if(Array.isArray(r)||(t=yx(r))||e&&r&&typeof r.length=="number"){t&&(r=t);var i=0;return function(){return i>=r.length?{done:!0}:{done:!1,value:r[i++]}}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. -In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function yx(r,e){if(!!r){if(typeof r=="string")return jc(r,e);var t=Object.prototype.toString.call(r).slice(8,-1);if(t==="Object"&&r.constructor&&(t=r.constructor.name),t==="Map"||t==="Set")return Array.from(r);if(t==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t))return jc(r,e)}}function jc(r,e){(e==null||e>r.length)&&(e=r.length);for(var t=0,i=new Array(e);t=n&&(this.indexes[s]=a-1);return this},t.removeAll=function(){for(var n=gx(this.nodes),a;!(a=n()).done;){var s=a.value;s.parent=void 0}return this.nodes=[],this},t.empty=function(){return this.removeAll()},t.insertAfter=function(n,a){a.parent=this;var s=this.index(n);this.nodes.splice(s+1,0,a),a.parent=this;var o;for(var u in this.indexes)o=this.indexes[u],s<=o&&(this.indexes[u]=o+1);return this},t.insertBefore=function(n,a){a.parent=this;var s=this.index(n);this.nodes.splice(s,0,a),a.parent=this;var o;for(var u in this.indexes)o=this.indexes[u],o<=s&&(this.indexes[u]=o+1);return this},t._findChildAtPosition=function(n,a){var s=void 0;return this.each(function(o){if(o.atPosition){var u=o.atPosition(n,a);if(u)return s=u,!1}else if(o.isAtPosition(n,a))return s=o,!1}),s},t.atPosition=function(n,a){if(this.isAtPosition(n,a))return this._findChildAtPosition(n,a)||this},t._inferEndPosition=function(){this.last&&this.last.source&&this.last.source.end&&(this.source=this.source||{},this.source.end=this.source.end||{},Object.assign(this.source.end,this.last.source.end))},t.each=function(n){this.lastEach||(this.lastEach=0),this.indexes||(this.indexes={}),this.lastEach++;var a=this.lastEach;if(this.indexes[a]=0,!!this.length){for(var s,o;this.indexes[a]{l();"use strict";Dr.__esModule=!0;Dr.default=void 0;var xx=Sx(nn()),kx=ne();function Sx(r){return r&&r.__esModule?r:{default:r}}function Wc(r,e){for(var t=0;t{l();"use strict";Ir.__esModule=!0;Ir.default=void 0;var Ox=Tx(nn()),Ex=ne();function Tx(r){return r&&r.__esModule?r:{default:r}}function Px(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,Js(r,e)}function Js(r,e){return Js=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},Js(r,e)}var Dx=function(r){Px(e,r);function e(t){var i;return i=r.call(this,t)||this,i.type=Ex.SELECTOR,i}return e}(Ox.default);Ir.default=Dx;Hc.exports=Ir.default});var sn=v((bT,Yc)=>{l();"use strict";var Ix={},qx=Ix.hasOwnProperty,Rx=function(e,t){if(!e)return t;var i={};for(var n in t)i[n]=qx.call(e,n)?e[n]:t[n];return i},Mx=/[ -,\.\/:-@\[-\^`\{-~]/,Bx=/[ -,\.\/:-@\[\]\^`\{-~]/,Fx=/(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g,Ks=function r(e,t){t=Rx(t,r.options),t.quotes!="single"&&t.quotes!="double"&&(t.quotes="single");for(var i=t.quotes=="double"?'"':"'",n=t.isIdentifier,a=e.charAt(0),s="",o=0,u=e.length;o126){if(f>=55296&&f<=56319&&o{l();"use strict";qr.__esModule=!0;qr.default=void 0;var Lx=Qc(sn()),Nx=Er(),$x=Qc(Ue()),zx=ne();function Qc(r){return r&&r.__esModule?r:{default:r}}function Jc(r,e){for(var t=0;t{l();"use strict";Rr.__esModule=!0;Rr.default=void 0;var Wx=Hx(Ue()),Gx=ne();function Hx(r){return r&&r.__esModule?r:{default:r}}function Yx(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,ta(r,e)}function ta(r,e){return ta=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},ta(r,e)}var Qx=function(r){Yx(e,r);function e(t){var i;return i=r.call(this,t)||this,i.type=Gx.COMMENT,i}return e}(Wx.default);Rr.default=Qx;Kc.exports=Rr.default});var na=v((Mr,Zc)=>{l();"use strict";Mr.__esModule=!0;Mr.default=void 0;var Jx=Kx(Ue()),Xx=ne();function Kx(r){return r&&r.__esModule?r:{default:r}}function Zx(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,ia(r,e)}function ia(r,e){return ia=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},ia(r,e)}var e1=function(r){Zx(e,r);function e(i){var n;return n=r.call(this,i)||this,n.type=Xx.ID,n}var t=e.prototype;return t.valueToString=function(){return"#"+r.prototype.valueToString.call(this)},e}(Jx.default);Mr.default=e1;Zc.exports=Mr.default});var an=v((Br,rp)=>{l();"use strict";Br.__esModule=!0;Br.default=void 0;var t1=ep(sn()),r1=Er(),i1=ep(Ue());function ep(r){return r&&r.__esModule?r:{default:r}}function tp(r,e){for(var t=0;t{l();"use strict";Fr.__esModule=!0;Fr.default=void 0;var o1=u1(an()),l1=ne();function u1(r){return r&&r.__esModule?r:{default:r}}function f1(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,aa(r,e)}function aa(r,e){return aa=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},aa(r,e)}var c1=function(r){f1(e,r);function e(t){var i;return i=r.call(this,t)||this,i.type=l1.TAG,i}return e}(o1.default);Fr.default=c1;ip.exports=Fr.default});var ua=v((Lr,np)=>{l();"use strict";Lr.__esModule=!0;Lr.default=void 0;var p1=h1(Ue()),d1=ne();function h1(r){return r&&r.__esModule?r:{default:r}}function m1(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,la(r,e)}function la(r,e){return la=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},la(r,e)}var g1=function(r){m1(e,r);function e(t){var i;return i=r.call(this,t)||this,i.type=d1.STRING,i}return e}(p1.default);Lr.default=g1;np.exports=Lr.default});var ca=v((Nr,sp)=>{l();"use strict";Nr.__esModule=!0;Nr.default=void 0;var y1=b1(nn()),w1=ne();function b1(r){return r&&r.__esModule?r:{default:r}}function v1(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,fa(r,e)}function fa(r,e){return fa=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},fa(r,e)}var x1=function(r){v1(e,r);function e(i){var n;return n=r.call(this,i)||this,n.type=w1.PSEUDO,n}var t=e.prototype;return t.toString=function(){var n=this.length?"("+this.map(String).join(",")+")":"";return[this.rawSpaceBefore,this.stringifyProperty("value"),n,this.rawSpaceAfter].join("")},e}(y1.default);Nr.default=x1;sp.exports=Nr.default});var ap={};Ae(ap,{deprecate:()=>k1});function k1(r){return r}var op=C(()=>{l()});var up=v((vT,lp)=>{l();lp.exports=(op(),ap).deprecate});var ya=v(jr=>{l();"use strict";jr.__esModule=!0;jr.default=void 0;jr.unescapeValue=ma;var $r=da(sn()),S1=da(Ki()),C1=da(an()),A1=ne(),pa;function da(r){return r&&r.__esModule?r:{default:r}}function fp(r,e){for(var t=0;t0&&!n.quoted&&o.before.length===0&&!(n.spaces.value&&n.spaces.value.after)&&(o.before=" "),cp(s,o)}))),a.push("]"),a.push(this.rawSpaceAfter),a.join("")},_1(e,[{key:"quoted",get:function(){var n=this.quoteMark;return n==="'"||n==='"'},set:function(n){P1()}},{key:"quoteMark",get:function(){return this._quoteMark},set:function(n){if(!this._constructed){this._quoteMark=n;return}this._quoteMark!==n&&(this._quoteMark=n,this._syncRawValue())}},{key:"qualifiedAttribute",get:function(){return this.qualifiedName(this.raws.attribute||this.attribute)}},{key:"insensitiveFlag",get:function(){return this.insensitive?"i":""}},{key:"value",get:function(){return this._value},set:function(n){if(this._constructed){var a=ma(n),s=a.deprecatedUsage,o=a.unescaped,u=a.quoteMark;if(s&&T1(),o===this._value&&u===this._quoteMark)return;this._value=o,this._quoteMark=u,this._syncRawValue()}else this._value=n}},{key:"insensitive",get:function(){return this._insensitive},set:function(n){n||(this._insensitive=!1,this.raws&&(this.raws.insensitiveFlag==="I"||this.raws.insensitiveFlag==="i")&&(this.raws.insensitiveFlag=void 0)),this._insensitive=n}},{key:"attribute",get:function(){return this._attribute},set:function(n){this._handleEscapes("attribute",n),this._attribute=n}}]),e}(C1.default);jr.default=on;on.NO_QUOTE=null;on.SINGLE_QUOTE="'";on.DOUBLE_QUOTE='"';var ga=(pa={"'":{quotes:"single",wrap:!0},'"':{quotes:"double",wrap:!0}},pa[null]={isIdentifier:!0},pa);function cp(r,e){return""+e.before+r+e.after}});var ba=v((Vr,pp)=>{l();"use strict";Vr.__esModule=!0;Vr.default=void 0;var q1=M1(an()),R1=ne();function M1(r){return r&&r.__esModule?r:{default:r}}function B1(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,wa(r,e)}function wa(r,e){return wa=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},wa(r,e)}var F1=function(r){B1(e,r);function e(t){var i;return i=r.call(this,t)||this,i.type=R1.UNIVERSAL,i.value="*",i}return e}(q1.default);Vr.default=F1;pp.exports=Vr.default});var xa=v((Ur,dp)=>{l();"use strict";Ur.__esModule=!0;Ur.default=void 0;var L1=$1(Ue()),N1=ne();function $1(r){return r&&r.__esModule?r:{default:r}}function z1(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,va(r,e)}function va(r,e){return va=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},va(r,e)}var j1=function(r){z1(e,r);function e(t){var i;return i=r.call(this,t)||this,i.type=N1.COMBINATOR,i}return e}(L1.default);Ur.default=j1;dp.exports=Ur.default});var Sa=v((Wr,hp)=>{l();"use strict";Wr.__esModule=!0;Wr.default=void 0;var V1=W1(Ue()),U1=ne();function W1(r){return r&&r.__esModule?r:{default:r}}function G1(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,ka(r,e)}function ka(r,e){return ka=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},ka(r,e)}var H1=function(r){G1(e,r);function e(t){var i;return i=r.call(this,t)||this,i.type=U1.NESTING,i.value="&",i}return e}(V1.default);Wr.default=H1;hp.exports=Wr.default});var gp=v((ln,mp)=>{l();"use strict";ln.__esModule=!0;ln.default=Y1;function Y1(r){return r.sort(function(e,t){return e-t})}mp.exports=ln.default});var Ca=v(D=>{l();"use strict";D.__esModule=!0;D.word=D.tilde=D.tab=D.str=D.space=D.slash=D.singleQuote=D.semicolon=D.plus=D.pipe=D.openSquare=D.openParenthesis=D.newline=D.greaterThan=D.feed=D.equals=D.doubleQuote=D.dollar=D.cr=D.comment=D.comma=D.combinator=D.colon=D.closeSquare=D.closeParenthesis=D.caret=D.bang=D.backslash=D.at=D.asterisk=D.ampersand=void 0;var Q1=38;D.ampersand=Q1;var J1=42;D.asterisk=J1;var X1=64;D.at=X1;var K1=44;D.comma=K1;var Z1=58;D.colon=Z1;var ek=59;D.semicolon=ek;var tk=40;D.openParenthesis=tk;var rk=41;D.closeParenthesis=rk;var ik=91;D.openSquare=ik;var nk=93;D.closeSquare=nk;var sk=36;D.dollar=sk;var ak=126;D.tilde=ak;var ok=94;D.caret=ok;var lk=43;D.plus=lk;var uk=61;D.equals=uk;var fk=124;D.pipe=fk;var ck=62;D.greaterThan=ck;var pk=32;D.space=pk;var yp=39;D.singleQuote=yp;var dk=34;D.doubleQuote=dk;var hk=47;D.slash=hk;var mk=33;D.bang=mk;var gk=92;D.backslash=gk;var yk=13;D.cr=yk;var wk=12;D.feed=wk;var bk=10;D.newline=bk;var vk=9;D.tab=vk;var xk=yp;D.str=xk;var kk=-1;D.comment=kk;var Sk=-2;D.word=Sk;var Ck=-3;D.combinator=Ck});var vp=v(Gr=>{l();"use strict";Gr.__esModule=!0;Gr.FIELDS=void 0;Gr.default=Dk;var O=Ak(Ca()),Rt,V;function wp(r){if(typeof WeakMap!="function")return null;var e=new WeakMap,t=new WeakMap;return(wp=function(n){return n?t:e})(r)}function Ak(r,e){if(!e&&r&&r.__esModule)return r;if(r===null||typeof r!="object"&&typeof r!="function")return{default:r};var t=wp(e);if(t&&t.has(r))return t.get(r);var i={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in r)if(a!=="default"&&Object.prototype.hasOwnProperty.call(r,a)){var s=n?Object.getOwnPropertyDescriptor(r,a):null;s&&(s.get||s.set)?Object.defineProperty(i,a,s):i[a]=r[a]}return i.default=r,t&&t.set(r,i),i}var _k=(Rt={},Rt[O.tab]=!0,Rt[O.newline]=!0,Rt[O.cr]=!0,Rt[O.feed]=!0,Rt),Ok=(V={},V[O.space]=!0,V[O.tab]=!0,V[O.newline]=!0,V[O.cr]=!0,V[O.feed]=!0,V[O.ampersand]=!0,V[O.asterisk]=!0,V[O.bang]=!0,V[O.comma]=!0,V[O.colon]=!0,V[O.semicolon]=!0,V[O.openParenthesis]=!0,V[O.closeParenthesis]=!0,V[O.openSquare]=!0,V[O.closeSquare]=!0,V[O.singleQuote]=!0,V[O.doubleQuote]=!0,V[O.plus]=!0,V[O.pipe]=!0,V[O.tilde]=!0,V[O.greaterThan]=!0,V[O.equals]=!0,V[O.dollar]=!0,V[O.caret]=!0,V[O.slash]=!0,V),Aa={},bp="0123456789abcdefABCDEF";for(un=0;un0?(k=s+x,S=w-y[x].length):(k=s,S=a),E=O.comment,s=k,p=k,d=w-S):c===O.slash?(w=o,E=c,p=s,d=o-a,u=w+1):(w=Ek(t,o),E=O.word,p=s,d=w-a),u=w+1;break}e.push([E,s,o-a,p,d,o,u]),S&&(a=S,S=null),o=u}return e}});var Ep=v((Hr,Op)=>{l();"use strict";Hr.__esModule=!0;Hr.default=void 0;var Ik=be(Qs()),_a=be(Xs()),qk=be(ea()),xp=be(ra()),Rk=be(na()),Mk=be(oa()),Oa=be(ua()),Bk=be(ca()),kp=fn(ya()),Fk=be(ba()),Ea=be(xa()),Lk=be(Sa()),Nk=be(gp()),A=fn(vp()),T=fn(Ca()),$k=fn(ne()),Y=Er(),xt,Ta;function Sp(r){if(typeof WeakMap!="function")return null;var e=new WeakMap,t=new WeakMap;return(Sp=function(n){return n?t:e})(r)}function fn(r,e){if(!e&&r&&r.__esModule)return r;if(r===null||typeof r!="object"&&typeof r!="function")return{default:r};var t=Sp(e);if(t&&t.has(r))return t.get(r);var i={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in r)if(a!=="default"&&Object.prototype.hasOwnProperty.call(r,a)){var s=n?Object.getOwnPropertyDescriptor(r,a):null;s&&(s.get||s.set)?Object.defineProperty(i,a,s):i[a]=r[a]}return i.default=r,t&&t.set(r,i),i}function be(r){return r&&r.__esModule?r:{default:r}}function Cp(r,e){for(var t=0;t0){var s=this.current.last;if(s){var o=this.convertWhitespaceNodesToSpace(a),u=o.space,c=o.rawSpace;c!==void 0&&(s.rawSpaceAfter+=c),s.spaces.after+=u}else a.forEach(function(E){return i.newNode(E)})}return}var f=this.currToken,d=void 0;n>this.position&&(d=this.parseWhitespaceEquivalentTokens(n));var p;if(this.isNamedCombinator()?p=this.namedCombinator():this.currToken[A.FIELDS.TYPE]===T.combinator?(p=new Ea.default({value:this.content(),source:Mt(this.currToken),sourceIndex:this.currToken[A.FIELDS.START_POS]}),this.position++):Pa[this.currToken[A.FIELDS.TYPE]]||d||this.unexpected(),p){if(d){var m=this.convertWhitespaceNodesToSpace(d),b=m.space,x=m.rawSpace;p.spaces.before=b,p.rawSpaceBefore=x}}else{var y=this.convertWhitespaceNodesToSpace(d,!0),w=y.space,k=y.rawSpace;k||(k=w);var S={},_={spaces:{}};w.endsWith(" ")&&k.endsWith(" ")?(S.before=w.slice(0,w.length-1),_.spaces.before=k.slice(0,k.length-1)):w.startsWith(" ")&&k.startsWith(" ")?(S.after=w.slice(1),_.spaces.after=k.slice(1)):_.value=k,p=new Ea.default({value:" ",source:Da(f,this.tokens[this.position-1]),sourceIndex:f[A.FIELDS.START_POS],spaces:S,raws:_})}return this.currToken&&this.currToken[A.FIELDS.TYPE]===T.space&&(p.spaces.after=this.optionalSpace(this.content()),this.position++),this.newNode(p)},e.comma=function(){if(this.position===this.tokens.length-1){this.root.trailingComma=!0,this.position++;return}this.current._inferEndPosition();var i=new _a.default({source:{start:Ap(this.tokens[this.position+1])}});this.current.parent.append(i),this.current=i,this.position++},e.comment=function(){var i=this.currToken;this.newNode(new xp.default({value:this.content(),source:Mt(i),sourceIndex:i[A.FIELDS.START_POS]})),this.position++},e.error=function(i,n){throw this.root.error(i,n)},e.missingBackslash=function(){return this.error("Expected a backslash preceding the semicolon.",{index:this.currToken[A.FIELDS.START_POS]})},e.missingParenthesis=function(){return this.expected("opening parenthesis",this.currToken[A.FIELDS.START_POS])},e.missingSquareBracket=function(){return this.expected("opening square bracket",this.currToken[A.FIELDS.START_POS])},e.unexpected=function(){return this.error("Unexpected '"+this.content()+"'. Escaping special characters with \\ may help.",this.currToken[A.FIELDS.START_POS])},e.unexpectedPipe=function(){return this.error("Unexpected '|'.",this.currToken[A.FIELDS.START_POS])},e.namespace=function(){var i=this.prevToken&&this.content(this.prevToken)||!0;if(this.nextToken[A.FIELDS.TYPE]===T.word)return this.position++,this.word(i);if(this.nextToken[A.FIELDS.TYPE]===T.asterisk)return this.position++,this.universal(i);this.unexpectedPipe()},e.nesting=function(){if(this.nextToken){var i=this.content(this.nextToken);if(i==="|"){this.position++;return}}var n=this.currToken;this.newNode(new Lk.default({value:this.content(),source:Mt(n),sourceIndex:n[A.FIELDS.START_POS]})),this.position++},e.parentheses=function(){var i=this.current.last,n=1;if(this.position++,i&&i.type===$k.PSEUDO){var a=new _a.default({source:{start:Ap(this.tokens[this.position-1])}}),s=this.current;for(i.append(a),this.current=a;this.position1&&i.nextToken&&i.nextToken[A.FIELDS.TYPE]===T.openParenthesis&&i.error("Misplaced parenthesis.",{index:i.nextToken[A.FIELDS.START_POS]})});else return this.expected(["pseudo-class","pseudo-element"],this.currToken[A.FIELDS.START_POS])},e.space=function(){var i=this.content();this.position===0||this.prevToken[A.FIELDS.TYPE]===T.comma||this.prevToken[A.FIELDS.TYPE]===T.openParenthesis||this.current.nodes.every(function(n){return n.type==="comment"})?(this.spaces=this.optionalSpace(i),this.position++):this.position===this.tokens.length-1||this.nextToken[A.FIELDS.TYPE]===T.comma||this.nextToken[A.FIELDS.TYPE]===T.closeParenthesis?(this.current.last.spaces.after=this.optionalSpace(i),this.position++):this.combinator()},e.string=function(){var i=this.currToken;this.newNode(new Oa.default({value:this.content(),source:Mt(i),sourceIndex:i[A.FIELDS.START_POS]})),this.position++},e.universal=function(i){var n=this.nextToken;if(n&&this.content(n)==="|")return this.position++,this.namespace();var a=this.currToken;this.newNode(new Fk.default({value:this.content(),source:Mt(a),sourceIndex:a[A.FIELDS.START_POS]}),i),this.position++},e.splitWord=function(i,n){for(var a=this,s=this.nextToken,o=this.content();s&&~[T.dollar,T.caret,T.equals,T.word].indexOf(s[A.FIELDS.TYPE]);){this.position++;var u=this.content();if(o+=u,u.lastIndexOf("\\")===u.length-1){var c=this.nextToken;c&&c[A.FIELDS.TYPE]===T.space&&(o+=this.requiredSpace(this.content(c)),this.position++)}s=this.nextToken}var f=Ia(o,".").filter(function(b){var x=o[b-1]==="\\",y=/^\d+\.\d+%$/.test(o);return!x&&!y}),d=Ia(o,"#").filter(function(b){return o[b-1]!=="\\"}),p=Ia(o,"#{");p.length&&(d=d.filter(function(b){return!~p.indexOf(b)}));var m=(0,Nk.default)(Vk([0].concat(f,d)));m.forEach(function(b,x){var y=m[x+1]||o.length,w=o.slice(b,y);if(x===0&&n)return n.call(a,w,m.length);var k,S=a.currToken,_=S[A.FIELDS.START_POS]+m[x],E=kt(S[1],S[2]+b,S[3],S[2]+(y-1));if(~f.indexOf(b)){var I={value:w.slice(1),source:E,sourceIndex:_};k=new qk.default(Bt(I,"value"))}else if(~d.indexOf(b)){var q={value:w.slice(1),source:E,sourceIndex:_};k=new Rk.default(Bt(q,"value"))}else{var R={value:w,source:E,sourceIndex:_};Bt(R,"value"),k=new Mk.default(R)}a.newNode(k,i),i=null}),this.position++},e.word=function(i){var n=this.nextToken;return n&&this.content(n)==="|"?(this.position++,this.namespace()):this.splitWord(i)},e.loop=function(){for(;this.position{l();"use strict";Yr.__esModule=!0;Yr.default=void 0;var Wk=Gk(Ep());function Gk(r){return r&&r.__esModule?r:{default:r}}var Hk=function(){function r(t,i){this.func=t||function(){},this.funcRes=null,this.options=i}var e=r.prototype;return e._shouldUpdateSelector=function(i,n){n===void 0&&(n={});var a=Object.assign({},this.options,n);return a.updateSelector===!1?!1:typeof i!="string"},e._isLossy=function(i){i===void 0&&(i={});var n=Object.assign({},this.options,i);return n.lossless===!1},e._root=function(i,n){n===void 0&&(n={});var a=new Wk.default(i,this._parseOptions(n));return a.root},e._parseOptions=function(i){return{lossy:this._isLossy(i)}},e._run=function(i,n){var a=this;return n===void 0&&(n={}),new Promise(function(s,o){try{var u=a._root(i,n);Promise.resolve(a.func(u)).then(function(c){var f=void 0;return a._shouldUpdateSelector(i,n)&&(f=u.toString(),i.selector=f),{transform:c,root:u,string:f}}).then(s,o)}catch(c){o(c);return}})},e._runSync=function(i,n){n===void 0&&(n={});var a=this._root(i,n),s=this.func(a);if(s&&typeof s.then=="function")throw new Error("Selector processor returned a promise to a synchronous call.");var o=void 0;return n.updateSelector&&typeof i!="string"&&(o=a.toString(),i.selector=o),{transform:s,root:a,string:o}},e.ast=function(i,n){return this._run(i,n).then(function(a){return a.root})},e.astSync=function(i,n){return this._runSync(i,n).root},e.transform=function(i,n){return this._run(i,n).then(function(a){return a.transform})},e.transformSync=function(i,n){return this._runSync(i,n).transform},e.process=function(i,n){return this._run(i,n).then(function(a){return a.string||a.root.toString()})},e.processSync=function(i,n){var a=this._runSync(i,n);return a.string||a.root.toString()},r}();Yr.default=Hk;Tp.exports=Yr.default});var Dp=v(G=>{l();"use strict";G.__esModule=!0;G.universal=G.tag=G.string=G.selector=G.root=G.pseudo=G.nesting=G.id=G.comment=G.combinator=G.className=G.attribute=void 0;var Yk=ve(ya()),Qk=ve(ea()),Jk=ve(xa()),Xk=ve(ra()),Kk=ve(na()),Zk=ve(Sa()),eS=ve(ca()),tS=ve(Qs()),rS=ve(Xs()),iS=ve(ua()),nS=ve(oa()),sS=ve(ba());function ve(r){return r&&r.__esModule?r:{default:r}}var aS=function(e){return new Yk.default(e)};G.attribute=aS;var oS=function(e){return new Qk.default(e)};G.className=oS;var lS=function(e){return new Jk.default(e)};G.combinator=lS;var uS=function(e){return new Xk.default(e)};G.comment=uS;var fS=function(e){return new Kk.default(e)};G.id=fS;var cS=function(e){return new Zk.default(e)};G.nesting=cS;var pS=function(e){return new eS.default(e)};G.pseudo=pS;var dS=function(e){return new tS.default(e)};G.root=dS;var hS=function(e){return new rS.default(e)};G.selector=hS;var mS=function(e){return new iS.default(e)};G.string=mS;var gS=function(e){return new nS.default(e)};G.tag=gS;var yS=function(e){return new sS.default(e)};G.universal=yS});var Mp=v($=>{l();"use strict";$.__esModule=!0;$.isComment=$.isCombinator=$.isClassName=$.isAttribute=void 0;$.isContainer=TS;$.isIdentifier=void 0;$.isNamespace=PS;$.isNesting=void 0;$.isNode=qa;$.isPseudo=void 0;$.isPseudoClass=ES;$.isPseudoElement=Rp;$.isUniversal=$.isTag=$.isString=$.isSelector=$.isRoot=void 0;var Q=ne(),fe,wS=(fe={},fe[Q.ATTRIBUTE]=!0,fe[Q.CLASS]=!0,fe[Q.COMBINATOR]=!0,fe[Q.COMMENT]=!0,fe[Q.ID]=!0,fe[Q.NESTING]=!0,fe[Q.PSEUDO]=!0,fe[Q.ROOT]=!0,fe[Q.SELECTOR]=!0,fe[Q.STRING]=!0,fe[Q.TAG]=!0,fe[Q.UNIVERSAL]=!0,fe);function qa(r){return typeof r=="object"&&wS[r.type]}function xe(r,e){return qa(e)&&e.type===r}var Ip=xe.bind(null,Q.ATTRIBUTE);$.isAttribute=Ip;var bS=xe.bind(null,Q.CLASS);$.isClassName=bS;var vS=xe.bind(null,Q.COMBINATOR);$.isCombinator=vS;var xS=xe.bind(null,Q.COMMENT);$.isComment=xS;var kS=xe.bind(null,Q.ID);$.isIdentifier=kS;var SS=xe.bind(null,Q.NESTING);$.isNesting=SS;var Ra=xe.bind(null,Q.PSEUDO);$.isPseudo=Ra;var CS=xe.bind(null,Q.ROOT);$.isRoot=CS;var AS=xe.bind(null,Q.SELECTOR);$.isSelector=AS;var _S=xe.bind(null,Q.STRING);$.isString=_S;var qp=xe.bind(null,Q.TAG);$.isTag=qp;var OS=xe.bind(null,Q.UNIVERSAL);$.isUniversal=OS;function Rp(r){return Ra(r)&&r.value&&(r.value.startsWith("::")||r.value.toLowerCase()===":before"||r.value.toLowerCase()===":after"||r.value.toLowerCase()===":first-letter"||r.value.toLowerCase()===":first-line")}function ES(r){return Ra(r)&&!Rp(r)}function TS(r){return!!(qa(r)&&r.walk)}function PS(r){return Ip(r)||qp(r)}});var Bp=v(Ee=>{l();"use strict";Ee.__esModule=!0;var Ma=ne();Object.keys(Ma).forEach(function(r){r==="default"||r==="__esModule"||r in Ee&&Ee[r]===Ma[r]||(Ee[r]=Ma[r])});var Ba=Dp();Object.keys(Ba).forEach(function(r){r==="default"||r==="__esModule"||r in Ee&&Ee[r]===Ba[r]||(Ee[r]=Ba[r])});var Fa=Mp();Object.keys(Fa).forEach(function(r){r==="default"||r==="__esModule"||r in Ee&&Ee[r]===Fa[r]||(Ee[r]=Fa[r])})});var Me=v((Qr,Lp)=>{l();"use strict";Qr.__esModule=!0;Qr.default=void 0;var DS=RS(Pp()),IS=qS(Bp());function Fp(r){if(typeof WeakMap!="function")return null;var e=new WeakMap,t=new WeakMap;return(Fp=function(n){return n?t:e})(r)}function qS(r,e){if(!e&&r&&r.__esModule)return r;if(r===null||typeof r!="object"&&typeof r!="function")return{default:r};var t=Fp(e);if(t&&t.has(r))return t.get(r);var i={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in r)if(a!=="default"&&Object.prototype.hasOwnProperty.call(r,a)){var s=n?Object.getOwnPropertyDescriptor(r,a):null;s&&(s.get||s.set)?Object.defineProperty(i,a,s):i[a]=r[a]}return i.default=r,t&&t.set(r,i),i}function RS(r){return r&&r.__esModule?r:{default:r}}var La=function(e){return new DS.default(e)};Object.assign(La,IS);delete La.__esModule;var MS=La;Qr.default=MS;Lp.exports=Qr.default});function Ge(r){return["fontSize","outline"].includes(r)?e=>(typeof e=="function"&&(e=e({})),Array.isArray(e)&&(e=e[0]),e):r==="fontFamily"?e=>{typeof e=="function"&&(e=e({}));let t=Array.isArray(e)&&ie(e[1])?e[0]:e;return Array.isArray(t)?t.join(", "):t}:["boxShadow","transitionProperty","transitionDuration","transitionDelay","transitionTimingFunction","backgroundImage","backgroundSize","backgroundColor","cursor","animation"].includes(r)?e=>(typeof e=="function"&&(e=e({})),Array.isArray(e)&&(e=e.join(", ")),e):["gridTemplateColumns","gridTemplateRows","objectPosition"].includes(r)?e=>(typeof e=="function"&&(e=e({})),typeof e=="string"&&(e=j.list.comma(e).join(" ")),e):(e,t={})=>(typeof e=="function"&&(e=e(t)),e)}var Jr=C(()=>{l();st();At()});var Wp=v((PT,Va)=>{l();var{Rule:Np,AtRule:BS}=ge(),$p=Me();function Na(r,e){let t;try{$p(i=>{t=i}).processSync(r)}catch(i){throw r.includes(":")?e?e.error("Missed semicolon"):i:e?e.error(i.message):i}return t.at(0)}function zp(r,e){let t=!1;return r.each(i=>{if(i.type==="nesting"){let n=e.clone({});i.value!=="&"?i.replaceWith(Na(i.value.replace("&",n.toString()))):i.replaceWith(n),t=!0}else"nodes"in i&&i.nodes&&zp(i,e)&&(t=!0)}),t}function jp(r,e){let t=[];return r.selectors.forEach(i=>{let n=Na(i,r);e.selectors.forEach(a=>{if(!a)return;let s=Na(a,e);zp(s,n)||(s.prepend($p.combinator({value:" "})),s.prepend(n.clone({}))),t.push(s.toString())})}),t}function cn(r,e){let t=r.prev();for(e.after(r);t&&t.type==="comment";){let i=t.prev();e.after(t),t=i}return r}function FS(r){return function e(t,i,n,a=n){let s=[];if(i.each(o=>{o.type==="rule"&&n?a&&(o.selectors=jp(t,o)):o.type==="atrule"&&o.nodes?r[o.name]?e(t,o,a):i[za]!==!1&&s.push(o):s.push(o)}),n&&s.length){let o=t.clone({nodes:[]});for(let u of s)o.append(u);i.prepend(o)}}}function $a(r,e,t){let i=new Np({selector:r,nodes:[]});return i.append(e),t.after(i),i}function Vp(r,e){let t={};for(let i of r)t[i]=!0;if(e)for(let i of e)t[i.replace(/^@/,"")]=!0;return t}function LS(r){r=r.trim();let e=r.match(/^\((.*)\)$/);if(!e)return{type:"basic",selector:r};let t=e[1].match(/^(with(?:out)?):(.+)$/);if(t){let i=t[1]==="with",n=Object.fromEntries(t[2].trim().split(/\s+/).map(s=>[s,!0]));if(i&&n.all)return{type:"noop"};let a=s=>!!n[s];return n.all?a=()=>!0:i&&(a=s=>s==="all"?!1:!n[s]),{type:"withrules",escapes:a}}return{type:"unknown"}}function NS(r){let e=[],t=r.parent;for(;t&&t instanceof BS;)e.push(t),t=t.parent;return e}function $S(r){let e=r[Up];if(!e)r.after(r.nodes);else{let t=r.nodes,i,n=-1,a,s,o,u=NS(r);if(u.forEach((c,f)=>{if(e(c.name))i=c,n=f,s=o;else{let d=o;o=c.clone({nodes:[]}),d&&o.append(d),a=a||o}}),i?s?(a.append(t),i.after(s)):i.after(t):r.after(t),r.next()&&i){let c;u.slice(0,n+1).forEach((f,d,p)=>{let m=c;c=f.clone({nodes:[]}),m&&c.append(m);let b=[],y=(p[d-1]||r).next();for(;y;)b.push(y),y=y.next();c.append(b)}),c&&(s||t[t.length-1]).after(c)}}r.remove()}var za=Symbol("rootRuleMergeSel"),Up=Symbol("rootRuleEscapes");function zS(r){let{params:e}=r,{type:t,selector:i,escapes:n}=LS(e);if(t==="unknown")throw r.error(`Unknown @${r.name} parameter ${JSON.stringify(e)}`);if(t==="basic"&&i){let a=new Np({selector:i,nodes:r.nodes});r.removeAll(),r.append(a)}r[Up]=n,r[za]=n?!n("all"):t==="noop"}var ja=Symbol("hasRootRule");Va.exports=(r={})=>{let e=Vp(["media","supports","layer","container"],r.bubble),t=FS(e),i=Vp(["document","font-face","keyframes","-webkit-keyframes","-moz-keyframes"],r.unwrap),n=(r.rootRuleName||"at-root").replace(/^@/,""),a=r.preserveEmpty;return{postcssPlugin:"postcss-nested",Once(s){s.walkAtRules(n,o=>{zS(o),s[ja]=!0})},Rule(s){let o=!1,u=s,c=!1,f=[];s.each(d=>{d.type==="rule"?(f.length&&(u=$a(s.selector,f,u),f=[]),c=!0,o=!0,d.selectors=jp(s,d),u=cn(d,u)):d.type==="atrule"?(f.length&&(u=$a(s.selector,f,u),f=[]),d.name===n?(o=!0,t(s,d,!0,d[za]),u=cn(d,u)):e[d.name]?(c=!0,o=!0,t(s,d,!0),u=cn(d,u)):i[d.name]?(c=!0,o=!0,t(s,d,!1),u=cn(d,u)):c&&f.push(d)):d.type==="decl"&&c&&f.push(d)}),f.length&&(u=$a(s.selector,f,u)),o&&a!==!0&&(s.raws.semicolon=!0,s.nodes.length===0&&s.remove())},RootExit(s){s[ja]&&(s.walkAtRules(n,$S),s[ja]=!1)}}};Va.exports.postcss=!0});var Qp=v((DT,Yp)=>{l();"use strict";var Gp=/-(\w|$)/g,Hp=(r,e)=>e.toUpperCase(),jS=r=>(r=r.toLowerCase(),r==="float"?"cssFloat":r.startsWith("-ms-")?r.substr(1).replace(Gp,Hp):r.replace(Gp,Hp));Yp.exports=jS});var Ga=v((IT,Jp)=>{l();var VS=Qp(),US={boxFlex:!0,boxFlexGroup:!0,columnCount:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,strokeDashoffset:!0,strokeOpacity:!0,strokeWidth:!0};function Ua(r){return typeof r.nodes=="undefined"?!0:Wa(r)}function Wa(r){let e,t={};return r.each(i=>{if(i.type==="atrule")e="@"+i.name,i.params&&(e+=" "+i.params),typeof t[e]=="undefined"?t[e]=Ua(i):Array.isArray(t[e])?t[e].push(Ua(i)):t[e]=[t[e],Ua(i)];else if(i.type==="rule"){let n=Wa(i);if(t[i.selector])for(let a in n)t[i.selector][a]=n[a];else t[i.selector]=n}else if(i.type==="decl"){i.prop[0]==="-"&&i.prop[1]==="-"||i.parent&&i.parent.selector===":export"?e=i.prop:e=VS(i.prop);let n=i.value;!isNaN(i.value)&&US[e]&&(n=parseFloat(i.value)),i.important&&(n+=" !important"),typeof t[e]=="undefined"?t[e]=n:Array.isArray(t[e])?t[e].push(n):t[e]=[t[e],n]}}),t}Jp.exports=Wa});var pn=v((qT,ed)=>{l();var Xr=ge(),Xp=/\s*!important\s*$/i,WS={"box-flex":!0,"box-flex-group":!0,"column-count":!0,flex:!0,"flex-grow":!0,"flex-positive":!0,"flex-shrink":!0,"flex-negative":!0,"font-weight":!0,"line-clamp":!0,"line-height":!0,opacity:!0,order:!0,orphans:!0,"tab-size":!0,widows:!0,"z-index":!0,zoom:!0,"fill-opacity":!0,"stroke-dashoffset":!0,"stroke-opacity":!0,"stroke-width":!0};function GS(r){return r.replace(/([A-Z])/g,"-$1").replace(/^ms-/,"-ms-").toLowerCase()}function Kp(r,e,t){t===!1||t===null||(e.startsWith("--")||(e=GS(e)),typeof t=="number"&&(t===0||WS[e]?t=t.toString():t+="px"),e==="css-float"&&(e="float"),Xp.test(t)?(t=t.replace(Xp,""),r.push(Xr.decl({prop:e,value:t,important:!0}))):r.push(Xr.decl({prop:e,value:t})))}function Zp(r,e,t){let i=Xr.atRule({name:e[1],params:e[3]||""});typeof t=="object"&&(i.nodes=[],Ha(t,i)),r.push(i)}function Ha(r,e){let t,i,n;for(t in r)if(i=r[t],!(i===null||typeof i=="undefined"))if(t[0]==="@"){let a=t.match(/@(\S+)(\s+([\W\w]*)\s*)?/);if(Array.isArray(i))for(let s of i)Zp(e,a,s);else Zp(e,a,i)}else if(Array.isArray(i))for(let a of i)Kp(e,t,a);else typeof i=="object"?(n=Xr.rule({selector:t}),Ha(i,n),e.push(n)):Kp(e,t,i)}ed.exports=function(r){let e=Xr.root();return Ha(r,e),e}});var Ya=v((RT,td)=>{l();var HS=Ga();td.exports=function(e){return console&&console.warn&&e.warnings().forEach(t=>{let i=t.plugin||"PostCSS";console.warn(i+": "+t.text)}),HS(e.root)}});var id=v((MT,rd)=>{l();var YS=ge(),QS=Ya(),JS=pn();rd.exports=function(e){let t=YS(e);return async i=>{let n=await t.process(i,{parser:JS,from:void 0});return QS(n)}}});var sd=v((BT,nd)=>{l();var XS=ge(),KS=Ya(),ZS=pn();nd.exports=function(r){let e=XS(r);return t=>{let i=e.process(t,{parser:ZS,from:void 0});return KS(i)}}});var od=v((FT,ad)=>{l();var e2=Ga(),t2=pn(),r2=id(),i2=sd();ad.exports={objectify:e2,parse:t2,async:r2,sync:i2}});var Ft,ld,LT,NT,$T,zT,ud=C(()=>{l();Ft=X(od()),ld=Ft.default,LT=Ft.default.objectify,NT=Ft.default.parse,$T=Ft.default.async,zT=Ft.default.sync});function Lt(r){return Array.isArray(r)?r.flatMap(e=>j([(0,fd.default)({bubble:["screen"]})]).process(e,{parser:ld}).root.nodes):Lt([r])}var fd,Qa=C(()=>{l();st();fd=X(Wp());ud()});function Nt(r,e,t=!1){if(r==="")return e;let i=typeof e=="string"?(0,cd.default)().astSync(e):e;return i.walkClasses(n=>{let a=n.value,s=t&&a.startsWith("-");n.value=s?`-${r}${a.slice(1)}`:`${r}${a}`}),typeof e=="string"?i.toString():i}var cd,dn=C(()=>{l();cd=X(Me())});function ce(r){let e=pd.default.className();return e.value=r,wt(e?.raws?.value??e.value)}var pd,$t=C(()=>{l();pd=X(Me());bi()});function Ja(r){return wt(`.${ce(r)}`)}function hn(r,e){return Ja(Kr(r,e))}function Kr(r,e){return e==="DEFAULT"?r:e==="-"||e==="-DEFAULT"?`-${r}`:e.startsWith("-")?`-${r}${e}`:e.startsWith("/")?`${r}${e}`:`${r}-${e}`}var Xa=C(()=>{l();$t();bi()});function P(r,e=[[r,[r]]],{filterDefault:t=!1,...i}={}){let n=Ge(r);return function({matchUtilities:a,theme:s}){for(let o of e){let u=Array.isArray(o[0])?o:[o];a(u.reduce((c,[f,d])=>Object.assign(c,{[f]:p=>d.reduce((m,b)=>Array.isArray(b)?Object.assign(m,{[b[0]]:b[1]}):Object.assign(m,{[b]:n(p)}),{})}),{}),{...i,values:t?Object.fromEntries(Object.entries(s(r)??{}).filter(([c])=>c!=="DEFAULT")):s(r)})}}}var dd=C(()=>{l();Jr()});function at(r){return r=Array.isArray(r)?r:[r],r.map(e=>{let t=e.values.map(i=>i.raw!==void 0?i.raw:[i.min&&`(min-width: ${i.min})`,i.max&&`(max-width: ${i.max})`].filter(Boolean).join(" and "));return e.not?`not all and ${t}`:t}).join(", ")}var mn=C(()=>{l()});function Ka(r){return r.split(f2).map(t=>{let i=t.trim(),n={value:i},a=i.split(c2),s=new Set;for(let o of a)!s.has("DIRECTIONS")&&n2.has(o)?(n.direction=o,s.add("DIRECTIONS")):!s.has("PLAY_STATES")&&s2.has(o)?(n.playState=o,s.add("PLAY_STATES")):!s.has("FILL_MODES")&&a2.has(o)?(n.fillMode=o,s.add("FILL_MODES")):!s.has("ITERATION_COUNTS")&&(o2.has(o)||p2.test(o))?(n.iterationCount=o,s.add("ITERATION_COUNTS")):!s.has("TIMING_FUNCTION")&&l2.has(o)||!s.has("TIMING_FUNCTION")&&u2.some(u=>o.startsWith(`${u}(`))?(n.timingFunction=o,s.add("TIMING_FUNCTION")):!s.has("DURATION")&&hd.test(o)?(n.duration=o,s.add("DURATION")):!s.has("DELAY")&&hd.test(o)?(n.delay=o,s.add("DELAY")):s.has("NAME")?(n.unknown||(n.unknown=[]),n.unknown.push(o)):(n.name=o,s.add("NAME"));return n})}var n2,s2,a2,o2,l2,u2,f2,c2,hd,p2,md=C(()=>{l();n2=new Set(["normal","reverse","alternate","alternate-reverse"]),s2=new Set(["running","paused"]),a2=new Set(["none","forwards","backwards","both"]),o2=new Set(["infinite"]),l2=new Set(["linear","ease","ease-in","ease-out","ease-in-out","step-start","step-end"]),u2=["cubic-bezier","steps"],f2=/\,(?![^(]*\))/g,c2=/\ +(?![^(]*\))/g,hd=/^(-?[\d.]+m?s)$/,p2=/^(\d+)$/});var gd,re,yd=C(()=>{l();gd=r=>Object.assign({},...Object.entries(r??{}).flatMap(([e,t])=>typeof t=="object"?Object.entries(gd(t)).map(([i,n])=>({[e+(i==="DEFAULT"?"":`-${i}`)]:n})):[{[`${e}`]:t}])),re=gd});var bd,wd=C(()=>{bd="3.4.3"});function ot(r,e=!0){return Array.isArray(r)?r.map(t=>{if(e&&Array.isArray(t))throw new Error("The tuple syntax is not supported for `screens`.");if(typeof t=="string")return{name:t.toString(),not:!1,values:[{min:t,max:void 0}]};let[i,n]=t;return i=i.toString(),typeof n=="string"?{name:i,not:!1,values:[{min:n,max:void 0}]}:Array.isArray(n)?{name:i,not:!1,values:n.map(a=>xd(a))}:{name:i,not:!1,values:[xd(n)]}}):ot(Object.entries(r??{}),!1)}function gn(r){return r.values.length!==1?{result:!1,reason:"multiple-values"}:r.values[0].raw!==void 0?{result:!1,reason:"raw-values"}:r.values[0].min!==void 0&&r.values[0].max!==void 0?{result:!1,reason:"min-and-max"}:{result:!0,reason:null}}function vd(r,e,t){let i=yn(e,r),n=yn(t,r),a=gn(i),s=gn(n);if(a.reason==="multiple-values"||s.reason==="multiple-values")throw new Error("Attempted to sort a screen with multiple values. This should never happen. Please open a bug report.");if(a.reason==="raw-values"||s.reason==="raw-values")throw new Error("Attempted to sort a screen with raw values. This should never happen. Please open a bug report.");if(a.reason==="min-and-max"||s.reason==="min-and-max")throw new Error("Attempted to sort a screen with both min and max values. This should never happen. Please open a bug report.");let{min:o,max:u}=i.values[0],{min:c,max:f}=n.values[0];e.not&&([o,u]=[u,o]),t.not&&([c,f]=[f,c]),o=o===void 0?o:parseFloat(o),u=u===void 0?u:parseFloat(u),c=c===void 0?c:parseFloat(c),f=f===void 0?f:parseFloat(f);let[d,p]=r==="min"?[o,c]:[f,u];return d-p}function yn(r,e){return typeof r=="object"?r:{name:"arbitrary-screen",values:[{[e]:r}]}}function xd({"min-width":r,min:e=r,max:t,raw:i}={}){return{min:e,max:t,raw:i}}var wn=C(()=>{l()});function bn(r,e){r.walkDecls(t=>{if(e.includes(t.prop)){t.remove();return}for(let i of e)t.value.includes(`/ var(${i})`)&&(t.value=t.value.replace(`/ var(${i})`,""))})}var kd=C(()=>{l()});var H,Te,Be,Fe,Sd,Cd=C(()=>{l();ze();bt();st();dd();mn();$t();md();yd();fr();ws();At();Jr();wd();Oe();wn();cs();kd();je();dr();ei();H={childVariant:({addVariant:r})=>{r("*","& > *")},pseudoElementVariants:({addVariant:r})=>{r("first-letter","&::first-letter"),r("first-line","&::first-line"),r("marker",[({container:e})=>(bn(e,["--tw-text-opacity"]),"& *::marker"),({container:e})=>(bn(e,["--tw-text-opacity"]),"&::marker")]),r("selection",["& *::selection","&::selection"]),r("file","&::file-selector-button"),r("placeholder","&::placeholder"),r("backdrop","&::backdrop"),r("before",({container:e})=>(e.walkRules(t=>{let i=!1;t.walkDecls("content",()=>{i=!0}),i||t.prepend(j.decl({prop:"content",value:"var(--tw-content)"}))}),"&::before")),r("after",({container:e})=>(e.walkRules(t=>{let i=!1;t.walkDecls("content",()=>{i=!0}),i||t.prepend(j.decl({prop:"content",value:"var(--tw-content)"}))}),"&::after"))},pseudoClassVariants:({addVariant:r,matchVariant:e,config:t,prefix:i})=>{let n=[["first","&:first-child"],["last","&:last-child"],["only","&:only-child"],["odd","&:nth-child(odd)"],["even","&:nth-child(even)"],"first-of-type","last-of-type","only-of-type",["visited",({container:s})=>(bn(s,["--tw-text-opacity","--tw-border-opacity","--tw-bg-opacity"]),"&:visited")],"target",["open","&[open]"],"default","checked","indeterminate","placeholder-shown","autofill","optional","required","valid","invalid","in-range","out-of-range","read-only","empty","focus-within",["hover",K(t(),"hoverOnlyWhenSupported")?"@media (hover: hover) and (pointer: fine) { &:hover }":"&:hover"],"focus","focus-visible","active","enabled","disabled"].map(s=>Array.isArray(s)?s:[s,`&:${s}`]);for(let[s,o]of n)r(s,u=>typeof o=="function"?o(u):o);let a={group:(s,{modifier:o})=>o?[`:merge(${i(".group")}\\/${ce(o)})`," &"]:[`:merge(${i(".group")})`," &"],peer:(s,{modifier:o})=>o?[`:merge(${i(".peer")}\\/${ce(o)})`," ~ &"]:[`:merge(${i(".peer")})`," ~ &"]};for(let[s,o]of Object.entries(a))e(s,(u="",c)=>{let f=L(typeof u=="function"?u(c):u);f.includes("&")||(f="&"+f);let[d,p]=o("",c),m=null,b=null,x=0;for(let y=0;y{r("ltr",'&:where([dir="ltr"], [dir="ltr"] *)'),r("rtl",'&:where([dir="rtl"], [dir="rtl"] *)')},reducedMotionVariants:({addVariant:r})=>{r("motion-safe","@media (prefers-reduced-motion: no-preference)"),r("motion-reduce","@media (prefers-reduced-motion: reduce)")},darkVariants:({config:r,addVariant:e})=>{let[t,i=".dark"]=[].concat(r("darkMode","media"));if(t===!1&&(t="media",F.warn("darkmode-false",["The `darkMode` option in your Tailwind CSS configuration is set to `false`, which now behaves the same as `media`.","Change `darkMode` to `media` or remove it entirely.","https://tailwindcss.com/docs/upgrade-guide#remove-dark-mode-configuration"])),t==="variant"){let n;if(Array.isArray(i)||typeof i=="function"?n=i:typeof i=="string"&&(n=[i]),Array.isArray(n))for(let a of n)a===".dark"?(t=!1,F.warn("darkmode-variant-without-selector",["When using `variant` for `darkMode`, you must provide a selector.",'Example: `darkMode: ["variant", ".your-selector &"]`'])):a.includes("&")||(t=!1,F.warn("darkmode-variant-without-ampersand",["When using `variant` for `darkMode`, your selector must contain `&`.",'Example `darkMode: ["variant", ".your-selector &"]`']));i=n}t==="selector"?e("dark",`&:where(${i}, ${i} *)`):t==="media"?e("dark","@media (prefers-color-scheme: dark)"):t==="variant"?e("dark",i):t==="class"&&e("dark",`&:is(${i} *)`)},printVariant:({addVariant:r})=>{r("print","@media print")},screenVariants:({theme:r,addVariant:e,matchVariant:t})=>{let i=r("screens")??{},n=Object.values(i).every(w=>typeof w=="string"),a=ot(r("screens")),s=new Set([]);function o(w){return w.match(/(\D+)$/)?.[1]??"(none)"}function u(w){w!==void 0&&s.add(o(w))}function c(w){return u(w),s.size===1}for(let w of a)for(let k of w.values)u(k.min),u(k.max);let f=s.size<=1;function d(w){return Object.fromEntries(a.filter(k=>gn(k).result).map(k=>{let{min:S,max:_}=k.values[0];if(w==="min"&&S!==void 0)return k;if(w==="min"&&_!==void 0)return{...k,not:!k.not};if(w==="max"&&_!==void 0)return k;if(w==="max"&&S!==void 0)return{...k,not:!k.not}}).map(k=>[k.name,k]))}function p(w){return(k,S)=>vd(w,k.value,S.value)}let m=p("max"),b=p("min");function x(w){return k=>{if(n)if(f){if(typeof k=="string"&&!c(k))return F.warn("minmax-have-mixed-units",["The `min-*` and `max-*` variants are not supported with a `screens` configuration containing mixed units."]),[]}else return F.warn("mixed-screen-units",["The `min-*` and `max-*` variants are not supported with a `screens` configuration containing mixed units."]),[];else return F.warn("complex-screen-config",["The `min-*` and `max-*` variants are not supported with a `screens` configuration containing objects."]),[];return[`@media ${at(yn(k,w))}`]}}t("max",x("max"),{sort:m,values:n?d("max"):{}});let y="min-screens";for(let w of a)e(w.name,`@media ${at(w)}`,{id:y,sort:n&&f?b:void 0,value:w});t("min",x("min"),{id:y,sort:b})},supportsVariants:({matchVariant:r,theme:e})=>{r("supports",(t="")=>{let i=L(t),n=/^\w*\s*\(/.test(i);return i=n?i.replace(/\b(and|or|not)\b/g," $1 "):i,n?`@supports ${i}`:(i.includes(":")||(i=`${i}: var(--tw)`),i.startsWith("(")&&i.endsWith(")")||(i=`(${i})`),`@supports ${i}`)},{values:e("supports")??{}})},hasVariants:({matchVariant:r})=>{r("has",e=>`&:has(${L(e)})`,{values:{}}),r("group-has",(e,{modifier:t})=>t?`:merge(.group\\/${t}):has(${L(e)}) &`:`:merge(.group):has(${L(e)}) &`,{values:{}}),r("peer-has",(e,{modifier:t})=>t?`:merge(.peer\\/${t}):has(${L(e)}) ~ &`:`:merge(.peer):has(${L(e)}) ~ &`,{values:{}})},ariaVariants:({matchVariant:r,theme:e})=>{r("aria",t=>`&[aria-${L(t)}]`,{values:e("aria")??{}}),r("group-aria",(t,{modifier:i})=>i?`:merge(.group\\/${i})[aria-${L(t)}] &`:`:merge(.group)[aria-${L(t)}] &`,{values:e("aria")??{}}),r("peer-aria",(t,{modifier:i})=>i?`:merge(.peer\\/${i})[aria-${L(t)}] ~ &`:`:merge(.peer)[aria-${L(t)}] ~ &`,{values:e("aria")??{}})},dataVariants:({matchVariant:r,theme:e})=>{r("data",t=>`&[data-${L(t)}]`,{values:e("data")??{}}),r("group-data",(t,{modifier:i})=>i?`:merge(.group\\/${i})[data-${L(t)}] &`:`:merge(.group)[data-${L(t)}] &`,{values:e("data")??{}}),r("peer-data",(t,{modifier:i})=>i?`:merge(.peer\\/${i})[data-${L(t)}] ~ &`:`:merge(.peer)[data-${L(t)}] ~ &`,{values:e("data")??{}})},orientationVariants:({addVariant:r})=>{r("portrait","@media (orientation: portrait)"),r("landscape","@media (orientation: landscape)")},prefersContrastVariants:({addVariant:r})=>{r("contrast-more","@media (prefers-contrast: more)"),r("contrast-less","@media (prefers-contrast: less)")},forcedColorsVariants:({addVariant:r})=>{r("forced-colors","@media (forced-colors: active)")}},Te=["translate(var(--tw-translate-x), var(--tw-translate-y))","rotate(var(--tw-rotate))","skewX(var(--tw-skew-x))","skewY(var(--tw-skew-y))","scaleX(var(--tw-scale-x))","scaleY(var(--tw-scale-y))"].join(" "),Be=["var(--tw-blur)","var(--tw-brightness)","var(--tw-contrast)","var(--tw-grayscale)","var(--tw-hue-rotate)","var(--tw-invert)","var(--tw-saturate)","var(--tw-sepia)","var(--tw-drop-shadow)"].join(" "),Fe=["var(--tw-backdrop-blur)","var(--tw-backdrop-brightness)","var(--tw-backdrop-contrast)","var(--tw-backdrop-grayscale)","var(--tw-backdrop-hue-rotate)","var(--tw-backdrop-invert)","var(--tw-backdrop-opacity)","var(--tw-backdrop-saturate)","var(--tw-backdrop-sepia)"].join(" "),Sd={preflight:({addBase:r})=>{let e=j.parse(`*,::after,::before{box-sizing:border-box;border-width:0;border-style:solid;border-color:theme('borderColor.DEFAULT', currentColor)}::after,::before{--tw-content:''}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:theme('fontFamily.sans', ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:theme('fontFamily.sans[1].fontFeatureSettings', normal);font-variation-settings:theme('fontFamily.sans[1].fontVariationSettings', normal);-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:theme('fontFamily.mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:theme('fontFamily.mono[1].fontFeatureSettings', normal);font-variation-settings:theme('fontFamily.mono[1].fontVariationSettings', normal);font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:theme('colors.gray.4', #9ca3af)}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}`);r([j.comment({text:`! tailwindcss v${bd} | MIT License | https://tailwindcss.com`}),...e.nodes])},container:(()=>{function r(t=[]){return t.flatMap(i=>i.values.map(n=>n.min)).filter(i=>i!==void 0)}function e(t,i,n){if(typeof n=="undefined")return[];if(!(typeof n=="object"&&n!==null))return[{screen:"DEFAULT",minWidth:0,padding:n}];let a=[];n.DEFAULT&&a.push({screen:"DEFAULT",minWidth:0,padding:n.DEFAULT});for(let s of t)for(let o of i)for(let{min:u}of o.values)u===s&&a.push({minWidth:s,padding:n[o.name]});return a}return function({addComponents:t,theme:i}){let n=ot(i("container.screens",i("screens"))),a=r(n),s=e(a,n,i("container.padding")),o=c=>{let f=s.find(d=>d.minWidth===c);return f?{paddingRight:f.padding,paddingLeft:f.padding}:{}},u=Array.from(new Set(a.slice().sort((c,f)=>parseInt(c)-parseInt(f)))).map(c=>({[`@media (min-width: ${c})`]:{".container":{"max-width":c,...o(c)}}}));t([{".container":Object.assign({width:"100%"},i("container.center",!1)?{marginRight:"auto",marginLeft:"auto"}:{},o(0))},...u])}})(),accessibility:({addUtilities:r})=>{r({".sr-only":{position:"absolute",width:"1px",height:"1px",padding:"0",margin:"-1px",overflow:"hidden",clip:"rect(0, 0, 0, 0)",whiteSpace:"nowrap",borderWidth:"0"},".not-sr-only":{position:"static",width:"auto",height:"auto",padding:"0",margin:"0",overflow:"visible",clip:"auto",whiteSpace:"normal"}})},pointerEvents:({addUtilities:r})=>{r({".pointer-events-none":{"pointer-events":"none"},".pointer-events-auto":{"pointer-events":"auto"}})},visibility:({addUtilities:r})=>{r({".visible":{visibility:"visible"},".invisible":{visibility:"hidden"},".collapse":{visibility:"collapse"}})},position:({addUtilities:r})=>{r({".static":{position:"static"},".fixed":{position:"fixed"},".absolute":{position:"absolute"},".relative":{position:"relative"},".sticky":{position:"sticky"}})},inset:P("inset",[["inset",["inset"]],[["inset-x",["left","right"]],["inset-y",["top","bottom"]]],[["start",["inset-inline-start"]],["end",["inset-inline-end"]],["top",["top"]],["right",["right"]],["bottom",["bottom"]],["left",["left"]]]],{supportsNegativeValues:!0}),isolation:({addUtilities:r})=>{r({".isolate":{isolation:"isolate"},".isolation-auto":{isolation:"auto"}})},zIndex:P("zIndex",[["z",["zIndex"]]],{supportsNegativeValues:!0}),order:P("order",void 0,{supportsNegativeValues:!0}),gridColumn:P("gridColumn",[["col",["gridColumn"]]]),gridColumnStart:P("gridColumnStart",[["col-start",["gridColumnStart"]]]),gridColumnEnd:P("gridColumnEnd",[["col-end",["gridColumnEnd"]]]),gridRow:P("gridRow",[["row",["gridRow"]]]),gridRowStart:P("gridRowStart",[["row-start",["gridRowStart"]]]),gridRowEnd:P("gridRowEnd",[["row-end",["gridRowEnd"]]]),float:({addUtilities:r})=>{r({".float-start":{float:"inline-start"},".float-end":{float:"inline-end"},".float-right":{float:"right"},".float-left":{float:"left"},".float-none":{float:"none"}})},clear:({addUtilities:r})=>{r({".clear-start":{clear:"inline-start"},".clear-end":{clear:"inline-end"},".clear-left":{clear:"left"},".clear-right":{clear:"right"},".clear-both":{clear:"both"},".clear-none":{clear:"none"}})},margin:P("margin",[["m",["margin"]],[["mx",["margin-left","margin-right"]],["my",["margin-top","margin-bottom"]]],[["ms",["margin-inline-start"]],["me",["margin-inline-end"]],["mt",["margin-top"]],["mr",["margin-right"]],["mb",["margin-bottom"]],["ml",["margin-left"]]]],{supportsNegativeValues:!0}),boxSizing:({addUtilities:r})=>{r({".box-border":{"box-sizing":"border-box"},".box-content":{"box-sizing":"content-box"}})},lineClamp:({matchUtilities:r,addUtilities:e,theme:t})=>{r({"line-clamp":i=>({overflow:"hidden",display:"-webkit-box","-webkit-box-orient":"vertical","-webkit-line-clamp":`${i}`})},{values:t("lineClamp")}),e({".line-clamp-none":{overflow:"visible",display:"block","-webkit-box-orient":"horizontal","-webkit-line-clamp":"none"}})},display:({addUtilities:r})=>{r({".block":{display:"block"},".inline-block":{display:"inline-block"},".inline":{display:"inline"},".flex":{display:"flex"},".inline-flex":{display:"inline-flex"},".table":{display:"table"},".inline-table":{display:"inline-table"},".table-caption":{display:"table-caption"},".table-cell":{display:"table-cell"},".table-column":{display:"table-column"},".table-column-group":{display:"table-column-group"},".table-footer-group":{display:"table-footer-group"},".table-header-group":{display:"table-header-group"},".table-row-group":{display:"table-row-group"},".table-row":{display:"table-row"},".flow-root":{display:"flow-root"},".grid":{display:"grid"},".inline-grid":{display:"inline-grid"},".contents":{display:"contents"},".list-item":{display:"list-item"},".hidden":{display:"none"}})},aspectRatio:P("aspectRatio",[["aspect",["aspect-ratio"]]]),size:P("size",[["size",["width","height"]]]),height:P("height",[["h",["height"]]]),maxHeight:P("maxHeight",[["max-h",["maxHeight"]]]),minHeight:P("minHeight",[["min-h",["minHeight"]]]),width:P("width",[["w",["width"]]]),minWidth:P("minWidth",[["min-w",["minWidth"]]]),maxWidth:P("maxWidth",[["max-w",["maxWidth"]]]),flex:P("flex"),flexShrink:P("flexShrink",[["flex-shrink",["flex-shrink"]],["shrink",["flex-shrink"]]]),flexGrow:P("flexGrow",[["flex-grow",["flex-grow"]],["grow",["flex-grow"]]]),flexBasis:P("flexBasis",[["basis",["flex-basis"]]]),tableLayout:({addUtilities:r})=>{r({".table-auto":{"table-layout":"auto"},".table-fixed":{"table-layout":"fixed"}})},captionSide:({addUtilities:r})=>{r({".caption-top":{"caption-side":"top"},".caption-bottom":{"caption-side":"bottom"}})},borderCollapse:({addUtilities:r})=>{r({".border-collapse":{"border-collapse":"collapse"},".border-separate":{"border-collapse":"separate"}})},borderSpacing:({addDefaults:r,matchUtilities:e,theme:t})=>{r("border-spacing",{"--tw-border-spacing-x":0,"--tw-border-spacing-y":0}),e({"border-spacing":i=>({"--tw-border-spacing-x":i,"--tw-border-spacing-y":i,"@defaults border-spacing":{},"border-spacing":"var(--tw-border-spacing-x) var(--tw-border-spacing-y)"}),"border-spacing-x":i=>({"--tw-border-spacing-x":i,"@defaults border-spacing":{},"border-spacing":"var(--tw-border-spacing-x) var(--tw-border-spacing-y)"}),"border-spacing-y":i=>({"--tw-border-spacing-y":i,"@defaults border-spacing":{},"border-spacing":"var(--tw-border-spacing-x) var(--tw-border-spacing-y)"})},{values:t("borderSpacing")})},transformOrigin:P("transformOrigin",[["origin",["transformOrigin"]]]),translate:P("translate",[[["translate-x",[["@defaults transform",{}],"--tw-translate-x",["transform",Te]]],["translate-y",[["@defaults transform",{}],"--tw-translate-y",["transform",Te]]]]],{supportsNegativeValues:!0}),rotate:P("rotate",[["rotate",[["@defaults transform",{}],"--tw-rotate",["transform",Te]]]],{supportsNegativeValues:!0}),skew:P("skew",[[["skew-x",[["@defaults transform",{}],"--tw-skew-x",["transform",Te]]],["skew-y",[["@defaults transform",{}],"--tw-skew-y",["transform",Te]]]]],{supportsNegativeValues:!0}),scale:P("scale",[["scale",[["@defaults transform",{}],"--tw-scale-x","--tw-scale-y",["transform",Te]]],[["scale-x",[["@defaults transform",{}],"--tw-scale-x",["transform",Te]]],["scale-y",[["@defaults transform",{}],"--tw-scale-y",["transform",Te]]]]],{supportsNegativeValues:!0}),transform:({addDefaults:r,addUtilities:e})=>{r("transform",{"--tw-translate-x":"0","--tw-translate-y":"0","--tw-rotate":"0","--tw-skew-x":"0","--tw-skew-y":"0","--tw-scale-x":"1","--tw-scale-y":"1"}),e({".transform":{"@defaults transform":{},transform:Te},".transform-cpu":{transform:Te},".transform-gpu":{transform:Te.replace("translate(var(--tw-translate-x), var(--tw-translate-y))","translate3d(var(--tw-translate-x), var(--tw-translate-y), 0)")},".transform-none":{transform:"none"}})},animation:({matchUtilities:r,theme:e,config:t})=>{let i=a=>ce(t("prefix")+a),n=Object.fromEntries(Object.entries(e("keyframes")??{}).map(([a,s])=>[a,{[`@keyframes ${i(a)}`]:s}]));r({animate:a=>{let s=Ka(a);return[...s.flatMap(o=>n[o.name]),{animation:s.map(({name:o,value:u})=>o===void 0||n[o]===void 0?u:u.replace(o,i(o))).join(", ")}]}},{values:e("animation")})},cursor:P("cursor"),touchAction:({addDefaults:r,addUtilities:e})=>{r("touch-action",{"--tw-pan-x":" ","--tw-pan-y":" ","--tw-pinch-zoom":" "});let t="var(--tw-pan-x) var(--tw-pan-y) var(--tw-pinch-zoom)";e({".touch-auto":{"touch-action":"auto"},".touch-none":{"touch-action":"none"},".touch-pan-x":{"@defaults touch-action":{},"--tw-pan-x":"pan-x","touch-action":t},".touch-pan-left":{"@defaults touch-action":{},"--tw-pan-x":"pan-left","touch-action":t},".touch-pan-right":{"@defaults touch-action":{},"--tw-pan-x":"pan-right","touch-action":t},".touch-pan-y":{"@defaults touch-action":{},"--tw-pan-y":"pan-y","touch-action":t},".touch-pan-up":{"@defaults touch-action":{},"--tw-pan-y":"pan-up","touch-action":t},".touch-pan-down":{"@defaults touch-action":{},"--tw-pan-y":"pan-down","touch-action":t},".touch-pinch-zoom":{"@defaults touch-action":{},"--tw-pinch-zoom":"pinch-zoom","touch-action":t},".touch-manipulation":{"touch-action":"manipulation"}})},userSelect:({addUtilities:r})=>{r({".select-none":{"user-select":"none"},".select-text":{"user-select":"text"},".select-all":{"user-select":"all"},".select-auto":{"user-select":"auto"}})},resize:({addUtilities:r})=>{r({".resize-none":{resize:"none"},".resize-y":{resize:"vertical"},".resize-x":{resize:"horizontal"},".resize":{resize:"both"}})},scrollSnapType:({addDefaults:r,addUtilities:e})=>{r("scroll-snap-type",{"--tw-scroll-snap-strictness":"proximity"}),e({".snap-none":{"scroll-snap-type":"none"},".snap-x":{"@defaults scroll-snap-type":{},"scroll-snap-type":"x var(--tw-scroll-snap-strictness)"},".snap-y":{"@defaults scroll-snap-type":{},"scroll-snap-type":"y var(--tw-scroll-snap-strictness)"},".snap-both":{"@defaults scroll-snap-type":{},"scroll-snap-type":"both var(--tw-scroll-snap-strictness)"},".snap-mandatory":{"--tw-scroll-snap-strictness":"mandatory"},".snap-proximity":{"--tw-scroll-snap-strictness":"proximity"}})},scrollSnapAlign:({addUtilities:r})=>{r({".snap-start":{"scroll-snap-align":"start"},".snap-end":{"scroll-snap-align":"end"},".snap-center":{"scroll-snap-align":"center"},".snap-align-none":{"scroll-snap-align":"none"}})},scrollSnapStop:({addUtilities:r})=>{r({".snap-normal":{"scroll-snap-stop":"normal"},".snap-always":{"scroll-snap-stop":"always"}})},scrollMargin:P("scrollMargin",[["scroll-m",["scroll-margin"]],[["scroll-mx",["scroll-margin-left","scroll-margin-right"]],["scroll-my",["scroll-margin-top","scroll-margin-bottom"]]],[["scroll-ms",["scroll-margin-inline-start"]],["scroll-me",["scroll-margin-inline-end"]],["scroll-mt",["scroll-margin-top"]],["scroll-mr",["scroll-margin-right"]],["scroll-mb",["scroll-margin-bottom"]],["scroll-ml",["scroll-margin-left"]]]],{supportsNegativeValues:!0}),scrollPadding:P("scrollPadding",[["scroll-p",["scroll-padding"]],[["scroll-px",["scroll-padding-left","scroll-padding-right"]],["scroll-py",["scroll-padding-top","scroll-padding-bottom"]]],[["scroll-ps",["scroll-padding-inline-start"]],["scroll-pe",["scroll-padding-inline-end"]],["scroll-pt",["scroll-padding-top"]],["scroll-pr",["scroll-padding-right"]],["scroll-pb",["scroll-padding-bottom"]],["scroll-pl",["scroll-padding-left"]]]]),listStylePosition:({addUtilities:r})=>{r({".list-inside":{"list-style-position":"inside"},".list-outside":{"list-style-position":"outside"}})},listStyleType:P("listStyleType",[["list",["listStyleType"]]]),listStyleImage:P("listStyleImage",[["list-image",["listStyleImage"]]]),appearance:({addUtilities:r})=>{r({".appearance-none":{appearance:"none"},".appearance-auto":{appearance:"auto"}})},columns:P("columns",[["columns",["columns"]]]),breakBefore:({addUtilities:r})=>{r({".break-before-auto":{"break-before":"auto"},".break-before-avoid":{"break-before":"avoid"},".break-before-all":{"break-before":"all"},".break-before-avoid-page":{"break-before":"avoid-page"},".break-before-page":{"break-before":"page"},".break-before-left":{"break-before":"left"},".break-before-right":{"break-before":"right"},".break-before-column":{"break-before":"column"}})},breakInside:({addUtilities:r})=>{r({".break-inside-auto":{"break-inside":"auto"},".break-inside-avoid":{"break-inside":"avoid"},".break-inside-avoid-page":{"break-inside":"avoid-page"},".break-inside-avoid-column":{"break-inside":"avoid-column"}})},breakAfter:({addUtilities:r})=>{r({".break-after-auto":{"break-after":"auto"},".break-after-avoid":{"break-after":"avoid"},".break-after-all":{"break-after":"all"},".break-after-avoid-page":{"break-after":"avoid-page"},".break-after-page":{"break-after":"page"},".break-after-left":{"break-after":"left"},".break-after-right":{"break-after":"right"},".break-after-column":{"break-after":"column"}})},gridAutoColumns:P("gridAutoColumns",[["auto-cols",["gridAutoColumns"]]]),gridAutoFlow:({addUtilities:r})=>{r({".grid-flow-row":{gridAutoFlow:"row"},".grid-flow-col":{gridAutoFlow:"column"},".grid-flow-dense":{gridAutoFlow:"dense"},".grid-flow-row-dense":{gridAutoFlow:"row dense"},".grid-flow-col-dense":{gridAutoFlow:"column dense"}})},gridAutoRows:P("gridAutoRows",[["auto-rows",["gridAutoRows"]]]),gridTemplateColumns:P("gridTemplateColumns",[["grid-cols",["gridTemplateColumns"]]]),gridTemplateRows:P("gridTemplateRows",[["grid-rows",["gridTemplateRows"]]]),flexDirection:({addUtilities:r})=>{r({".flex-row":{"flex-direction":"row"},".flex-row-reverse":{"flex-direction":"row-reverse"},".flex-col":{"flex-direction":"column"},".flex-col-reverse":{"flex-direction":"column-reverse"}})},flexWrap:({addUtilities:r})=>{r({".flex-wrap":{"flex-wrap":"wrap"},".flex-wrap-reverse":{"flex-wrap":"wrap-reverse"},".flex-nowrap":{"flex-wrap":"nowrap"}})},placeContent:({addUtilities:r})=>{r({".place-content-center":{"place-content":"center"},".place-content-start":{"place-content":"start"},".place-content-end":{"place-content":"end"},".place-content-between":{"place-content":"space-between"},".place-content-around":{"place-content":"space-around"},".place-content-evenly":{"place-content":"space-evenly"},".place-content-baseline":{"place-content":"baseline"},".place-content-stretch":{"place-content":"stretch"}})},placeItems:({addUtilities:r})=>{r({".place-items-start":{"place-items":"start"},".place-items-end":{"place-items":"end"},".place-items-center":{"place-items":"center"},".place-items-baseline":{"place-items":"baseline"},".place-items-stretch":{"place-items":"stretch"}})},alignContent:({addUtilities:r})=>{r({".content-normal":{"align-content":"normal"},".content-center":{"align-content":"center"},".content-start":{"align-content":"flex-start"},".content-end":{"align-content":"flex-end"},".content-between":{"align-content":"space-between"},".content-around":{"align-content":"space-around"},".content-evenly":{"align-content":"space-evenly"},".content-baseline":{"align-content":"baseline"},".content-stretch":{"align-content":"stretch"}})},alignItems:({addUtilities:r})=>{r({".items-start":{"align-items":"flex-start"},".items-end":{"align-items":"flex-end"},".items-center":{"align-items":"center"},".items-baseline":{"align-items":"baseline"},".items-stretch":{"align-items":"stretch"}})},justifyContent:({addUtilities:r})=>{r({".justify-normal":{"justify-content":"normal"},".justify-start":{"justify-content":"flex-start"},".justify-end":{"justify-content":"flex-end"},".justify-center":{"justify-content":"center"},".justify-between":{"justify-content":"space-between"},".justify-around":{"justify-content":"space-around"},".justify-evenly":{"justify-content":"space-evenly"},".justify-stretch":{"justify-content":"stretch"}})},justifyItems:({addUtilities:r})=>{r({".justify-items-start":{"justify-items":"start"},".justify-items-end":{"justify-items":"end"},".justify-items-center":{"justify-items":"center"},".justify-items-stretch":{"justify-items":"stretch"}})},gap:P("gap",[["gap",["gap"]],[["gap-x",["columnGap"]],["gap-y",["rowGap"]]]]),space:({matchUtilities:r,addUtilities:e,theme:t})=>{r({"space-x":i=>(i=i==="0"?"0px":i,{"& > :not([hidden]) ~ :not([hidden])":{"--tw-space-x-reverse":"0","margin-right":`calc(${i} * var(--tw-space-x-reverse))`,"margin-left":`calc(${i} * calc(1 - var(--tw-space-x-reverse)))`}}),"space-y":i=>(i=i==="0"?"0px":i,{"& > :not([hidden]) ~ :not([hidden])":{"--tw-space-y-reverse":"0","margin-top":`calc(${i} * calc(1 - var(--tw-space-y-reverse)))`,"margin-bottom":`calc(${i} * var(--tw-space-y-reverse))`}})},{values:t("space"),supportsNegativeValues:!0}),e({".space-y-reverse > :not([hidden]) ~ :not([hidden])":{"--tw-space-y-reverse":"1"},".space-x-reverse > :not([hidden]) ~ :not([hidden])":{"--tw-space-x-reverse":"1"}})},divideWidth:({matchUtilities:r,addUtilities:e,theme:t})=>{r({"divide-x":i=>(i=i==="0"?"0px":i,{"& > :not([hidden]) ~ :not([hidden])":{"@defaults border-width":{},"--tw-divide-x-reverse":"0","border-right-width":`calc(${i} * var(--tw-divide-x-reverse))`,"border-left-width":`calc(${i} * calc(1 - var(--tw-divide-x-reverse)))`}}),"divide-y":i=>(i=i==="0"?"0px":i,{"& > :not([hidden]) ~ :not([hidden])":{"@defaults border-width":{},"--tw-divide-y-reverse":"0","border-top-width":`calc(${i} * calc(1 - var(--tw-divide-y-reverse)))`,"border-bottom-width":`calc(${i} * var(--tw-divide-y-reverse))`}})},{values:t("divideWidth"),type:["line-width","length","any"]}),e({".divide-y-reverse > :not([hidden]) ~ :not([hidden])":{"@defaults border-width":{},"--tw-divide-y-reverse":"1"},".divide-x-reverse > :not([hidden]) ~ :not([hidden])":{"@defaults border-width":{},"--tw-divide-x-reverse":"1"}})},divideStyle:({addUtilities:r})=>{r({".divide-solid > :not([hidden]) ~ :not([hidden])":{"border-style":"solid"},".divide-dashed > :not([hidden]) ~ :not([hidden])":{"border-style":"dashed"},".divide-dotted > :not([hidden]) ~ :not([hidden])":{"border-style":"dotted"},".divide-double > :not([hidden]) ~ :not([hidden])":{"border-style":"double"},".divide-none > :not([hidden]) ~ :not([hidden])":{"border-style":"none"}})},divideColor:({matchUtilities:r,theme:e,corePlugins:t})=>{r({divide:i=>t("divideOpacity")?{["& > :not([hidden]) ~ :not([hidden])"]:se({color:i,property:"border-color",variable:"--tw-divide-opacity"})}:{["& > :not([hidden]) ~ :not([hidden])"]:{"border-color":N(i)}}},{values:(({DEFAULT:i,...n})=>n)(re(e("divideColor"))),type:["color","any"]})},divideOpacity:({matchUtilities:r,theme:e})=>{r({"divide-opacity":t=>({["& > :not([hidden]) ~ :not([hidden])"]:{"--tw-divide-opacity":t}})},{values:e("divideOpacity")})},placeSelf:({addUtilities:r})=>{r({".place-self-auto":{"place-self":"auto"},".place-self-start":{"place-self":"start"},".place-self-end":{"place-self":"end"},".place-self-center":{"place-self":"center"},".place-self-stretch":{"place-self":"stretch"}})},alignSelf:({addUtilities:r})=>{r({".self-auto":{"align-self":"auto"},".self-start":{"align-self":"flex-start"},".self-end":{"align-self":"flex-end"},".self-center":{"align-self":"center"},".self-stretch":{"align-self":"stretch"},".self-baseline":{"align-self":"baseline"}})},justifySelf:({addUtilities:r})=>{r({".justify-self-auto":{"justify-self":"auto"},".justify-self-start":{"justify-self":"start"},".justify-self-end":{"justify-self":"end"},".justify-self-center":{"justify-self":"center"},".justify-self-stretch":{"justify-self":"stretch"}})},overflow:({addUtilities:r})=>{r({".overflow-auto":{overflow:"auto"},".overflow-hidden":{overflow:"hidden"},".overflow-clip":{overflow:"clip"},".overflow-visible":{overflow:"visible"},".overflow-scroll":{overflow:"scroll"},".overflow-x-auto":{"overflow-x":"auto"},".overflow-y-auto":{"overflow-y":"auto"},".overflow-x-hidden":{"overflow-x":"hidden"},".overflow-y-hidden":{"overflow-y":"hidden"},".overflow-x-clip":{"overflow-x":"clip"},".overflow-y-clip":{"overflow-y":"clip"},".overflow-x-visible":{"overflow-x":"visible"},".overflow-y-visible":{"overflow-y":"visible"},".overflow-x-scroll":{"overflow-x":"scroll"},".overflow-y-scroll":{"overflow-y":"scroll"}})},overscrollBehavior:({addUtilities:r})=>{r({".overscroll-auto":{"overscroll-behavior":"auto"},".overscroll-contain":{"overscroll-behavior":"contain"},".overscroll-none":{"overscroll-behavior":"none"},".overscroll-y-auto":{"overscroll-behavior-y":"auto"},".overscroll-y-contain":{"overscroll-behavior-y":"contain"},".overscroll-y-none":{"overscroll-behavior-y":"none"},".overscroll-x-auto":{"overscroll-behavior-x":"auto"},".overscroll-x-contain":{"overscroll-behavior-x":"contain"},".overscroll-x-none":{"overscroll-behavior-x":"none"}})},scrollBehavior:({addUtilities:r})=>{r({".scroll-auto":{"scroll-behavior":"auto"},".scroll-smooth":{"scroll-behavior":"smooth"}})},textOverflow:({addUtilities:r})=>{r({".truncate":{overflow:"hidden","text-overflow":"ellipsis","white-space":"nowrap"},".overflow-ellipsis":{"text-overflow":"ellipsis"},".text-ellipsis":{"text-overflow":"ellipsis"},".text-clip":{"text-overflow":"clip"}})},hyphens:({addUtilities:r})=>{r({".hyphens-none":{hyphens:"none"},".hyphens-manual":{hyphens:"manual"},".hyphens-auto":{hyphens:"auto"}})},whitespace:({addUtilities:r})=>{r({".whitespace-normal":{"white-space":"normal"},".whitespace-nowrap":{"white-space":"nowrap"},".whitespace-pre":{"white-space":"pre"},".whitespace-pre-line":{"white-space":"pre-line"},".whitespace-pre-wrap":{"white-space":"pre-wrap"},".whitespace-break-spaces":{"white-space":"break-spaces"}})},textWrap:({addUtilities:r})=>{r({".text-wrap":{"text-wrap":"wrap"},".text-nowrap":{"text-wrap":"nowrap"},".text-balance":{"text-wrap":"balance"},".text-pretty":{"text-wrap":"pretty"}})},wordBreak:({addUtilities:r})=>{r({".break-normal":{"overflow-wrap":"normal","word-break":"normal"},".break-words":{"overflow-wrap":"break-word"},".break-all":{"word-break":"break-all"},".break-keep":{"word-break":"keep-all"}})},borderRadius:P("borderRadius",[["rounded",["border-radius"]],[["rounded-s",["border-start-start-radius","border-end-start-radius"]],["rounded-e",["border-start-end-radius","border-end-end-radius"]],["rounded-t",["border-top-left-radius","border-top-right-radius"]],["rounded-r",["border-top-right-radius","border-bottom-right-radius"]],["rounded-b",["border-bottom-right-radius","border-bottom-left-radius"]],["rounded-l",["border-top-left-radius","border-bottom-left-radius"]]],[["rounded-ss",["border-start-start-radius"]],["rounded-se",["border-start-end-radius"]],["rounded-ee",["border-end-end-radius"]],["rounded-es",["border-end-start-radius"]],["rounded-tl",["border-top-left-radius"]],["rounded-tr",["border-top-right-radius"]],["rounded-br",["border-bottom-right-radius"]],["rounded-bl",["border-bottom-left-radius"]]]]),borderWidth:P("borderWidth",[["border",[["@defaults border-width",{}],"border-width"]],[["border-x",[["@defaults border-width",{}],"border-left-width","border-right-width"]],["border-y",[["@defaults border-width",{}],"border-top-width","border-bottom-width"]]],[["border-s",[["@defaults border-width",{}],"border-inline-start-width"]],["border-e",[["@defaults border-width",{}],"border-inline-end-width"]],["border-t",[["@defaults border-width",{}],"border-top-width"]],["border-r",[["@defaults border-width",{}],"border-right-width"]],["border-b",[["@defaults border-width",{}],"border-bottom-width"]],["border-l",[["@defaults border-width",{}],"border-left-width"]]]],{type:["line-width","length"]}),borderStyle:({addUtilities:r})=>{r({".border-solid":{"border-style":"solid"},".border-dashed":{"border-style":"dashed"},".border-dotted":{"border-style":"dotted"},".border-double":{"border-style":"double"},".border-hidden":{"border-style":"hidden"},".border-none":{"border-style":"none"}})},borderColor:({matchUtilities:r,theme:e,corePlugins:t})=>{r({border:i=>t("borderOpacity")?se({color:i,property:"border-color",variable:"--tw-border-opacity"}):{"border-color":N(i)}},{values:(({DEFAULT:i,...n})=>n)(re(e("borderColor"))),type:["color","any"]}),r({"border-x":i=>t("borderOpacity")?se({color:i,property:["border-left-color","border-right-color"],variable:"--tw-border-opacity"}):{"border-left-color":N(i),"border-right-color":N(i)},"border-y":i=>t("borderOpacity")?se({color:i,property:["border-top-color","border-bottom-color"],variable:"--tw-border-opacity"}):{"border-top-color":N(i),"border-bottom-color":N(i)}},{values:(({DEFAULT:i,...n})=>n)(re(e("borderColor"))),type:["color","any"]}),r({"border-s":i=>t("borderOpacity")?se({color:i,property:"border-inline-start-color",variable:"--tw-border-opacity"}):{"border-inline-start-color":N(i)},"border-e":i=>t("borderOpacity")?se({color:i,property:"border-inline-end-color",variable:"--tw-border-opacity"}):{"border-inline-end-color":N(i)},"border-t":i=>t("borderOpacity")?se({color:i,property:"border-top-color",variable:"--tw-border-opacity"}):{"border-top-color":N(i)},"border-r":i=>t("borderOpacity")?se({color:i,property:"border-right-color",variable:"--tw-border-opacity"}):{"border-right-color":N(i)},"border-b":i=>t("borderOpacity")?se({color:i,property:"border-bottom-color",variable:"--tw-border-opacity"}):{"border-bottom-color":N(i)},"border-l":i=>t("borderOpacity")?se({color:i,property:"border-left-color",variable:"--tw-border-opacity"}):{"border-left-color":N(i)}},{values:(({DEFAULT:i,...n})=>n)(re(e("borderColor"))),type:["color","any"]})},borderOpacity:P("borderOpacity",[["border-opacity",["--tw-border-opacity"]]]),backgroundColor:({matchUtilities:r,theme:e,corePlugins:t})=>{r({bg:i=>t("backgroundOpacity")?se({color:i,property:"background-color",variable:"--tw-bg-opacity"}):{"background-color":N(i)}},{values:re(e("backgroundColor")),type:["color","any"]})},backgroundOpacity:P("backgroundOpacity",[["bg-opacity",["--tw-bg-opacity"]]]),backgroundImage:P("backgroundImage",[["bg",["background-image"]]],{type:["lookup","image","url"]}),gradientColorStops:(()=>{function r(e){return Ie(e,0,"rgb(255 255 255 / 0)")}return function({matchUtilities:e,theme:t,addDefaults:i}){i("gradient-color-stops",{"--tw-gradient-from-position":" ","--tw-gradient-via-position":" ","--tw-gradient-to-position":" "});let n={values:re(t("gradientColorStops")),type:["color","any"]},a={values:t("gradientColorStopPositions"),type:["length","percentage"]};e({from:s=>{let o=r(s);return{"@defaults gradient-color-stops":{},"--tw-gradient-from":`${N(s)} var(--tw-gradient-from-position)`,"--tw-gradient-to":`${o} var(--tw-gradient-to-position)`,"--tw-gradient-stops":"var(--tw-gradient-from), var(--tw-gradient-to)"}}},n),e({from:s=>({"--tw-gradient-from-position":s})},a),e({via:s=>{let o=r(s);return{"@defaults gradient-color-stops":{},"--tw-gradient-to":`${o} var(--tw-gradient-to-position)`,"--tw-gradient-stops":`var(--tw-gradient-from), ${N(s)} var(--tw-gradient-via-position), var(--tw-gradient-to)`}}},n),e({via:s=>({"--tw-gradient-via-position":s})},a),e({to:s=>({"@defaults gradient-color-stops":{},"--tw-gradient-to":`${N(s)} var(--tw-gradient-to-position)`})},n),e({to:s=>({"--tw-gradient-to-position":s})},a)}})(),boxDecorationBreak:({addUtilities:r})=>{r({".decoration-slice":{"box-decoration-break":"slice"},".decoration-clone":{"box-decoration-break":"clone"},".box-decoration-slice":{"box-decoration-break":"slice"},".box-decoration-clone":{"box-decoration-break":"clone"}})},backgroundSize:P("backgroundSize",[["bg",["background-size"]]],{type:["lookup","length","percentage","size"]}),backgroundAttachment:({addUtilities:r})=>{r({".bg-fixed":{"background-attachment":"fixed"},".bg-local":{"background-attachment":"local"},".bg-scroll":{"background-attachment":"scroll"}})},backgroundClip:({addUtilities:r})=>{r({".bg-clip-border":{"background-clip":"border-box"},".bg-clip-padding":{"background-clip":"padding-box"},".bg-clip-content":{"background-clip":"content-box"},".bg-clip-text":{"background-clip":"text"}})},backgroundPosition:P("backgroundPosition",[["bg",["background-position"]]],{type:["lookup",["position",{preferOnConflict:!0}]]}),backgroundRepeat:({addUtilities:r})=>{r({".bg-repeat":{"background-repeat":"repeat"},".bg-no-repeat":{"background-repeat":"no-repeat"},".bg-repeat-x":{"background-repeat":"repeat-x"},".bg-repeat-y":{"background-repeat":"repeat-y"},".bg-repeat-round":{"background-repeat":"round"},".bg-repeat-space":{"background-repeat":"space"}})},backgroundOrigin:({addUtilities:r})=>{r({".bg-origin-border":{"background-origin":"border-box"},".bg-origin-padding":{"background-origin":"padding-box"},".bg-origin-content":{"background-origin":"content-box"}})},fill:({matchUtilities:r,theme:e})=>{r({fill:t=>({fill:N(t)})},{values:re(e("fill")),type:["color","any"]})},stroke:({matchUtilities:r,theme:e})=>{r({stroke:t=>({stroke:N(t)})},{values:re(e("stroke")),type:["color","url","any"]})},strokeWidth:P("strokeWidth",[["stroke",["stroke-width"]]],{type:["length","number","percentage"]}),objectFit:({addUtilities:r})=>{r({".object-contain":{"object-fit":"contain"},".object-cover":{"object-fit":"cover"},".object-fill":{"object-fit":"fill"},".object-none":{"object-fit":"none"},".object-scale-down":{"object-fit":"scale-down"}})},objectPosition:P("objectPosition",[["object",["object-position"]]]),padding:P("padding",[["p",["padding"]],[["px",["padding-left","padding-right"]],["py",["padding-top","padding-bottom"]]],[["ps",["padding-inline-start"]],["pe",["padding-inline-end"]],["pt",["padding-top"]],["pr",["padding-right"]],["pb",["padding-bottom"]],["pl",["padding-left"]]]]),textAlign:({addUtilities:r})=>{r({".text-left":{"text-align":"left"},".text-center":{"text-align":"center"},".text-right":{"text-align":"right"},".text-justify":{"text-align":"justify"},".text-start":{"text-align":"start"},".text-end":{"text-align":"end"}})},textIndent:P("textIndent",[["indent",["text-indent"]]],{supportsNegativeValues:!0}),verticalAlign:({addUtilities:r,matchUtilities:e})=>{r({".align-baseline":{"vertical-align":"baseline"},".align-top":{"vertical-align":"top"},".align-middle":{"vertical-align":"middle"},".align-bottom":{"vertical-align":"bottom"},".align-text-top":{"vertical-align":"text-top"},".align-text-bottom":{"vertical-align":"text-bottom"},".align-sub":{"vertical-align":"sub"},".align-super":{"vertical-align":"super"}}),e({align:t=>({"vertical-align":t})})},fontFamily:({matchUtilities:r,theme:e})=>{r({font:t=>{let[i,n={}]=Array.isArray(t)&&ie(t[1])?t:[t],{fontFeatureSettings:a,fontVariationSettings:s}=n;return{"font-family":Array.isArray(i)?i.join(", "):i,...a===void 0?{}:{"font-feature-settings":a},...s===void 0?{}:{"font-variation-settings":s}}}},{values:e("fontFamily"),type:["lookup","generic-name","family-name"]})},fontSize:({matchUtilities:r,theme:e})=>{r({text:(t,{modifier:i})=>{let[n,a]=Array.isArray(t)?t:[t];if(i)return{"font-size":n,"line-height":i};let{lineHeight:s,letterSpacing:o,fontWeight:u}=ie(a)?a:{lineHeight:a};return{"font-size":n,...s===void 0?{}:{"line-height":s},...o===void 0?{}:{"letter-spacing":o},...u===void 0?{}:{"font-weight":u}}}},{values:e("fontSize"),modifiers:e("lineHeight"),type:["absolute-size","relative-size","length","percentage"]})},fontWeight:P("fontWeight",[["font",["fontWeight"]]],{type:["lookup","number","any"]}),textTransform:({addUtilities:r})=>{r({".uppercase":{"text-transform":"uppercase"},".lowercase":{"text-transform":"lowercase"},".capitalize":{"text-transform":"capitalize"},".normal-case":{"text-transform":"none"}})},fontStyle:({addUtilities:r})=>{r({".italic":{"font-style":"italic"},".not-italic":{"font-style":"normal"}})},fontVariantNumeric:({addDefaults:r,addUtilities:e})=>{let t="var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)";r("font-variant-numeric",{"--tw-ordinal":" ","--tw-slashed-zero":" ","--tw-numeric-figure":" ","--tw-numeric-spacing":" ","--tw-numeric-fraction":" "}),e({".normal-nums":{"font-variant-numeric":"normal"},".ordinal":{"@defaults font-variant-numeric":{},"--tw-ordinal":"ordinal","font-variant-numeric":t},".slashed-zero":{"@defaults font-variant-numeric":{},"--tw-slashed-zero":"slashed-zero","font-variant-numeric":t},".lining-nums":{"@defaults font-variant-numeric":{},"--tw-numeric-figure":"lining-nums","font-variant-numeric":t},".oldstyle-nums":{"@defaults font-variant-numeric":{},"--tw-numeric-figure":"oldstyle-nums","font-variant-numeric":t},".proportional-nums":{"@defaults font-variant-numeric":{},"--tw-numeric-spacing":"proportional-nums","font-variant-numeric":t},".tabular-nums":{"@defaults font-variant-numeric":{},"--tw-numeric-spacing":"tabular-nums","font-variant-numeric":t},".diagonal-fractions":{"@defaults font-variant-numeric":{},"--tw-numeric-fraction":"diagonal-fractions","font-variant-numeric":t},".stacked-fractions":{"@defaults font-variant-numeric":{},"--tw-numeric-fraction":"stacked-fractions","font-variant-numeric":t}})},lineHeight:P("lineHeight",[["leading",["lineHeight"]]]),letterSpacing:P("letterSpacing",[["tracking",["letterSpacing"]]],{supportsNegativeValues:!0}),textColor:({matchUtilities:r,theme:e,corePlugins:t})=>{r({text:i=>t("textOpacity")?se({color:i,property:"color",variable:"--tw-text-opacity"}):{color:N(i)}},{values:re(e("textColor")),type:["color","any"]})},textOpacity:P("textOpacity",[["text-opacity",["--tw-text-opacity"]]]),textDecoration:({addUtilities:r})=>{r({".underline":{"text-decoration-line":"underline"},".overline":{"text-decoration-line":"overline"},".line-through":{"text-decoration-line":"line-through"},".no-underline":{"text-decoration-line":"none"}})},textDecorationColor:({matchUtilities:r,theme:e})=>{r({decoration:t=>({"text-decoration-color":N(t)})},{values:re(e("textDecorationColor")),type:["color","any"]})},textDecorationStyle:({addUtilities:r})=>{r({".decoration-solid":{"text-decoration-style":"solid"},".decoration-double":{"text-decoration-style":"double"},".decoration-dotted":{"text-decoration-style":"dotted"},".decoration-dashed":{"text-decoration-style":"dashed"},".decoration-wavy":{"text-decoration-style":"wavy"}})},textDecorationThickness:P("textDecorationThickness",[["decoration",["text-decoration-thickness"]]],{type:["length","percentage"]}),textUnderlineOffset:P("textUnderlineOffset",[["underline-offset",["text-underline-offset"]]],{type:["length","percentage","any"]}),fontSmoothing:({addUtilities:r})=>{r({".antialiased":{"-webkit-font-smoothing":"antialiased","-moz-osx-font-smoothing":"grayscale"},".subpixel-antialiased":{"-webkit-font-smoothing":"auto","-moz-osx-font-smoothing":"auto"}})},placeholderColor:({matchUtilities:r,theme:e,corePlugins:t})=>{r({placeholder:i=>t("placeholderOpacity")?{"&::placeholder":se({color:i,property:"color",variable:"--tw-placeholder-opacity"})}:{"&::placeholder":{color:N(i)}}},{values:re(e("placeholderColor")),type:["color","any"]})},placeholderOpacity:({matchUtilities:r,theme:e})=>{r({"placeholder-opacity":t=>({["&::placeholder"]:{"--tw-placeholder-opacity":t}})},{values:e("placeholderOpacity")})},caretColor:({matchUtilities:r,theme:e})=>{r({caret:t=>({"caret-color":N(t)})},{values:re(e("caretColor")),type:["color","any"]})},accentColor:({matchUtilities:r,theme:e})=>{r({accent:t=>({"accent-color":N(t)})},{values:re(e("accentColor")),type:["color","any"]})},opacity:P("opacity",[["opacity",["opacity"]]]),backgroundBlendMode:({addUtilities:r})=>{r({".bg-blend-normal":{"background-blend-mode":"normal"},".bg-blend-multiply":{"background-blend-mode":"multiply"},".bg-blend-screen":{"background-blend-mode":"screen"},".bg-blend-overlay":{"background-blend-mode":"overlay"},".bg-blend-darken":{"background-blend-mode":"darken"},".bg-blend-lighten":{"background-blend-mode":"lighten"},".bg-blend-color-dodge":{"background-blend-mode":"color-dodge"},".bg-blend-color-burn":{"background-blend-mode":"color-burn"},".bg-blend-hard-light":{"background-blend-mode":"hard-light"},".bg-blend-soft-light":{"background-blend-mode":"soft-light"},".bg-blend-difference":{"background-blend-mode":"difference"},".bg-blend-exclusion":{"background-blend-mode":"exclusion"},".bg-blend-hue":{"background-blend-mode":"hue"},".bg-blend-saturation":{"background-blend-mode":"saturation"},".bg-blend-color":{"background-blend-mode":"color"},".bg-blend-luminosity":{"background-blend-mode":"luminosity"}})},mixBlendMode:({addUtilities:r})=>{r({".mix-blend-normal":{"mix-blend-mode":"normal"},".mix-blend-multiply":{"mix-blend-mode":"multiply"},".mix-blend-screen":{"mix-blend-mode":"screen"},".mix-blend-overlay":{"mix-blend-mode":"overlay"},".mix-blend-darken":{"mix-blend-mode":"darken"},".mix-blend-lighten":{"mix-blend-mode":"lighten"},".mix-blend-color-dodge":{"mix-blend-mode":"color-dodge"},".mix-blend-color-burn":{"mix-blend-mode":"color-burn"},".mix-blend-hard-light":{"mix-blend-mode":"hard-light"},".mix-blend-soft-light":{"mix-blend-mode":"soft-light"},".mix-blend-difference":{"mix-blend-mode":"difference"},".mix-blend-exclusion":{"mix-blend-mode":"exclusion"},".mix-blend-hue":{"mix-blend-mode":"hue"},".mix-blend-saturation":{"mix-blend-mode":"saturation"},".mix-blend-color":{"mix-blend-mode":"color"},".mix-blend-luminosity":{"mix-blend-mode":"luminosity"},".mix-blend-plus-darker":{"mix-blend-mode":"plus-darker"},".mix-blend-plus-lighter":{"mix-blend-mode":"plus-lighter"}})},boxShadow:(()=>{let r=Ge("boxShadow"),e=["var(--tw-ring-offset-shadow, 0 0 #0000)","var(--tw-ring-shadow, 0 0 #0000)","var(--tw-shadow)"].join(", ");return function({matchUtilities:t,addDefaults:i,theme:n}){i("box-shadow",{"--tw-ring-offset-shadow":"0 0 #0000","--tw-ring-shadow":"0 0 #0000","--tw-shadow":"0 0 #0000","--tw-shadow-colored":"0 0 #0000"}),t({shadow:a=>{a=r(a);let s=xi(a);for(let o of s)!o.valid||(o.color="var(--tw-shadow-color)");return{"@defaults box-shadow":{},"--tw-shadow":a==="none"?"0 0 #0000":a,"--tw-shadow-colored":a==="none"?"0 0 #0000":Lu(s),"box-shadow":e}}},{values:n("boxShadow"),type:["shadow"]})}})(),boxShadowColor:({matchUtilities:r,theme:e})=>{r({shadow:t=>({"--tw-shadow-color":N(t),"--tw-shadow":"var(--tw-shadow-colored)"})},{values:re(e("boxShadowColor")),type:["color","any"]})},outlineStyle:({addUtilities:r})=>{r({".outline-none":{outline:"2px solid transparent","outline-offset":"2px"},".outline":{"outline-style":"solid"},".outline-dashed":{"outline-style":"dashed"},".outline-dotted":{"outline-style":"dotted"},".outline-double":{"outline-style":"double"}})},outlineWidth:P("outlineWidth",[["outline",["outline-width"]]],{type:["length","number","percentage"]}),outlineOffset:P("outlineOffset",[["outline-offset",["outline-offset"]]],{type:["length","number","percentage","any"],supportsNegativeValues:!0}),outlineColor:({matchUtilities:r,theme:e})=>{r({outline:t=>({"outline-color":N(t)})},{values:re(e("outlineColor")),type:["color","any"]})},ringWidth:({matchUtilities:r,addDefaults:e,addUtilities:t,theme:i,config:n})=>{let a=(()=>{if(K(n(),"respectDefaultRingColorOpacity"))return i("ringColor.DEFAULT");let s=i("ringOpacity.DEFAULT","0.5");return i("ringColor")?.DEFAULT?Ie(i("ringColor")?.DEFAULT,s,`rgb(147 197 253 / ${s})`):`rgb(147 197 253 / ${s})`})();e("ring-width",{"--tw-ring-inset":" ","--tw-ring-offset-width":i("ringOffsetWidth.DEFAULT","0px"),"--tw-ring-offset-color":i("ringOffsetColor.DEFAULT","#fff"),"--tw-ring-color":a,"--tw-ring-offset-shadow":"0 0 #0000","--tw-ring-shadow":"0 0 #0000","--tw-shadow":"0 0 #0000","--tw-shadow-colored":"0 0 #0000"}),r({ring:s=>({"@defaults ring-width":{},"--tw-ring-offset-shadow":"var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)","--tw-ring-shadow":`var(--tw-ring-inset) 0 0 0 calc(${s} + var(--tw-ring-offset-width)) var(--tw-ring-color)`,"box-shadow":["var(--tw-ring-offset-shadow)","var(--tw-ring-shadow)","var(--tw-shadow, 0 0 #0000)"].join(", ")})},{values:i("ringWidth"),type:"length"}),t({".ring-inset":{"@defaults ring-width":{},"--tw-ring-inset":"inset"}})},ringColor:({matchUtilities:r,theme:e,corePlugins:t})=>{r({ring:i=>t("ringOpacity")?se({color:i,property:"--tw-ring-color",variable:"--tw-ring-opacity"}):{"--tw-ring-color":N(i)}},{values:Object.fromEntries(Object.entries(re(e("ringColor"))).filter(([i])=>i!=="DEFAULT")),type:["color","any"]})},ringOpacity:r=>{let{config:e}=r;return P("ringOpacity",[["ring-opacity",["--tw-ring-opacity"]]],{filterDefault:!K(e(),"respectDefaultRingColorOpacity")})(r)},ringOffsetWidth:P("ringOffsetWidth",[["ring-offset",["--tw-ring-offset-width"]]],{type:"length"}),ringOffsetColor:({matchUtilities:r,theme:e})=>{r({"ring-offset":t=>({"--tw-ring-offset-color":N(t)})},{values:re(e("ringOffsetColor")),type:["color","any"]})},blur:({matchUtilities:r,theme:e})=>{r({blur:t=>({"--tw-blur":`blur(${t})`,"@defaults filter":{},filter:Be})},{values:e("blur")})},brightness:({matchUtilities:r,theme:e})=>{r({brightness:t=>({"--tw-brightness":`brightness(${t})`,"@defaults filter":{},filter:Be})},{values:e("brightness")})},contrast:({matchUtilities:r,theme:e})=>{r({contrast:t=>({"--tw-contrast":`contrast(${t})`,"@defaults filter":{},filter:Be})},{values:e("contrast")})},dropShadow:({matchUtilities:r,theme:e})=>{r({"drop-shadow":t=>({"--tw-drop-shadow":Array.isArray(t)?t.map(i=>`drop-shadow(${i})`).join(" "):`drop-shadow(${t})`,"@defaults filter":{},filter:Be})},{values:e("dropShadow")})},grayscale:({matchUtilities:r,theme:e})=>{r({grayscale:t=>({"--tw-grayscale":`grayscale(${t})`,"@defaults filter":{},filter:Be})},{values:e("grayscale")})},hueRotate:({matchUtilities:r,theme:e})=>{r({"hue-rotate":t=>({"--tw-hue-rotate":`hue-rotate(${t})`,"@defaults filter":{},filter:Be})},{values:e("hueRotate"),supportsNegativeValues:!0})},invert:({matchUtilities:r,theme:e})=>{r({invert:t=>({"--tw-invert":`invert(${t})`,"@defaults filter":{},filter:Be})},{values:e("invert")})},saturate:({matchUtilities:r,theme:e})=>{r({saturate:t=>({"--tw-saturate":`saturate(${t})`,"@defaults filter":{},filter:Be})},{values:e("saturate")})},sepia:({matchUtilities:r,theme:e})=>{r({sepia:t=>({"--tw-sepia":`sepia(${t})`,"@defaults filter":{},filter:Be})},{values:e("sepia")})},filter:({addDefaults:r,addUtilities:e})=>{r("filter",{"--tw-blur":" ","--tw-brightness":" ","--tw-contrast":" ","--tw-grayscale":" ","--tw-hue-rotate":" ","--tw-invert":" ","--tw-saturate":" ","--tw-sepia":" ","--tw-drop-shadow":" "}),e({".filter":{"@defaults filter":{},filter:Be},".filter-none":{filter:"none"}})},backdropBlur:({matchUtilities:r,theme:e})=>{r({"backdrop-blur":t=>({"--tw-backdrop-blur":`blur(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropBlur")})},backdropBrightness:({matchUtilities:r,theme:e})=>{r({"backdrop-brightness":t=>({"--tw-backdrop-brightness":`brightness(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropBrightness")})},backdropContrast:({matchUtilities:r,theme:e})=>{r({"backdrop-contrast":t=>({"--tw-backdrop-contrast":`contrast(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropContrast")})},backdropGrayscale:({matchUtilities:r,theme:e})=>{r({"backdrop-grayscale":t=>({"--tw-backdrop-grayscale":`grayscale(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropGrayscale")})},backdropHueRotate:({matchUtilities:r,theme:e})=>{r({"backdrop-hue-rotate":t=>({"--tw-backdrop-hue-rotate":`hue-rotate(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropHueRotate"),supportsNegativeValues:!0})},backdropInvert:({matchUtilities:r,theme:e})=>{r({"backdrop-invert":t=>({"--tw-backdrop-invert":`invert(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropInvert")})},backdropOpacity:({matchUtilities:r,theme:e})=>{r({"backdrop-opacity":t=>({"--tw-backdrop-opacity":`opacity(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropOpacity")})},backdropSaturate:({matchUtilities:r,theme:e})=>{r({"backdrop-saturate":t=>({"--tw-backdrop-saturate":`saturate(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropSaturate")})},backdropSepia:({matchUtilities:r,theme:e})=>{r({"backdrop-sepia":t=>({"--tw-backdrop-sepia":`sepia(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropSepia")})},backdropFilter:({addDefaults:r,addUtilities:e})=>{r("backdrop-filter",{"--tw-backdrop-blur":" ","--tw-backdrop-brightness":" ","--tw-backdrop-contrast":" ","--tw-backdrop-grayscale":" ","--tw-backdrop-hue-rotate":" ","--tw-backdrop-invert":" ","--tw-backdrop-opacity":" ","--tw-backdrop-saturate":" ","--tw-backdrop-sepia":" "}),e({".backdrop-filter":{"@defaults backdrop-filter":{},"backdrop-filter":Fe},".backdrop-filter-none":{"backdrop-filter":"none"}})},transitionProperty:({matchUtilities:r,theme:e})=>{let t=e("transitionTimingFunction.DEFAULT"),i=e("transitionDuration.DEFAULT");r({transition:n=>({"transition-property":n,...n==="none"?{}:{"transition-timing-function":t,"transition-duration":i}})},{values:e("transitionProperty")})},transitionDelay:P("transitionDelay",[["delay",["transitionDelay"]]]),transitionDuration:P("transitionDuration",[["duration",["transitionDuration"]]],{filterDefault:!0}),transitionTimingFunction:P("transitionTimingFunction",[["ease",["transitionTimingFunction"]]],{filterDefault:!0}),willChange:P("willChange",[["will-change",["will-change"]]]),contain:({addDefaults:r,addUtilities:e})=>{let t="var(--tw-contain-size) var(--tw-contain-layout) var(--tw-contain-paint) var(--tw-contain-style)";r("contain",{"--tw-contain-size":" ","--tw-contain-layout":" ","--tw-contain-paint":" ","--tw-contain-style":" "}),e({".contain-none":{contain:"none"},".contain-content":{contain:"content"},".contain-strict":{contain:"strict"},".contain-size":{"@defaults contain":{},"--tw-contain-size":"size",contain:t},".contain-inline-size":{"@defaults contain":{},"--tw-contain-size":"inline-size",contain:t},".contain-layout":{"@defaults contain":{},"--tw-contain-layout":"layout",contain:t},".contain-paint":{"@defaults contain":{},"--tw-contain-paint":"paint",contain:t},".contain-style":{"@defaults contain":{},"--tw-contain-style":"style",contain:t}})},content:P("content",[["content",["--tw-content",["content","var(--tw-content)"]]]]),forcedColorAdjust:({addUtilities:r})=>{r({".forced-color-adjust-auto":{"forced-color-adjust":"auto"},".forced-color-adjust-none":{"forced-color-adjust":"none"}})}}});function h2(r){if(r===void 0)return!1;if(r==="true"||r==="1")return!0;if(r==="false"||r==="0")return!1;if(r==="*")return!0;let e=r.split(",").map(t=>t.split(":")[0]);return e.includes("-tailwindcss")?!1:!!e.includes("tailwindcss")}var Pe,Ad,_d,vn,Za,He,ti,lt=C(()=>{l();Pe=typeof h!="undefined"?{NODE_ENV:"production",DEBUG:h2(h.env.DEBUG)}:{NODE_ENV:"production",DEBUG:!1},Ad=new Map,_d=new Map,vn=new Map,Za=new Map,He=new String("*"),ti=Symbol("__NONE__")});function zt(r){let e=[],t=!1;for(let i=0;i0)}var Od,Ed,m2,eo=C(()=>{l();Od=new Map([["{","}"],["[","]"],["(",")"]]),Ed=new Map(Array.from(Od.entries()).map(([r,e])=>[e,r])),m2=new Set(['"',"'","`"])});function jt(r){let[e]=Td(r);return e.forEach(([t,i])=>t.removeChild(i)),r.nodes.push(...e.map(([,t])=>t)),r}function Td(r){let e=[],t=null;for(let i of r.nodes)if(i.type==="combinator")e=e.filter(([,n])=>ro(n).includes("jumpable")),t=null;else if(i.type==="pseudo"){g2(i)?(t=i,e.push([r,i,null])):t&&y2(i,t)?e.push([r,i,t]):t=null;for(let n of i.nodes??[]){let[a,s]=Td(n);t=s||t,e.push(...a)}}return[e,t]}function Pd(r){return r.value.startsWith("::")||to[r.value]!==void 0}function g2(r){return Pd(r)&&ro(r).includes("terminal")}function y2(r,e){return r.type!=="pseudo"||Pd(r)?!1:ro(e).includes("actionable")}function ro(r){return to[r.value]??to.__default__}var to,xn=C(()=>{l();to={"::after":["terminal","jumpable"],"::backdrop":["terminal","jumpable"],"::before":["terminal","jumpable"],"::cue":["terminal"],"::cue-region":["terminal"],"::first-letter":["terminal","jumpable"],"::first-line":["terminal","jumpable"],"::grammar-error":["terminal"],"::marker":["terminal","jumpable"],"::part":["terminal","actionable"],"::placeholder":["terminal","jumpable"],"::selection":["terminal","jumpable"],"::slotted":["terminal"],"::spelling-error":["terminal"],"::target-text":["terminal"],"::file-selector-button":["terminal","actionable"],"::deep":["actionable"],"::v-deep":["actionable"],"::ng-deep":["actionable"],":after":["terminal","jumpable"],":before":["terminal","jumpable"],":first-letter":["terminal","jumpable"],":first-line":["terminal","jumpable"],":where":[],":is":[],":has":[],__default__:["terminal","actionable"]}});function Vt(r,{context:e,candidate:t}){let i=e?.tailwindConfig.prefix??"",n=r.map(s=>{let o=(0,Le.default)().astSync(s.format);return{...s,ast:s.respectPrefix?Nt(i,o):o}}),a=Le.default.root({nodes:[Le.default.selector({nodes:[Le.default.className({value:ce(t)})]})]});for(let{ast:s}of n)[a,s]=b2(a,s),s.walkNesting(o=>o.replaceWith(...a.nodes[0].nodes)),a=s;return a}function Id(r){let e=[];for(;r.prev()&&r.prev().type!=="combinator";)r=r.prev();for(;r&&r.type!=="combinator";)e.push(r),r=r.next();return e}function w2(r){return r.sort((e,t)=>e.type==="tag"&&t.type==="class"?-1:e.type==="class"&&t.type==="tag"?1:e.type==="class"&&t.type==="pseudo"&&t.value.startsWith("::")?-1:e.type==="pseudo"&&e.value.startsWith("::")&&t.type==="class"?1:r.index(e)-r.index(t)),r}function no(r,e){let t=!1;r.walk(i=>{if(i.type==="class"&&i.value===e)return t=!0,!1}),t||r.remove()}function kn(r,e,{context:t,candidate:i,base:n}){let a=t?.tailwindConfig?.separator??":";n=n??ae(i,a).pop();let s=(0,Le.default)().astSync(r);if(s.walkClasses(f=>{f.raws&&f.value.includes(n)&&(f.raws.value=ce((0,Dd.default)(f.raws.value)))}),s.each(f=>no(f,n)),s.length===0)return null;let o=Array.isArray(e)?Vt(e,{context:t,candidate:i}):e;if(o===null)return s.toString();let u=Le.default.comment({value:"/*__simple__*/"}),c=Le.default.comment({value:"/*__simple__*/"});return s.walkClasses(f=>{if(f.value!==n)return;let d=f.parent,p=o.nodes[0].nodes;if(d.nodes.length===1){f.replaceWith(...p);return}let m=Id(f);d.insertBefore(m[0],u),d.insertAfter(m[m.length-1],c);for(let x of p)d.insertBefore(m[0],x.clone());f.remove(),m=Id(u);let b=d.index(u);d.nodes.splice(b,m.length,...w2(Le.default.selector({nodes:m})).nodes),u.remove(),c.remove()}),s.walkPseudos(f=>{f.value===io&&f.replaceWith(f.nodes)}),s.each(f=>jt(f)),s.toString()}function b2(r,e){let t=[];return r.walkPseudos(i=>{i.value===io&&t.push({pseudo:i,value:i.nodes[0].toString()})}),e.walkPseudos(i=>{if(i.value!==io)return;let n=i.nodes[0].toString(),a=t.find(c=>c.value===n);if(!a)return;let s=[],o=i.next();for(;o&&o.type!=="combinator";)s.push(o),o=o.next();let u=o;a.pseudo.parent.insertAfter(a.pseudo,Le.default.selector({nodes:s.map(c=>c.clone())})),i.remove(),s.forEach(c=>c.remove()),u&&u.type==="combinator"&&u.remove()}),[r,e]}var Le,Dd,io,so=C(()=>{l();Le=X(Me()),Dd=X(Ki());$t();dn();xn();_t();io=":merge"});function Sn(r,e){let t=(0,ao.default)().astSync(r);return t.each(i=>{i.nodes[0].type==="pseudo"&&i.nodes[0].value===":is"&&i.nodes.every(a=>a.type!=="combinator")||(i.nodes=[ao.default.pseudo({value:":is",nodes:[i.clone()]})]),jt(i)}),`${e} ${t.toString()}`}var ao,oo=C(()=>{l();ao=X(Me());xn()});function lo(r){return v2.transformSync(r)}function*x2(r){let e=1/0;for(;e>=0;){let t,i=!1;if(e===1/0&&r.endsWith("]")){let s=r.indexOf("[");r[s-1]==="-"?t=s-1:r[s-1]==="/"?(t=s-1,i=!0):t=-1}else e===1/0&&r.includes("/")?(t=r.lastIndexOf("/"),i=!0):t=r.lastIndexOf("-",e);if(t<0)break;let n=r.slice(0,t),a=r.slice(i?t:t+1);e=t-1,!(n===""||a==="/")&&(yield[n,a])}}function k2(r,e){if(r.length===0||e.tailwindConfig.prefix==="")return r;for(let t of r){let[i]=t;if(i.options.respectPrefix){let n=j.root({nodes:[t[1].clone()]}),a=t[1].raws.tailwind.classCandidate;n.walkRules(s=>{let o=a.startsWith("-");s.selector=Nt(e.tailwindConfig.prefix,s.selector,o)}),t[1]=n.nodes[0]}}return r}function S2(r,e){if(r.length===0)return r;let t=[];function i(n){return n.parent&&n.parent.type==="atrule"&&n.parent.name==="keyframes"}for(let[n,a]of r){let s=j.root({nodes:[a.clone()]});s.walkRules(o=>{if(i(o))return;let u=(0,Cn.default)().astSync(o.selector);u.each(c=>no(c,e)),Ju(u,c=>c===e?`!${c}`:c),o.selector=u.toString(),o.walkDecls(c=>c.important=!0)}),t.push([{...n,important:!0},s.nodes[0]])}return t}function C2(r,e,t){if(e.length===0)return e;let i={modifier:null,value:ti};{let[n,...a]=ae(r,"/");if(a.length>1&&(n=n+"/"+a.slice(0,-1).join("/"),a=a.slice(-1)),a.length&&!t.variantMap.has(r)&&(r=n,i.modifier=a[0],!K(t.tailwindConfig,"generalizedModifiers")))return[]}if(r.endsWith("]")&&!r.startsWith("[")){let n=/(.)(-?)\[(.*)\]/g.exec(r);if(n){let[,a,s,o]=n;if(a==="@"&&s==="-")return[];if(a!=="@"&&s==="")return[];r=r.replace(`${s}[${o}]`,""),i.value=o}}if(co(r)&&!t.variantMap.has(r)){let n=t.offsets.recordVariant(r),a=L(r.slice(1,-1)),s=ae(a,",");if(s.length>1)return[];if(!s.every(En))return[];let o=s.map((u,c)=>[t.offsets.applyParallelOffset(n,c),ri(u.trim())]);t.variantMap.set(r,o)}if(t.variantMap.has(r)){let n=co(r),a=t.variantOptions.get(r)?.[Zr]??{},s=t.variantMap.get(r).slice(),o=[],u=(()=>!(n||a.respectPrefix===!1))();for(let[c,f]of e){if(c.layer==="user")continue;let d=j.root({nodes:[f.clone()]});for(let[p,m,b]of s){let w=function(){x.raws.neededBackup||(x.raws.neededBackup=!0,x.walkRules(E=>E.raws.originalSelector=E.selector))},k=function(E){return w(),x.each(I=>{I.type==="rule"&&(I.selectors=I.selectors.map(q=>E({get className(){return lo(q)},selector:q})))}),x},x=(b??d).clone(),y=[],S=m({get container(){return w(),x},separator:t.tailwindConfig.separator,modifySelectors:k,wrap(E){let I=x.nodes;x.removeAll(),E.append(I),x.append(E)},format(E){y.push({format:E,respectPrefix:u})},args:i});if(Array.isArray(S)){for(let[E,I]of S.entries())s.push([t.offsets.applyParallelOffset(p,E),I,x.clone()]);continue}if(typeof S=="string"&&y.push({format:S,respectPrefix:u}),S===null)continue;x.raws.neededBackup&&(delete x.raws.neededBackup,x.walkRules(E=>{let I=E.raws.originalSelector;if(!I||(delete E.raws.originalSelector,I===E.selector))return;let q=E.selector,R=(0,Cn.default)(J=>{J.walkClasses(ue=>{ue.value=`${r}${t.tailwindConfig.separator}${ue.value}`})}).processSync(I);y.push({format:q.replace(R,"&"),respectPrefix:u}),E.selector=I})),x.nodes[0].raws.tailwind={...x.nodes[0].raws.tailwind,parentLayer:c.layer};let _=[{...c,sort:t.offsets.applyVariantOffset(c.sort,p,Object.assign(i,t.variantOptions.get(r))),collectedFormats:(c.collectedFormats??[]).concat(y)},x.nodes[0]];o.push(_)}}return o}return[]}function uo(r,e,t={}){return!ie(r)&&!Array.isArray(r)?[[r],t]:Array.isArray(r)?uo(r[0],e,r[1]):(e.has(r)||e.set(r,Lt(r)),[e.get(r),t])}function _2(r){return A2.test(r)}function O2(r){if(!r.includes("://"))return!1;try{let e=new URL(r);return e.scheme!==""&&e.host!==""}catch(e){return!1}}function qd(r){let e=!0;return r.walkDecls(t=>{if(!Rd(t.prop,t.value))return e=!1,!1}),e}function Rd(r,e){if(O2(`${r}:${e}`))return!1;try{return j.parse(`a{${r}:${e}}`).toResult(),!0}catch(t){return!1}}function E2(r,e){let[,t,i]=r.match(/^\[([a-zA-Z0-9-_]+):(\S+)\]$/)??[];if(i===void 0||!_2(t)||!zt(i))return null;let n=L(i,{property:t});return Rd(t,n)?[[{sort:e.offsets.arbitraryProperty(r),layer:"utilities",options:{respectImportant:!0}},()=>({[Ja(r)]:{[t]:n}})]]:null}function*T2(r,e){e.candidateRuleMap.has(r)&&(yield[e.candidateRuleMap.get(r),"DEFAULT"]),yield*function*(o){o!==null&&(yield[o,"DEFAULT"])}(E2(r,e));let t=r,i=!1,n=e.tailwindConfig.prefix,a=n.length,s=t.startsWith(n)||t.startsWith(`-${n}`);t[a]==="-"&&s&&(i=!0,t=n+t.slice(a+1)),i&&e.candidateRuleMap.has(t)&&(yield[e.candidateRuleMap.get(t),"-DEFAULT"]);for(let[o,u]of x2(t))e.candidateRuleMap.has(o)&&(yield[e.candidateRuleMap.get(o),i?`-${u}`:u])}function P2(r,e){return r===He?[He]:ae(r,e)}function*D2(r,e){for(let t of r)t[1].raws.tailwind={...t[1].raws.tailwind,classCandidate:e,preserveSource:t[0].options?.preserveSource??!1},yield t}function*fo(r,e){let t=e.tailwindConfig.separator,[i,...n]=P2(r,t).reverse(),a=!1;i.startsWith("!")&&(a=!0,i=i.slice(1));for(let s of T2(i,e)){let o=[],u=new Map,[c,f]=s,d=c.length===1;for(let[p,m]of c){let b=[];if(typeof m=="function")for(let x of[].concat(m(f,{isOnlyPlugin:d}))){let[y,w]=uo(x,e.postCssNodeCache);for(let k of y)b.push([{...p,options:{...p.options,...w}},k])}else if(f==="DEFAULT"||f==="-DEFAULT"){let x=m,[y,w]=uo(x,e.postCssNodeCache);for(let k of y)b.push([{...p,options:{...p.options,...w}},k])}if(b.length>0){let x=Array.from(ys(p.options?.types??[],f,p.options??{},e.tailwindConfig)).map(([y,w])=>w);x.length>0&&u.set(b,x),o.push(b)}}if(co(f)){if(o.length>1){let b=function(y){return y.length===1?y[0]:y.find(w=>{let k=u.get(w);return w.some(([{options:S},_])=>qd(_)?S.types.some(({type:E,preferOnConflict:I})=>k.includes(E)&&I):!1)})},[p,m]=o.reduce((y,w)=>(w.some(([{options:S}])=>S.types.some(({type:_})=>_==="any"))?y[0].push(w):y[1].push(w),y),[[],[]]),x=b(m)??b(p);if(x)o=[x];else{let y=o.map(k=>new Set([...u.get(k)??[]]));for(let k of y)for(let S of k){let _=!1;for(let E of y)k!==E&&E.has(S)&&(E.delete(S),_=!0);_&&k.delete(S)}let w=[];for(let[k,S]of y.entries())for(let _ of S){let E=o[k].map(([,I])=>I).flat().map(I=>I.toString().split(` -`).slice(1,-1).map(q=>q.trim()).map(q=>` ${q}`).join(` -`)).join(` +` + + e + + ` +`), + this.name + ": " + this.message + e + ); + } + }; + mf.exports = Tt; + Tt.default = Tt; + }); + var Oi = v((h3, _s) => { + l(); + ("use strict"); + _s.exports.isClean = Symbol("isClean"); + _s.exports.my = Symbol("my"); + }); + var Os = v((m3, yf) => { + l(); + ("use strict"); + var gf = { + colon: ": ", + indent: " ", + beforeDecl: ` +`, + beforeRule: ` +`, + beforeOpen: " ", + beforeClose: ` +`, + beforeComment: ` +`, + after: ` +`, + emptyBody: "", + commentLeft: " ", + commentRight: " ", + semicolon: !1, + }; + function v0(r) { + return r[0].toUpperCase() + r.slice(1); + } + var Ei = class { + constructor(e) { + this.builder = e; + } + stringify(e, t) { + if (!this[e.type]) + throw new Error( + "Unknown AST node type " + e.type + ". Maybe you need to change PostCSS stringifier." + ); + this[e.type](e, t); + } + document(e) { + this.body(e); + } + root(e) { + (this.body(e), e.raws.after && this.builder(e.raws.after)); + } + comment(e) { + let t = this.raw(e, "left", "commentLeft"), + i = this.raw(e, "right", "commentRight"); + this.builder("/*" + t + e.text + i + "*/", e); + } + decl(e, t) { + let i = this.raw(e, "between", "colon"), + n = e.prop + i + this.rawValue(e, "value"); + (e.important && (n += e.raws.important || " !important"), t && (n += ";"), this.builder(n, e)); + } + rule(e) { + (this.block(e, this.rawValue(e, "selector")), + e.raws.ownSemicolon && this.builder(e.raws.ownSemicolon, e, "end")); + } + atrule(e, t) { + let i = "@" + e.name, + n = e.params ? this.rawValue(e, "params") : ""; + if ((typeof e.raws.afterName != "undefined" ? (i += e.raws.afterName) : n && (i += " "), e.nodes)) + this.block(e, i + n); + else { + let a = (e.raws.between || "") + (t ? ";" : ""); + this.builder(i + n + a, e); + } + } + body(e) { + let t = e.nodes.length - 1; + for (; t > 0 && e.nodes[t].type === "comment"; ) t -= 1; + let i = this.raw(e, "semicolon"); + for (let n = 0; n < e.nodes.length; n++) { + let a = e.nodes[n], + s = this.raw(a, "before"); + (s && this.builder(s), this.stringify(a, t !== n || i)); + } + } + block(e, t) { + let i = this.raw(e, "between", "beforeOpen"); + this.builder(t + i + "{", e, "start"); + let n; + (e.nodes && e.nodes.length + ? (this.body(e), (n = this.raw(e, "after"))) + : (n = this.raw(e, "after", "emptyBody")), + n && this.builder(n), + this.builder("}", e, "end")); + } + raw(e, t, i) { + let n; + if ((i || (i = t), t && ((n = e.raws[t]), typeof n != "undefined"))) return n; + let a = e.parent; + if (i === "before" && (!a || (a.type === "root" && a.first === e) || (a && a.type === "document"))) + return ""; + if (!a) return gf[i]; + let s = e.root(); + if ((s.rawCache || (s.rawCache = {}), typeof s.rawCache[i] != "undefined")) return s.rawCache[i]; + if (i === "before" || i === "after") return this.beforeAfter(e, i); + { + let o = "raw" + v0(i); + this[o] + ? (n = this[o](s, e)) + : s.walk((u) => { + if (((n = u.raws[t]), typeof n != "undefined")) return !1; + }); + } + return (typeof n == "undefined" && (n = gf[i]), (s.rawCache[i] = n), n); + } + rawSemicolon(e) { + let t; + return ( + e.walk((i) => { + if ( + i.nodes && + i.nodes.length && + i.last.type === "decl" && + ((t = i.raws.semicolon), typeof t != "undefined") + ) + return !1; + }), + t + ); + } + rawEmptyBody(e) { + let t; + return ( + e.walk((i) => { + if (i.nodes && i.nodes.length === 0 && ((t = i.raws.after), typeof t != "undefined")) return !1; + }), + t + ); + } + rawIndent(e) { + if (e.raws.indent) return e.raws.indent; + let t; + return ( + e.walk((i) => { + let n = i.parent; + if (n && n !== e && n.parent && n.parent === e && typeof i.raws.before != "undefined") { + let a = i.raws.before.split(` +`); + return ((t = a[a.length - 1]), (t = t.replace(/\S/g, "")), !1); + } + }), + t + ); + } + rawBeforeComment(e, t) { + let i; + return ( + e.walkComments((n) => { + if (typeof n.raws.before != "undefined") + return ( + (i = n.raws.before), + i.includes(` +`) && (i = i.replace(/[^\n]+$/, "")), + !1 + ); + }), + typeof i == "undefined" ? (i = this.raw(t, null, "beforeDecl")) : i && (i = i.replace(/\S/g, "")), + i + ); + } + rawBeforeDecl(e, t) { + let i; + return ( + e.walkDecls((n) => { + if (typeof n.raws.before != "undefined") + return ( + (i = n.raws.before), + i.includes(` +`) && (i = i.replace(/[^\n]+$/, "")), + !1 + ); + }), + typeof i == "undefined" ? (i = this.raw(t, null, "beforeRule")) : i && (i = i.replace(/\S/g, "")), + i + ); + } + rawBeforeRule(e) { + let t; + return ( + e.walk((i) => { + if (i.nodes && (i.parent !== e || e.first !== i) && typeof i.raws.before != "undefined") + return ( + (t = i.raws.before), + t.includes(` +`) && (t = t.replace(/[^\n]+$/, "")), + !1 + ); + }), + t && (t = t.replace(/\S/g, "")), + t + ); + } + rawBeforeClose(e) { + let t; + return ( + e.walk((i) => { + if (i.nodes && i.nodes.length > 0 && typeof i.raws.after != "undefined") + return ( + (t = i.raws.after), + t.includes(` +`) && (t = t.replace(/[^\n]+$/, "")), + !1 + ); + }), + t && (t = t.replace(/\S/g, "")), + t + ); + } + rawBeforeOpen(e) { + let t; + return ( + e.walk((i) => { + if (i.type !== "decl" && ((t = i.raws.between), typeof t != "undefined")) return !1; + }), + t + ); + } + rawColon(e) { + let t; + return ( + e.walkDecls((i) => { + if (typeof i.raws.between != "undefined") + return ((t = i.raws.between.replace(/[^\s:]/g, "")), !1); + }), + t + ); + } + beforeAfter(e, t) { + let i; + e.type === "decl" + ? (i = this.raw(e, null, "beforeDecl")) + : e.type === "comment" + ? (i = this.raw(e, null, "beforeComment")) + : t === "before" + ? (i = this.raw(e, null, "beforeRule")) + : (i = this.raw(e, null, "beforeClose")); + let n = e.parent, + a = 0; + for (; n && n.type !== "root"; ) ((a += 1), (n = n.parent)); + if ( + i.includes(` +`) + ) { + let s = this.raw(e, null, "indent"); + if (s.length) for (let o = 0; o < a; o++) i += s; + } + return i; + } + rawValue(e, t) { + let i = e[t], + n = e.raws[t]; + return n && n.value === i ? n.raw : i; + } + }; + yf.exports = Ei; + Ei.default = Ei; + }); + var yr = v((g3, wf) => { + l(); + ("use strict"); + var x0 = Os(); + function Es(r, e) { + new x0(e).stringify(r); + } + wf.exports = Es; + Es.default = Es; + }); + var wr = v((y3, bf) => { + l(); + ("use strict"); + var { isClean: Ti, my: k0 } = Oi(), + S0 = _i(), + C0 = Os(), + A0 = yr(); + function Ts(r, e) { + let t = new r.constructor(); + for (let i in r) { + if (!Object.prototype.hasOwnProperty.call(r, i) || i === "proxyCache") continue; + let n = r[i], + a = typeof n; + i === "parent" && a === "object" + ? e && (t[i] = e) + : i === "source" + ? (t[i] = n) + : Array.isArray(n) + ? (t[i] = n.map((s) => Ts(s, t))) + : (a === "object" && n !== null && (n = Ts(n)), (t[i] = n)); + } + return t; + } + var Pi = class { + constructor(e = {}) { + ((this.raws = {}), (this[Ti] = !1), (this[k0] = !0)); + for (let t in e) + if (t === "nodes") { + this.nodes = []; + for (let i of e[t]) typeof i.clone == "function" ? this.append(i.clone()) : this.append(i); + } else this[t] = e[t]; + } + error(e, t = {}) { + if (this.source) { + let { start: i, end: n } = this.rangeBy(t); + return this.source.input.error( + e, + { line: i.line, column: i.column }, + { line: n.line, column: n.column }, + t + ); + } + return new S0(e); + } + warn(e, t, i) { + let n = { node: this }; + for (let a in i) n[a] = i[a]; + return e.warn(t, n); + } + remove() { + return (this.parent && this.parent.removeChild(this), (this.parent = void 0), this); + } + toString(e = A0) { + e.stringify && (e = e.stringify); + let t = ""; + return ( + e(this, (i) => { + t += i; + }), + t + ); + } + assign(e = {}) { + for (let t in e) this[t] = e[t]; + return this; + } + clone(e = {}) { + let t = Ts(this); + for (let i in e) t[i] = e[i]; + return t; + } + cloneBefore(e = {}) { + let t = this.clone(e); + return (this.parent.insertBefore(this, t), t); + } + cloneAfter(e = {}) { + let t = this.clone(e); + return (this.parent.insertAfter(this, t), t); + } + replaceWith(...e) { + if (this.parent) { + let t = this, + i = !1; + for (let n of e) + n === this + ? (i = !0) + : i + ? (this.parent.insertAfter(t, n), (t = n)) + : this.parent.insertBefore(t, n); + i || this.remove(); + } + return this; + } + next() { + if (!this.parent) return; + let e = this.parent.index(this); + return this.parent.nodes[e + 1]; + } + prev() { + if (!this.parent) return; + let e = this.parent.index(this); + return this.parent.nodes[e - 1]; + } + before(e) { + return (this.parent.insertBefore(this, e), this); + } + after(e) { + return (this.parent.insertAfter(this, e), this); + } + root() { + let e = this; + for (; e.parent && e.parent.type !== "document"; ) e = e.parent; + return e; + } + raw(e, t) { + return new C0().raw(this, e, t); + } + cleanRaws(e) { + (delete this.raws.before, delete this.raws.after, e || delete this.raws.between); + } + toJSON(e, t) { + let i = {}, + n = t == null; + t = t || new Map(); + let a = 0; + for (let s in this) { + if (!Object.prototype.hasOwnProperty.call(this, s) || s === "parent" || s === "proxyCache") + continue; + let o = this[s]; + if (Array.isArray(o)) + i[s] = o.map((u) => (typeof u == "object" && u.toJSON ? u.toJSON(null, t) : u)); + else if (typeof o == "object" && o.toJSON) i[s] = o.toJSON(null, t); + else if (s === "source") { + let u = t.get(o.input); + (u == null && ((u = a), t.set(o.input, a), a++), + (i[s] = { inputId: u, start: o.start, end: o.end })); + } else i[s] = o; + } + return (n && (i.inputs = [...t.keys()].map((s) => s.toJSON())), i); + } + positionInside(e) { + let t = this.toString(), + i = this.source.start.column, + n = this.source.start.line; + for (let a = 0; a < e; a++) + t[a] === + ` +` + ? ((i = 1), (n += 1)) + : (i += 1); + return { line: n, column: i }; + } + positionBy(e) { + let t = this.source.start; + if (e.index) t = this.positionInside(e.index); + else if (e.word) { + let i = this.toString().indexOf(e.word); + i !== -1 && (t = this.positionInside(i)); + } + return t; + } + rangeBy(e) { + let t = { line: this.source.start.line, column: this.source.start.column }, + i = this.source.end + ? { line: this.source.end.line, column: this.source.end.column + 1 } + : { line: t.line, column: t.column + 1 }; + if (e.word) { + let n = this.toString().indexOf(e.word); + n !== -1 && ((t = this.positionInside(n)), (i = this.positionInside(n + e.word.length))); + } else + (e.start + ? (t = { line: e.start.line, column: e.start.column }) + : e.index && (t = this.positionInside(e.index)), + e.end + ? (i = { line: e.end.line, column: e.end.column }) + : e.endIndex + ? (i = this.positionInside(e.endIndex)) + : e.index && (i = this.positionInside(e.index + 1))); + return ( + (i.line < t.line || (i.line === t.line && i.column <= t.column)) && + (i = { line: t.line, column: t.column + 1 }), + { start: t, end: i } + ); + } + getProxyProcessor() { + return { + set(e, t, i) { + return ( + e[t] === i || + ((e[t] = i), + (t === "prop" || + t === "value" || + t === "name" || + t === "params" || + t === "important" || + t === "text") && + e.markDirty()), + !0 + ); + }, + get(e, t) { + return t === "proxyOf" ? e : t === "root" ? () => e.root().toProxy() : e[t]; + }, + }; + } + toProxy() { + return ( + this.proxyCache || (this.proxyCache = new Proxy(this, this.getProxyProcessor())), + this.proxyCache + ); + } + addToError(e) { + if (((e.postcssNode = this), e.stack && this.source && /\n\s{4}at /.test(e.stack))) { + let t = this.source; + e.stack = e.stack.replace(/\n\s{4}at /, `$&${t.input.from}:${t.start.line}:${t.start.column}$&`); + } + return e; + } + markDirty() { + if (this[Ti]) { + this[Ti] = !1; + let e = this; + for (; (e = e.parent); ) e[Ti] = !1; + } + } + get proxyOf() { + return this; + } + }; + bf.exports = Pi; + Pi.default = Pi; + }); + var br = v((w3, vf) => { + l(); + ("use strict"); + var _0 = wr(), + Di = class extends _0 { + constructor(e) { + e && + typeof e.value != "undefined" && + typeof e.value != "string" && + (e = { ...e, value: String(e.value) }); + super(e); + this.type = "decl"; + } + get variable() { + return this.prop.startsWith("--") || this.prop[0] === "$"; + } + }; + vf.exports = Di; + Di.default = Di; + }); + var Ps = v((b3, xf) => { + l(); + xf.exports = function (r, e) { + return { + generate: () => { + let t = ""; + return ( + r(e, (i) => { + t += i; + }), + [t] + ); + }, + }; + }; + }); + var vr = v((v3, kf) => { + l(); + ("use strict"); + var O0 = wr(), + Ii = class extends O0 { + constructor(e) { + super(e); + this.type = "comment"; + } + }; + kf.exports = Ii; + Ii.default = Ii; + }); + var nt = v((x3, Df) => { + l(); + ("use strict"); + var { isClean: Sf, my: Cf } = Oi(), + Af = br(), + _f = vr(), + E0 = wr(), + Of, + Ds, + Is, + Ef; + function Tf(r) { + return r.map((e) => (e.nodes && (e.nodes = Tf(e.nodes)), delete e.source, e)); + } + function Pf(r) { + if (((r[Sf] = !1), r.proxyOf.nodes)) for (let e of r.proxyOf.nodes) Pf(e); + } + var we = class extends E0 { + push(e) { + return ((e.parent = this), this.proxyOf.nodes.push(e), this); + } + each(e) { + if (!this.proxyOf.nodes) return; + let t = this.getIterator(), + i, + n; + for ( + ; + this.indexes[t] < this.proxyOf.nodes.length && + ((i = this.indexes[t]), (n = e(this.proxyOf.nodes[i], i)), n !== !1); + ) + this.indexes[t] += 1; + return (delete this.indexes[t], n); + } + walk(e) { + return this.each((t, i) => { + let n; + try { + n = e(t, i); + } catch (a) { + throw t.addToError(a); + } + return (n !== !1 && t.walk && (n = t.walk(e)), n); + }); + } + walkDecls(e, t) { + return t + ? e instanceof RegExp + ? this.walk((i, n) => { + if (i.type === "decl" && e.test(i.prop)) return t(i, n); + }) + : this.walk((i, n) => { + if (i.type === "decl" && i.prop === e) return t(i, n); + }) + : ((t = e), + this.walk((i, n) => { + if (i.type === "decl") return t(i, n); + })); + } + walkRules(e, t) { + return t + ? e instanceof RegExp + ? this.walk((i, n) => { + if (i.type === "rule" && e.test(i.selector)) return t(i, n); + }) + : this.walk((i, n) => { + if (i.type === "rule" && i.selector === e) return t(i, n); + }) + : ((t = e), + this.walk((i, n) => { + if (i.type === "rule") return t(i, n); + })); + } + walkAtRules(e, t) { + return t + ? e instanceof RegExp + ? this.walk((i, n) => { + if (i.type === "atrule" && e.test(i.name)) return t(i, n); + }) + : this.walk((i, n) => { + if (i.type === "atrule" && i.name === e) return t(i, n); + }) + : ((t = e), + this.walk((i, n) => { + if (i.type === "atrule") return t(i, n); + })); + } + walkComments(e) { + return this.walk((t, i) => { + if (t.type === "comment") return e(t, i); + }); + } + append(...e) { + for (let t of e) { + let i = this.normalize(t, this.last); + for (let n of i) this.proxyOf.nodes.push(n); + } + return (this.markDirty(), this); + } + prepend(...e) { + e = e.reverse(); + for (let t of e) { + let i = this.normalize(t, this.first, "prepend").reverse(); + for (let n of i) this.proxyOf.nodes.unshift(n); + for (let n in this.indexes) this.indexes[n] = this.indexes[n] + i.length; + } + return (this.markDirty(), this); + } + cleanRaws(e) { + if ((super.cleanRaws(e), this.nodes)) for (let t of this.nodes) t.cleanRaws(e); + } + insertBefore(e, t) { + let i = this.index(e), + n = i === 0 ? "prepend" : !1, + a = this.normalize(t, this.proxyOf.nodes[i], n).reverse(); + i = this.index(e); + for (let o of a) this.proxyOf.nodes.splice(i, 0, o); + let s; + for (let o in this.indexes) ((s = this.indexes[o]), i <= s && (this.indexes[o] = s + a.length)); + return (this.markDirty(), this); + } + insertAfter(e, t) { + let i = this.index(e), + n = this.normalize(t, this.proxyOf.nodes[i]).reverse(); + i = this.index(e); + for (let s of n) this.proxyOf.nodes.splice(i + 1, 0, s); + let a; + for (let s in this.indexes) ((a = this.indexes[s]), i < a && (this.indexes[s] = a + n.length)); + return (this.markDirty(), this); + } + removeChild(e) { + ((e = this.index(e)), (this.proxyOf.nodes[e].parent = void 0), this.proxyOf.nodes.splice(e, 1)); + let t; + for (let i in this.indexes) ((t = this.indexes[i]), t >= e && (this.indexes[i] = t - 1)); + return (this.markDirty(), this); + } + removeAll() { + for (let e of this.proxyOf.nodes) e.parent = void 0; + return ((this.proxyOf.nodes = []), this.markDirty(), this); + } + replaceValues(e, t, i) { + return ( + i || ((i = t), (t = {})), + this.walkDecls((n) => { + (t.props && !t.props.includes(n.prop)) || + (t.fast && !n.value.includes(t.fast)) || + (n.value = n.value.replace(e, i)); + }), + this.markDirty(), + this + ); + } + every(e) { + return this.nodes.every(e); + } + some(e) { + return this.nodes.some(e); + } + index(e) { + return typeof e == "number" ? e : (e.proxyOf && (e = e.proxyOf), this.proxyOf.nodes.indexOf(e)); + } + get first() { + if (!!this.proxyOf.nodes) return this.proxyOf.nodes[0]; + } + get last() { + if (!!this.proxyOf.nodes) return this.proxyOf.nodes[this.proxyOf.nodes.length - 1]; + } + normalize(e, t) { + if (typeof e == "string") e = Tf(Of(e).nodes); + else if (Array.isArray(e)) { + e = e.slice(0); + for (let n of e) n.parent && n.parent.removeChild(n, "ignore"); + } else if (e.type === "root" && this.type !== "document") { + e = e.nodes.slice(0); + for (let n of e) n.parent && n.parent.removeChild(n, "ignore"); + } else if (e.type) e = [e]; + else if (e.prop) { + if (typeof e.value == "undefined") throw new Error("Value field is missed in node creation"); + (typeof e.value != "string" && (e.value = String(e.value)), (e = [new Af(e)])); + } else if (e.selector) e = [new Ds(e)]; + else if (e.name) e = [new Is(e)]; + else if (e.text) e = [new _f(e)]; + else throw new Error("Unknown node type in node creation"); + return e.map( + (n) => ( + n[Cf] || we.rebuild(n), + (n = n.proxyOf), + n.parent && n.parent.removeChild(n), + n[Sf] && Pf(n), + typeof n.raws.before == "undefined" && + t && + typeof t.raws.before != "undefined" && + (n.raws.before = t.raws.before.replace(/\S/g, "")), + (n.parent = this.proxyOf), + n + ) + ); + } + getProxyProcessor() { + return { + set(e, t, i) { + return ( + e[t] === i || + ((e[t] = i), (t === "name" || t === "params" || t === "selector") && e.markDirty()), + !0 + ); + }, + get(e, t) { + return t === "proxyOf" + ? e + : e[t] + ? t === "each" || (typeof t == "string" && t.startsWith("walk")) + ? (...i) => + e[t]( + ...i.map((n) => (typeof n == "function" ? (a, s) => n(a.toProxy(), s) : n)) + ) + : t === "every" || t === "some" + ? (i) => e[t]((n, ...a) => i(n.toProxy(), ...a)) + : t === "root" + ? () => e.root().toProxy() + : t === "nodes" + ? e.nodes.map((i) => i.toProxy()) + : t === "first" || t === "last" + ? e[t].toProxy() + : e[t] + : e[t]; + }, + }; + } + getIterator() { + (this.lastEach || (this.lastEach = 0), this.indexes || (this.indexes = {}), (this.lastEach += 1)); + let e = this.lastEach; + return ((this.indexes[e] = 0), e); + } + }; + we.registerParse = (r) => { + Of = r; + }; + we.registerRule = (r) => { + Ds = r; + }; + we.registerAtRule = (r) => { + Is = r; + }; + we.registerRoot = (r) => { + Ef = r; + }; + Df.exports = we; + we.default = we; + we.rebuild = (r) => { + (r.type === "atrule" + ? Object.setPrototypeOf(r, Is.prototype) + : r.type === "rule" + ? Object.setPrototypeOf(r, Ds.prototype) + : r.type === "decl" + ? Object.setPrototypeOf(r, Af.prototype) + : r.type === "comment" + ? Object.setPrototypeOf(r, _f.prototype) + : r.type === "root" && Object.setPrototypeOf(r, Ef.prototype), + (r[Cf] = !0), + r.nodes && + r.nodes.forEach((e) => { + we.rebuild(e); + })); + }; + }); + var qi = v((k3, Rf) => { + l(); + ("use strict"); + var T0 = nt(), + If, + qf, + Pt = class extends T0 { + constructor(e) { + super({ type: "document", ...e }); + this.nodes || (this.nodes = []); + } + toResult(e = {}) { + return new If(new qf(), this, e).stringify(); + } + }; + Pt.registerLazyResult = (r) => { + If = r; + }; + Pt.registerProcessor = (r) => { + qf = r; + }; + Rf.exports = Pt; + Pt.default = Pt; + }); + var qs = v((S3, Bf) => { + l(); + ("use strict"); + var Mf = {}; + Bf.exports = function (e) { + Mf[e] || ((Mf[e] = !0), typeof console != "undefined" && console.warn && console.warn(e)); + }; + }); + var Rs = v((C3, Ff) => { + l(); + ("use strict"); + var Ri = class { + constructor(e, t = {}) { + if (((this.type = "warning"), (this.text = e), t.node && t.node.source)) { + let i = t.node.rangeBy(t); + ((this.line = i.start.line), + (this.column = i.start.column), + (this.endLine = i.end.line), + (this.endColumn = i.end.column)); + } + for (let i in t) this[i] = t[i]; + } + toString() { + return this.node + ? this.node.error(this.text, { plugin: this.plugin, index: this.index, word: this.word }).message + : this.plugin + ? this.plugin + ": " + this.text + : this.text; + } + }; + Ff.exports = Ri; + Ri.default = Ri; + }); + var Bi = v((A3, Lf) => { + l(); + ("use strict"); + var P0 = Rs(), + Mi = class { + constructor(e, t, i) { + ((this.processor = e), + (this.messages = []), + (this.root = t), + (this.opts = i), + (this.css = void 0), + (this.map = void 0)); + } + toString() { + return this.css; + } + warn(e, t = {}) { + t.plugin || + (this.lastPlugin && + this.lastPlugin.postcssPlugin && + (t.plugin = this.lastPlugin.postcssPlugin)); + let i = new P0(e, t); + return (this.messages.push(i), i); + } + warnings() { + return this.messages.filter((e) => e.type === "warning"); + } + get content() { + return this.css; + } + }; + Lf.exports = Mi; + Mi.default = Mi; + }); + var Vf = v((_3, jf) => { + l(); + ("use strict"); + var Ms = "'".charCodeAt(0), + Nf = '"'.charCodeAt(0), + Fi = "\\".charCodeAt(0), + $f = "/".charCodeAt(0), + Li = ` +`.charCodeAt(0), + xr = " ".charCodeAt(0), + Ni = "\f".charCodeAt(0), + $i = " ".charCodeAt(0), + zi = "\r".charCodeAt(0), + D0 = "[".charCodeAt(0), + I0 = "]".charCodeAt(0), + q0 = "(".charCodeAt(0), + R0 = ")".charCodeAt(0), + M0 = "{".charCodeAt(0), + B0 = "}".charCodeAt(0), + F0 = ";".charCodeAt(0), + L0 = "*".charCodeAt(0), + N0 = ":".charCodeAt(0), + $0 = "@".charCodeAt(0), + ji = /[\t\n\f\r "#'()/;[\\\]{}]/g, + Vi = /[\t\n\f\r !"#'():;@[\\\]{}]|\/(?=\*)/g, + z0 = /.[\n"'(/\\]/, + zf = /[\da-f]/i; + jf.exports = function (e, t = {}) { + let i = e.css.valueOf(), + n = t.ignoreErrors, + a, + s, + o, + u, + c, + f, + d, + p, + m, + b, + x = i.length, + y = 0, + w = [], + k = []; + function S() { + return y; + } + function _(R) { + throw e.error("Unclosed " + R, y); + } + function E() { + return k.length === 0 && y >= x; + } + function I(R) { + if (k.length) return k.pop(); + if (y >= x) return; + let J = R ? R.ignoreUnclosed : !1; + switch (((a = i.charCodeAt(y)), a)) { + case Li: + case xr: + case $i: + case zi: + case Ni: { + s = y; + do ((s += 1), (a = i.charCodeAt(s))); + while (a === xr || a === Li || a === $i || a === zi || a === Ni); + ((b = ["space", i.slice(y, s)]), (y = s - 1)); + break; + } + case D0: + case I0: + case M0: + case B0: + case N0: + case F0: + case R0: { + let ue = String.fromCharCode(a); + b = [ue, ue, y]; + break; + } + case q0: { + if ( + ((p = w.length ? w.pop()[1] : ""), + (m = i.charCodeAt(y + 1)), + p === "url" && + m !== Ms && + m !== Nf && + m !== xr && + m !== Li && + m !== $i && + m !== Ni && + m !== zi) + ) { + s = y; + do { + if (((f = !1), (s = i.indexOf(")", s + 1)), s === -1)) + if (n || J) { + s = y; + break; + } else _("bracket"); + for (d = s; i.charCodeAt(d - 1) === Fi; ) ((d -= 1), (f = !f)); + } while (f); + ((b = ["brackets", i.slice(y, s + 1), y, s]), (y = s)); + } else + ((s = i.indexOf(")", y + 1)), + (u = i.slice(y, s + 1)), + s === -1 || z0.test(u) ? (b = ["(", "(", y]) : ((b = ["brackets", u, y, s]), (y = s))); + break; + } + case Ms: + case Nf: { + ((o = a === Ms ? "'" : '"'), (s = y)); + do { + if (((f = !1), (s = i.indexOf(o, s + 1)), s === -1)) + if (n || J) { + s = y + 1; + break; + } else _("string"); + for (d = s; i.charCodeAt(d - 1) === Fi; ) ((d -= 1), (f = !f)); + } while (f); + ((b = ["string", i.slice(y, s + 1), y, s]), (y = s)); + break; + } + case $0: { + ((ji.lastIndex = y + 1), + ji.test(i), + ji.lastIndex === 0 ? (s = i.length - 1) : (s = ji.lastIndex - 2), + (b = ["at-word", i.slice(y, s + 1), y, s]), + (y = s)); + break; + } + case Fi: { + for (s = y, c = !0; i.charCodeAt(s + 1) === Fi; ) ((s += 1), (c = !c)); + if ( + ((a = i.charCodeAt(s + 1)), + c && + a !== $f && + a !== xr && + a !== Li && + a !== $i && + a !== zi && + a !== Ni && + ((s += 1), zf.test(i.charAt(s)))) + ) { + for (; zf.test(i.charAt(s + 1)); ) s += 1; + i.charCodeAt(s + 1) === xr && (s += 1); + } + ((b = ["word", i.slice(y, s + 1), y, s]), (y = s)); + break; + } + default: { + a === $f && i.charCodeAt(y + 1) === L0 + ? ((s = i.indexOf("*/", y + 2) + 1), + s === 0 && (n || J ? (s = i.length) : _("comment")), + (b = ["comment", i.slice(y, s + 1), y, s]), + (y = s)) + : ((Vi.lastIndex = y + 1), + Vi.test(i), + Vi.lastIndex === 0 ? (s = i.length - 1) : (s = Vi.lastIndex - 2), + (b = ["word", i.slice(y, s + 1), y, s]), + w.push(b), + (y = s)); + break; + } + } + return (y++, b); + } + function q(R) { + k.push(R); + } + return { back: q, nextToken: I, endOfFile: E, position: S }; + }; + }); + var Ui = v((O3, Wf) => { + l(); + ("use strict"); + var Uf = nt(), + kr = class extends Uf { + constructor(e) { + super(e); + this.type = "atrule"; + } + append(...e) { + return (this.proxyOf.nodes || (this.nodes = []), super.append(...e)); + } + prepend(...e) { + return (this.proxyOf.nodes || (this.nodes = []), super.prepend(...e)); + } + }; + Wf.exports = kr; + kr.default = kr; + Uf.registerAtRule(kr); + }); + var Dt = v((E3, Qf) => { + l(); + ("use strict"); + var Gf = nt(), + Hf, + Yf, + vt = class extends Gf { + constructor(e) { + super(e); + ((this.type = "root"), this.nodes || (this.nodes = [])); + } + removeChild(e, t) { + let i = this.index(e); + return ( + !t && + i === 0 && + this.nodes.length > 1 && + (this.nodes[1].raws.before = this.nodes[i].raws.before), + super.removeChild(e) + ); + } + normalize(e, t, i) { + let n = super.normalize(e); + if (t) { + if (i === "prepend") + this.nodes.length > 1 ? (t.raws.before = this.nodes[1].raws.before) : delete t.raws.before; + else if (this.first !== t) for (let a of n) a.raws.before = t.raws.before; + } + return n; + } + toResult(e = {}) { + return new Hf(new Yf(), this, e).stringify(); + } + }; + vt.registerLazyResult = (r) => { + Hf = r; + }; + vt.registerProcessor = (r) => { + Yf = r; + }; + Qf.exports = vt; + vt.default = vt; + Gf.registerRoot(vt); + }); + var Bs = v((T3, Jf) => { + l(); + ("use strict"); + var Sr = { + split(r, e, t) { + let i = [], + n = "", + a = !1, + s = 0, + o = !1, + u = "", + c = !1; + for (let f of r) + (c + ? (c = !1) + : f === "\\" + ? (c = !0) + : o + ? f === u && (o = !1) + : f === '"' || f === "'" + ? ((o = !0), (u = f)) + : f === "(" + ? (s += 1) + : f === ")" + ? s > 0 && (s -= 1) + : s === 0 && e.includes(f) && (a = !0), + a ? (n !== "" && i.push(n.trim()), (n = ""), (a = !1)) : (n += f)); + return ((t || n !== "") && i.push(n.trim()), i); + }, + space(r) { + let e = [ + " ", + ` +`, + " ", + ]; + return Sr.split(r, e); + }, + comma(r) { + return Sr.split(r, [","], !0); + }, + }; + Jf.exports = Sr; + Sr.default = Sr; + }); + var Wi = v((P3, Kf) => { + l(); + ("use strict"); + var Xf = nt(), + j0 = Bs(), + Cr = class extends Xf { + constructor(e) { + super(e); + ((this.type = "rule"), this.nodes || (this.nodes = [])); + } + get selectors() { + return j0.comma(this.selector); + } + set selectors(e) { + let t = this.selector ? this.selector.match(/,\s*/) : null, + i = t ? t[0] : "," + this.raw("between", "beforeOpen"); + this.selector = e.join(i); + } + }; + Kf.exports = Cr; + Cr.default = Cr; + Xf.registerRule(Cr); + }); + var ic = v((D3, rc) => { + l(); + ("use strict"); + var V0 = br(), + U0 = Vf(), + W0 = vr(), + G0 = Ui(), + H0 = Dt(), + Zf = Wi(), + ec = { empty: !0, space: !0 }; + function Y0(r) { + for (let e = r.length - 1; e >= 0; e--) { + let t = r[e], + i = t[3] || t[2]; + if (i) return i; + } + } + var tc = class { + constructor(e) { + ((this.input = e), + (this.root = new H0()), + (this.current = this.root), + (this.spaces = ""), + (this.semicolon = !1), + (this.customProperty = !1), + this.createTokenizer(), + (this.root.source = { input: e, start: { offset: 0, line: 1, column: 1 } })); + } + createTokenizer() { + this.tokenizer = U0(this.input); + } + parse() { + let e; + for (; !this.tokenizer.endOfFile(); ) + switch (((e = this.tokenizer.nextToken()), e[0])) { + case "space": + this.spaces += e[1]; + break; + case ";": + this.freeSemicolon(e); + break; + case "}": + this.end(e); + break; + case "comment": + this.comment(e); + break; + case "at-word": + this.atrule(e); + break; + case "{": + this.emptyRule(e); + break; + default: + this.other(e); + break; + } + this.endFile(); + } + comment(e) { + let t = new W0(); + (this.init(t, e[2]), (t.source.end = this.getPosition(e[3] || e[2]))); + let i = e[1].slice(2, -2); + if (/^\s*$/.test(i)) ((t.text = ""), (t.raws.left = i), (t.raws.right = "")); + else { + let n = i.match(/^(\s*)([^]*\S)(\s*)$/); + ((t.text = n[2]), (t.raws.left = n[1]), (t.raws.right = n[3])); + } + } + emptyRule(e) { + let t = new Zf(); + (this.init(t, e[2]), (t.selector = ""), (t.raws.between = ""), (this.current = t)); + } + other(e) { + let t = !1, + i = null, + n = !1, + a = null, + s = [], + o = e[1].startsWith("--"), + u = [], + c = e; + for (; c; ) { + if (((i = c[0]), u.push(c), i === "(" || i === "[")) (a || (a = c), s.push(i === "(" ? ")" : "]")); + else if (o && n && i === "{") (a || (a = c), s.push("}")); + else if (s.length === 0) + if (i === ";") + if (n) { + this.decl(u, o); + return; + } else break; + else if (i === "{") { + this.rule(u); + return; + } else if (i === "}") { + (this.tokenizer.back(u.pop()), (t = !0)); + break; + } else i === ":" && (n = !0); + else i === s[s.length - 1] && (s.pop(), s.length === 0 && (a = null)); + c = this.tokenizer.nextToken(); + } + if ((this.tokenizer.endOfFile() && (t = !0), s.length > 0 && this.unclosedBracket(a), t && n)) { + if (!o) + for (; u.length && ((c = u[u.length - 1][0]), !(c !== "space" && c !== "comment")); ) + this.tokenizer.back(u.pop()); + this.decl(u, o); + } else this.unknownWord(u); + } + rule(e) { + e.pop(); + let t = new Zf(); + (this.init(t, e[0][2]), + (t.raws.between = this.spacesAndCommentsFromEnd(e)), + this.raw(t, "selector", e), + (this.current = t)); + } + decl(e, t) { + let i = new V0(); + this.init(i, e[0][2]); + let n = e[e.length - 1]; + for ( + n[0] === ";" && ((this.semicolon = !0), e.pop()), + i.source.end = this.getPosition(n[3] || n[2] || Y0(e)); + e[0][0] !== "word"; + ) + (e.length === 1 && this.unknownWord(e), (i.raws.before += e.shift()[1])); + for (i.source.start = this.getPosition(e[0][2]), i.prop = ""; e.length; ) { + let c = e[0][0]; + if (c === ":" || c === "space" || c === "comment") break; + i.prop += e.shift()[1]; + } + i.raws.between = ""; + let a; + for (; e.length; ) + if (((a = e.shift()), a[0] === ":")) { + i.raws.between += a[1]; + break; + } else (a[0] === "word" && /\w/.test(a[1]) && this.unknownWord([a]), (i.raws.between += a[1])); + (i.prop[0] === "_" || i.prop[0] === "*") && ((i.raws.before += i.prop[0]), (i.prop = i.prop.slice(1))); + let s = [], + o; + for (; e.length && ((o = e[0][0]), !(o !== "space" && o !== "comment")); ) s.push(e.shift()); + this.precheckMissedSemicolon(e); + for (let c = e.length - 1; c >= 0; c--) { + if (((a = e[c]), a[1].toLowerCase() === "!important")) { + i.important = !0; + let f = this.stringFrom(e, c); + ((f = this.spacesFromEnd(e) + f), f !== " !important" && (i.raws.important = f)); + break; + } else if (a[1].toLowerCase() === "important") { + let f = e.slice(0), + d = ""; + for (let p = c; p > 0; p--) { + let m = f[p][0]; + if (d.trim().indexOf("!") === 0 && m !== "space") break; + d = f.pop()[1] + d; + } + d.trim().indexOf("!") === 0 && ((i.important = !0), (i.raws.important = d), (e = f)); + } + if (a[0] !== "space" && a[0] !== "comment") break; + } + (e.some((c) => c[0] !== "space" && c[0] !== "comment") && + ((i.raws.between += s.map((c) => c[1]).join("")), (s = [])), + this.raw(i, "value", s.concat(e), t), + i.value.includes(":") && !t && this.checkMissedSemicolon(e)); + } + atrule(e) { + let t = new G0(); + ((t.name = e[1].slice(1)), t.name === "" && this.unnamedAtrule(t, e), this.init(t, e[2])); + let i, + n, + a, + s = !1, + o = !1, + u = [], + c = []; + for (; !this.tokenizer.endOfFile(); ) { + if ( + ((e = this.tokenizer.nextToken()), + (i = e[0]), + i === "(" || i === "[" + ? c.push(i === "(" ? ")" : "]") + : i === "{" && c.length > 0 + ? c.push("}") + : i === c[c.length - 1] && c.pop(), + c.length === 0) + ) + if (i === ";") { + ((t.source.end = this.getPosition(e[2])), (this.semicolon = !0)); + break; + } else if (i === "{") { + o = !0; + break; + } else if (i === "}") { + if (u.length > 0) { + for (a = u.length - 1, n = u[a]; n && n[0] === "space"; ) n = u[--a]; + n && (t.source.end = this.getPosition(n[3] || n[2])); + } + this.end(e); + break; + } else u.push(e); + else u.push(e); + if (this.tokenizer.endOfFile()) { + s = !0; + break; + } + } + ((t.raws.between = this.spacesAndCommentsFromEnd(u)), + u.length + ? ((t.raws.afterName = this.spacesAndCommentsFromStart(u)), + this.raw(t, "params", u), + s && + ((e = u[u.length - 1]), + (t.source.end = this.getPosition(e[3] || e[2])), + (this.spaces = t.raws.between), + (t.raws.between = ""))) + : ((t.raws.afterName = ""), (t.params = "")), + o && ((t.nodes = []), (this.current = t))); + } + end(e) { + (this.current.nodes && this.current.nodes.length && (this.current.raws.semicolon = this.semicolon), + (this.semicolon = !1), + (this.current.raws.after = (this.current.raws.after || "") + this.spaces), + (this.spaces = ""), + this.current.parent + ? ((this.current.source.end = this.getPosition(e[2])), (this.current = this.current.parent)) + : this.unexpectedClose(e)); + } + endFile() { + (this.current.parent && this.unclosedBlock(), + this.current.nodes && this.current.nodes.length && (this.current.raws.semicolon = this.semicolon), + (this.current.raws.after = (this.current.raws.after || "") + this.spaces)); + } + freeSemicolon(e) { + if (((this.spaces += e[1]), this.current.nodes)) { + let t = this.current.nodes[this.current.nodes.length - 1]; + t && + t.type === "rule" && + !t.raws.ownSemicolon && + ((t.raws.ownSemicolon = this.spaces), (this.spaces = "")); + } + } + getPosition(e) { + let t = this.input.fromOffset(e); + return { offset: e, line: t.line, column: t.col }; + } + init(e, t) { + (this.current.push(e), + (e.source = { start: this.getPosition(t), input: this.input }), + (e.raws.before = this.spaces), + (this.spaces = ""), + e.type !== "comment" && (this.semicolon = !1)); + } + raw(e, t, i, n) { + let a, + s, + o = i.length, + u = "", + c = !0, + f, + d; + for (let p = 0; p < o; p += 1) + ((a = i[p]), + (s = a[0]), + s === "space" && p === o - 1 && !n + ? (c = !1) + : s === "comment" + ? ((d = i[p - 1] ? i[p - 1][0] : "empty"), + (f = i[p + 1] ? i[p + 1][0] : "empty"), + !ec[d] && !ec[f] ? (u.slice(-1) === "," ? (c = !1) : (u += a[1])) : (c = !1)) + : (u += a[1])); + if (!c) { + let p = i.reduce((m, b) => m + b[1], ""); + e.raws[t] = { value: u, raw: p }; + } + e[t] = u; + } + spacesAndCommentsFromEnd(e) { + let t, + i = ""; + for (; e.length && ((t = e[e.length - 1][0]), !(t !== "space" && t !== "comment")); ) + i = e.pop()[1] + i; + return i; + } + spacesAndCommentsFromStart(e) { + let t, + i = ""; + for (; e.length && ((t = e[0][0]), !(t !== "space" && t !== "comment")); ) i += e.shift()[1]; + return i; + } + spacesFromEnd(e) { + let t, + i = ""; + for (; e.length && ((t = e[e.length - 1][0]), t === "space"); ) i = e.pop()[1] + i; + return i; + } + stringFrom(e, t) { + let i = ""; + for (let n = t; n < e.length; n++) i += e[n][1]; + return (e.splice(t, e.length - t), i); + } + colon(e) { + let t = 0, + i, + n, + a; + for (let [s, o] of e.entries()) { + if (((i = o), (n = i[0]), n === "(" && (t += 1), n === ")" && (t -= 1), t === 0 && n === ":")) + if (!a) this.doubleColon(i); + else { + if (a[0] === "word" && a[1] === "progid") continue; + return s; + } + a = i; + } + return !1; + } + unclosedBracket(e) { + throw this.input.error("Unclosed bracket", { offset: e[2] }, { offset: e[2] + 1 }); + } + unknownWord(e) { + throw this.input.error("Unknown word", { offset: e[0][2] }, { offset: e[0][2] + e[0][1].length }); + } + unexpectedClose(e) { + throw this.input.error("Unexpected }", { offset: e[2] }, { offset: e[2] + 1 }); + } + unclosedBlock() { + let e = this.current.source.start; + throw this.input.error("Unclosed block", e.line, e.column); + } + doubleColon(e) { + throw this.input.error("Double colon", { offset: e[2] }, { offset: e[2] + e[1].length }); + } + unnamedAtrule(e, t) { + throw this.input.error("At-rule without name", { offset: t[2] }, { offset: t[2] + t[1].length }); + } + precheckMissedSemicolon() {} + checkMissedSemicolon(e) { + let t = this.colon(e); + if (t === !1) return; + let i = 0, + n; + for (let a = t - 1; a >= 0 && ((n = e[a]), !(n[0] !== "space" && ((i += 1), i === 2))); a--); + throw this.input.error("Missed semicolon", n[0] === "word" ? n[3] + 1 : n[2]); + } + }; + rc.exports = tc; + }); + var nc = v(() => { + l(); + }); + var ac = v((R3, sc) => { + l(); + var Q0 = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict", + J0 = + (r, e = 21) => + (t = e) => { + let i = "", + n = t; + for (; n--; ) i += r[(Math.random() * r.length) | 0]; + return i; + }, + X0 = (r = 21) => { + let e = "", + t = r; + for (; t--; ) e += Q0[(Math.random() * 64) | 0]; + return e; + }; + sc.exports = { nanoid: X0, customAlphabet: J0 }; + }); + var Fs = v((M3, oc) => { + l(); + oc.exports = {}; + }); + var Hi = v((B3, cc) => { + l(); + ("use strict"); + var { SourceMapConsumer: K0, SourceMapGenerator: Z0 } = nc(), + { fileURLToPath: lc, pathToFileURL: Gi } = (Cs(), pf), + { resolve: Ls, isAbsolute: Ns } = (bt(), uf), + { nanoid: ev } = ac(), + $s = As(), + uc = _i(), + tv = Fs(), + zs = Symbol("fromOffsetCache"), + rv = Boolean(K0 && Z0), + fc = Boolean(Ls && Ns), + Ar = class { + constructor(e, t = {}) { + if (e === null || typeof e == "undefined" || (typeof e == "object" && !e.toString)) + throw new Error(`PostCSS received ${e} instead of CSS string`); + if ( + ((this.css = e.toString()), + this.css[0] === "\uFEFF" || this.css[0] === "\uFFFE" + ? ((this.hasBOM = !0), (this.css = this.css.slice(1))) + : (this.hasBOM = !1), + t.from && + (!fc || /^\w+:\/\//.test(t.from) || Ns(t.from) + ? (this.file = t.from) + : (this.file = Ls(t.from))), + fc && rv) + ) { + let i = new tv(this.css, t); + if (i.text) { + this.map = i; + let n = i.consumer().file; + !this.file && n && (this.file = this.mapResolve(n)); + } + } + (this.file || (this.id = ""), this.map && (this.map.file = this.from)); + } + fromOffset(e) { + let t, i; + if (this[zs]) i = this[zs]; + else { + let a = this.css.split(` +`); + i = new Array(a.length); + let s = 0; + for (let o = 0, u = a.length; o < u; o++) ((i[o] = s), (s += a[o].length + 1)); + this[zs] = i; + } + t = i[i.length - 1]; + let n = 0; + if (e >= t) n = i.length - 1; + else { + let a = i.length - 2, + s; + for (; n < a; ) + if (((s = n + ((a - n) >> 1)), e < i[s])) a = s - 1; + else if (e >= i[s + 1]) n = s + 1; + else { + n = s; + break; + } + } + return { line: n + 1, col: e - i[n] + 1 }; + } + error(e, t, i, n = {}) { + let a, s, o; + if (t && typeof t == "object") { + let c = t, + f = i; + if (typeof c.offset == "number") { + let d = this.fromOffset(c.offset); + ((t = d.line), (i = d.col)); + } else ((t = c.line), (i = c.column)); + if (typeof f.offset == "number") { + let d = this.fromOffset(f.offset); + ((s = d.line), (o = d.col)); + } else ((s = f.line), (o = f.column)); + } else if (!i) { + let c = this.fromOffset(t); + ((t = c.line), (i = c.col)); + } + let u = this.origin(t, i, s, o); + return ( + u + ? (a = new uc( + e, + u.endLine === void 0 ? u.line : { line: u.line, column: u.column }, + u.endLine === void 0 ? u.column : { line: u.endLine, column: u.endColumn }, + u.source, + u.file, + n.plugin + )) + : (a = new uc( + e, + s === void 0 ? t : { line: t, column: i }, + s === void 0 ? i : { line: s, column: o }, + this.css, + this.file, + n.plugin + )), + (a.input = { line: t, column: i, endLine: s, endColumn: o, source: this.css }), + this.file && (Gi && (a.input.url = Gi(this.file).toString()), (a.input.file = this.file)), + a + ); + } + origin(e, t, i, n) { + if (!this.map) return !1; + let a = this.map.consumer(), + s = a.originalPositionFor({ line: e, column: t }); + if (!s.source) return !1; + let o; + typeof i == "number" && (o = a.originalPositionFor({ line: i, column: n })); + let u; + Ns(s.source) + ? (u = Gi(s.source)) + : (u = new URL(s.source, this.map.consumer().sourceRoot || Gi(this.map.mapFile))); + let c = { + url: u.toString(), + line: s.line, + column: s.column, + endLine: o && o.line, + endColumn: o && o.column, + }; + if (u.protocol === "file:") + if (lc) c.file = lc(u); + else throw new Error("file: protocol is not available in this PostCSS build"); + let f = a.sourceContentFor(s.source); + return (f && (c.source = f), c); + } + mapResolve(e) { + return /^\w+:\/\//.test(e) ? e : Ls(this.map.consumer().sourceRoot || this.map.root || ".", e); + } + get from() { + return this.file || this.id; + } + toJSON() { + let e = {}; + for (let t of ["hasBOM", "css", "file", "id"]) this[t] != null && (e[t] = this[t]); + return ( + this.map && ((e.map = { ...this.map }), e.map.consumerCache && (e.map.consumerCache = void 0)), + e + ); + } + }; + cc.exports = Ar; + Ar.default = Ar; + $s && $s.registerInput && $s.registerInput(Ar); + }); + var Qi = v((F3, pc) => { + l(); + ("use strict"); + var iv = nt(), + nv = ic(), + sv = Hi(); + function Yi(r, e) { + let t = new sv(r, e), + i = new nv(t); + try { + i.parse(); + } catch (n) { + throw n; + } + return i.root; + } + pc.exports = Yi; + Yi.default = Yi; + iv.registerParse(Yi); + }); + var Us = v((N3, gc) => { + l(); + ("use strict"); + var { isClean: qe, my: av } = Oi(), + ov = Ps(), + lv = yr(), + uv = nt(), + fv = qi(), + L3 = qs(), + dc = Bi(), + cv = Qi(), + pv = Dt(), + dv = { + document: "Document", + root: "Root", + atrule: "AtRule", + rule: "Rule", + decl: "Declaration", + comment: "Comment", + }, + hv = { + postcssPlugin: !0, + prepare: !0, + Once: !0, + Document: !0, + Root: !0, + Declaration: !0, + Rule: !0, + AtRule: !0, + Comment: !0, + DeclarationExit: !0, + RuleExit: !0, + AtRuleExit: !0, + CommentExit: !0, + RootExit: !0, + DocumentExit: !0, + OnceExit: !0, + }, + mv = { postcssPlugin: !0, prepare: !0, Once: !0 }, + It = 0; + function _r(r) { + return typeof r == "object" && typeof r.then == "function"; + } + function hc(r) { + let e = !1, + t = dv[r.type]; + return ( + r.type === "decl" ? (e = r.prop.toLowerCase()) : r.type === "atrule" && (e = r.name.toLowerCase()), + e && r.append + ? [t, t + "-" + e, It, t + "Exit", t + "Exit-" + e] + : e + ? [t, t + "-" + e, t + "Exit", t + "Exit-" + e] + : r.append + ? [t, It, t + "Exit"] + : [t, t + "Exit"] + ); + } + function mc(r) { + let e; + return ( + r.type === "document" + ? (e = ["Document", It, "DocumentExit"]) + : r.type === "root" + ? (e = ["Root", It, "RootExit"]) + : (e = hc(r)), + { node: r, events: e, eventIndex: 0, visitors: [], visitorIndex: 0, iterator: 0 } + ); + } + function js(r) { + return ((r[qe] = !1), r.nodes && r.nodes.forEach((e) => js(e)), r); + } + var Vs = {}, + Ve = class { + constructor(e, t, i) { + ((this.stringified = !1), (this.processed = !1)); + let n; + if (typeof t == "object" && t !== null && (t.type === "root" || t.type === "document")) n = js(t); + else if (t instanceof Ve || t instanceof dc) + ((n = js(t.root)), + t.map && + (typeof i.map == "undefined" && (i.map = {}), + i.map.inline || (i.map.inline = !1), + (i.map.prev = t.map))); + else { + let a = cv; + (i.syntax && (a = i.syntax.parse), i.parser && (a = i.parser), a.parse && (a = a.parse)); + try { + n = a(t, i); + } catch (s) { + ((this.processed = !0), (this.error = s)); + } + n && !n[av] && uv.rebuild(n); + } + ((this.result = new dc(e, n, i)), + (this.helpers = { ...Vs, result: this.result, postcss: Vs }), + (this.plugins = this.processor.plugins.map((a) => + typeof a == "object" && a.prepare ? { ...a, ...a.prepare(this.result) } : a + ))); + } + get [Symbol.toStringTag]() { + return "LazyResult"; + } + get processor() { + return this.result.processor; + } + get opts() { + return this.result.opts; + } + get css() { + return this.stringify().css; + } + get content() { + return this.stringify().content; + } + get map() { + return this.stringify().map; + } + get root() { + return this.sync().root; + } + get messages() { + return this.sync().messages; + } + warnings() { + return this.sync().warnings(); + } + toString() { + return this.css; + } + then(e, t) { + return this.async().then(e, t); + } + catch(e) { + return this.async().catch(e); + } + finally(e) { + return this.async().then(e, e); + } + async() { + return this.error + ? Promise.reject(this.error) + : this.processed + ? Promise.resolve(this.result) + : (this.processing || (this.processing = this.runAsync()), this.processing); + } + sync() { + if (this.error) throw this.error; + if (this.processed) return this.result; + if (((this.processed = !0), this.processing)) throw this.getAsyncError(); + for (let e of this.plugins) { + let t = this.runOnRoot(e); + if (_r(t)) throw this.getAsyncError(); + } + if ((this.prepareVisitors(), this.hasListener)) { + let e = this.result.root; + for (; !e[qe]; ) ((e[qe] = !0), this.walkSync(e)); + if (this.listeners.OnceExit) + if (e.type === "document") + for (let t of e.nodes) this.visitSync(this.listeners.OnceExit, t); + else this.visitSync(this.listeners.OnceExit, e); + } + return this.result; + } + stringify() { + if (this.error) throw this.error; + if (this.stringified) return this.result; + ((this.stringified = !0), this.sync()); + let e = this.result.opts, + t = lv; + (e.syntax && (t = e.syntax.stringify), + e.stringifier && (t = e.stringifier), + t.stringify && (t = t.stringify)); + let n = new ov(t, this.result.root, this.result.opts).generate(); + return ((this.result.css = n[0]), (this.result.map = n[1]), this.result); + } + walkSync(e) { + e[qe] = !0; + let t = hc(e); + for (let i of t) + if (i === It) + e.nodes && + e.each((n) => { + n[qe] || this.walkSync(n); + }); + else { + let n = this.listeners[i]; + if (n && this.visitSync(n, e.toProxy())) return; + } + } + visitSync(e, t) { + for (let [i, n] of e) { + this.result.lastPlugin = i; + let a; + try { + a = n(t, this.helpers); + } catch (s) { + throw this.handleError(s, t.proxyOf); + } + if (t.type !== "root" && t.type !== "document" && !t.parent) return !0; + if (_r(a)) throw this.getAsyncError(); + } + } + runOnRoot(e) { + this.result.lastPlugin = e; + try { + if (typeof e == "object" && e.Once) { + if (this.result.root.type === "document") { + let t = this.result.root.nodes.map((i) => e.Once(i, this.helpers)); + return _r(t[0]) ? Promise.all(t) : t; + } + return e.Once(this.result.root, this.helpers); + } else if (typeof e == "function") return e(this.result.root, this.result); + } catch (t) { + throw this.handleError(t); + } + } + getAsyncError() { + throw new Error("Use process(css).then(cb) to work with async plugins"); + } + handleError(e, t) { + let i = this.result.lastPlugin; + try { + (t && t.addToError(e), + (this.error = e), + e.name === "CssSyntaxError" && !e.plugin + ? ((e.plugin = i.postcssPlugin), e.setMessage()) + : i.postcssVersion); + } catch (n) { + console && console.error && console.error(n); + } + return e; + } + async runAsync() { + this.plugin = 0; + for (let e = 0; e < this.plugins.length; e++) { + let t = this.plugins[e], + i = this.runOnRoot(t); + if (_r(i)) + try { + await i; + } catch (n) { + throw this.handleError(n); + } + } + if ((this.prepareVisitors(), this.hasListener)) { + let e = this.result.root; + for (; !e[qe]; ) { + e[qe] = !0; + let t = [mc(e)]; + for (; t.length > 0; ) { + let i = this.visitTick(t); + if (_r(i)) + try { + await i; + } catch (n) { + let a = t[t.length - 1].node; + throw this.handleError(n, a); + } + } + } + if (this.listeners.OnceExit) + for (let [t, i] of this.listeners.OnceExit) { + this.result.lastPlugin = t; + try { + if (e.type === "document") { + let n = e.nodes.map((a) => i(a, this.helpers)); + await Promise.all(n); + } else await i(e, this.helpers); + } catch (n) { + throw this.handleError(n); + } + } + } + return ((this.processed = !0), this.stringify()); + } + prepareVisitors() { + this.listeners = {}; + let e = (t, i, n) => { + (this.listeners[i] || (this.listeners[i] = []), this.listeners[i].push([t, n])); + }; + for (let t of this.plugins) + if (typeof t == "object") + for (let i in t) { + if (!hv[i] && /^[A-Z]/.test(i)) + throw new Error( + `Unknown event ${i} in ${t.postcssPlugin}. Try to update PostCSS (${this.processor.version} now).` + ); + if (!mv[i]) + if (typeof t[i] == "object") + for (let n in t[i]) + n === "*" ? e(t, i, t[i][n]) : e(t, i + "-" + n.toLowerCase(), t[i][n]); + else typeof t[i] == "function" && e(t, i, t[i]); + } + this.hasListener = Object.keys(this.listeners).length > 0; + } + visitTick(e) { + let t = e[e.length - 1], + { node: i, visitors: n } = t; + if (i.type !== "root" && i.type !== "document" && !i.parent) { + e.pop(); + return; + } + if (n.length > 0 && t.visitorIndex < n.length) { + let [s, o] = n[t.visitorIndex]; + ((t.visitorIndex += 1), + t.visitorIndex === n.length && ((t.visitors = []), (t.visitorIndex = 0)), + (this.result.lastPlugin = s)); + try { + return o(i.toProxy(), this.helpers); + } catch (u) { + throw this.handleError(u, i); + } + } + if (t.iterator !== 0) { + let s = t.iterator, + o; + for (; (o = i.nodes[i.indexes[s]]); ) + if (((i.indexes[s] += 1), !o[qe])) { + ((o[qe] = !0), e.push(mc(o))); + return; + } + ((t.iterator = 0), delete i.indexes[s]); + } + let a = t.events; + for (; t.eventIndex < a.length; ) { + let s = a[t.eventIndex]; + if (((t.eventIndex += 1), s === It)) { + i.nodes && i.nodes.length && ((i[qe] = !0), (t.iterator = i.getIterator())); + return; + } else if (this.listeners[s]) { + t.visitors = this.listeners[s]; + return; + } + } + e.pop(); + } + }; + Ve.registerPostcss = (r) => { + Vs = r; + }; + gc.exports = Ve; + Ve.default = Ve; + pv.registerLazyResult(Ve); + fv.registerLazyResult(Ve); + }); + var wc = v((z3, yc) => { + l(); + ("use strict"); + var gv = Ps(), + yv = yr(), + $3 = qs(), + wv = Qi(), + bv = Bi(), + Ji = class { + constructor(e, t, i) { + ((t = t.toString()), + (this.stringified = !1), + (this._processor = e), + (this._css = t), + (this._opts = i), + (this._map = void 0)); + let n, + a = yv; + ((this.result = new bv(this._processor, n, this._opts)), (this.result.css = t)); + let s = this; + Object.defineProperty(this.result, "root", { + get() { + return s.root; + }, + }); + let o = new gv(a, n, this._opts, t); + if (o.isMap()) { + let [u, c] = o.generate(); + (u && (this.result.css = u), c && (this.result.map = c)); + } + } + get [Symbol.toStringTag]() { + return "NoWorkResult"; + } + get processor() { + return this.result.processor; + } + get opts() { + return this.result.opts; + } + get css() { + return this.result.css; + } + get content() { + return this.result.css; + } + get map() { + return this.result.map; + } + get root() { + if (this._root) return this._root; + let e, + t = wv; + try { + e = t(this._css, this._opts); + } catch (i) { + this.error = i; + } + if (this.error) throw this.error; + return ((this._root = e), e); + } + get messages() { + return []; + } + warnings() { + return []; + } + toString() { + return this._css; + } + then(e, t) { + return this.async().then(e, t); + } + catch(e) { + return this.async().catch(e); + } + finally(e) { + return this.async().then(e, e); + } + async() { + return this.error ? Promise.reject(this.error) : Promise.resolve(this.result); + } + sync() { + if (this.error) throw this.error; + return this.result; + } + }; + yc.exports = Ji; + Ji.default = Ji; + }); + var vc = v((j3, bc) => { + l(); + ("use strict"); + var vv = wc(), + xv = Us(), + kv = qi(), + Sv = Dt(), + qt = class { + constructor(e = []) { + ((this.version = "8.4.24"), (this.plugins = this.normalize(e))); + } + use(e) { + return ((this.plugins = this.plugins.concat(this.normalize([e]))), this); + } + process(e, t = {}) { + return this.plugins.length === 0 && + typeof t.parser == "undefined" && + typeof t.stringifier == "undefined" && + typeof t.syntax == "undefined" + ? new vv(this, e, t) + : new xv(this, e, t); + } + normalize(e) { + let t = []; + for (let i of e) + if ( + (i.postcss === !0 ? (i = i()) : i.postcss && (i = i.postcss), + typeof i == "object" && Array.isArray(i.plugins)) + ) + t = t.concat(i.plugins); + else if (typeof i == "object" && i.postcssPlugin) t.push(i); + else if (typeof i == "function") t.push(i); + else if (!(typeof i == "object" && (i.parse || i.stringify))) + throw new Error(i + " is not a PostCSS plugin"); + return t; + } + }; + bc.exports = qt; + qt.default = qt; + Sv.registerProcessor(qt); + kv.registerProcessor(qt); + }); + var kc = v((V3, xc) => { + l(); + ("use strict"); + var Cv = br(), + Av = Fs(), + _v = vr(), + Ov = Ui(), + Ev = Hi(), + Tv = Dt(), + Pv = Wi(); + function Or(r, e) { + if (Array.isArray(r)) return r.map((n) => Or(n)); + let { inputs: t, ...i } = r; + if (t) { + e = []; + for (let n of t) { + let a = { ...n, __proto__: Ev.prototype }; + (a.map && (a.map = { ...a.map, __proto__: Av.prototype }), e.push(a)); + } + } + if ((i.nodes && (i.nodes = r.nodes.map((n) => Or(n, e))), i.source)) { + let { inputId: n, ...a } = i.source; + ((i.source = a), n != null && (i.source.input = e[n])); + } + if (i.type === "root") return new Tv(i); + if (i.type === "decl") return new Cv(i); + if (i.type === "rule") return new Pv(i); + if (i.type === "comment") return new _v(i); + if (i.type === "atrule") return new Ov(i); + throw new Error("Unknown node type: " + r.type); + } + xc.exports = Or; + Or.default = Or; + }); + var ge = v((U3, Tc) => { + l(); + ("use strict"); + var Dv = _i(), + Sc = br(), + Iv = Us(), + qv = nt(), + Ws = vc(), + Rv = yr(), + Mv = kc(), + Cc = qi(), + Bv = Rs(), + Ac = vr(), + _c = Ui(), + Fv = Bi(), + Lv = Hi(), + Nv = Qi(), + $v = Bs(), + Oc = Wi(), + Ec = Dt(), + zv = wr(); + function z(...r) { + return (r.length === 1 && Array.isArray(r[0]) && (r = r[0]), new Ws(r)); + } + z.plugin = function (e, t) { + let i = !1; + function n(...s) { + console && + console.warn && + !i && + ((i = !0), + console.warn( + e + + `: postcss.plugin was deprecated. Migration guide: +https://evilmartians.com/chronicles/postcss-8-plugin-migration` + ), + h.env.LANG && + h.env.LANG.startsWith("cn") && + console.warn( + e + + `: \u91CC\u9762 postcss.plugin \u88AB\u5F03\u7528. \u8FC1\u79FB\u6307\u5357: +https://www.w3ctech.com/topic/2226` + )); + let o = t(...s); + return ((o.postcssPlugin = e), (o.postcssVersion = new Ws().version), o); + } + let a; + return ( + Object.defineProperty(n, "postcss", { + get() { + return (a || (a = n()), a); + }, + }), + (n.process = function (s, o, u) { + return z([n(u)]).process(s, o); + }), + n + ); + }; + z.stringify = Rv; + z.parse = Nv; + z.fromJSON = Mv; + z.list = $v; + z.comment = (r) => new Ac(r); + z.atRule = (r) => new _c(r); + z.decl = (r) => new Sc(r); + z.rule = (r) => new Oc(r); + z.root = (r) => new Ec(r); + z.document = (r) => new Cc(r); + z.CssSyntaxError = Dv; + z.Declaration = Sc; + z.Container = qv; + z.Processor = Ws; + z.Document = Cc; + z.Comment = Ac; + z.Warning = Bv; + z.AtRule = _c; + z.Result = Fv; + z.Input = Lv; + z.Rule = Oc; + z.Root = Ec; + z.Node = zv; + Iv.registerPostcss(z); + Tc.exports = z; + z.default = z; + }); + var U, + j, + W3, + G3, + H3, + Y3, + Q3, + J3, + X3, + K3, + Z3, + eT, + tT, + rT, + iT, + nT, + sT, + aT, + oT, + lT, + uT, + fT, + cT, + pT, + dT, + hT, + st = C(() => { + l(); + ((U = X(ge())), + (j = U.default), + (W3 = U.default.stringify), + (G3 = U.default.fromJSON), + (H3 = U.default.plugin), + (Y3 = U.default.parse), + (Q3 = U.default.list), + (J3 = U.default.document), + (X3 = U.default.comment), + (K3 = U.default.atRule), + (Z3 = U.default.rule), + (eT = U.default.decl), + (tT = U.default.root), + (rT = U.default.CssSyntaxError), + (iT = U.default.Declaration), + (nT = U.default.Container), + (sT = U.default.Processor), + (aT = U.default.Document), + (oT = U.default.Comment), + (lT = U.default.Warning), + (uT = U.default.AtRule), + (fT = U.default.Result), + (cT = U.default.Input), + (pT = U.default.Rule), + (dT = U.default.Root), + (hT = U.default.Node)); + }); + var Gs = v((gT, Pc) => { + l(); + Pc.exports = function (r, e, t, i, n) { + for (e = e.split ? e.split(".") : e, i = 0; i < e.length; i++) r = r ? r[e[i]] : n; + return r === n ? t : r; + }; + }); + var Ki = v((Xi, Dc) => { + l(); + ("use strict"); + Xi.__esModule = !0; + Xi.default = Uv; + function jv(r) { + for (var e = r.toLowerCase(), t = "", i = !1, n = 0; n < 6 && e[n] !== void 0; n++) { + var a = e.charCodeAt(n), + s = (a >= 97 && a <= 102) || (a >= 48 && a <= 57); + if (((i = a === 32), !s)) break; + t += e[n]; + } + if (t.length !== 0) { + var o = parseInt(t, 16), + u = o >= 55296 && o <= 57343; + return u || o === 0 || o > 1114111 + ? ["\uFFFD", t.length + (i ? 1 : 0)] + : [String.fromCodePoint(o), t.length + (i ? 1 : 0)]; + } + } + var Vv = /\\/; + function Uv(r) { + var e = Vv.test(r); + if (!e) return r; + for (var t = "", i = 0; i < r.length; i++) { + if (r[i] === "\\") { + var n = jv(r.slice(i + 1, i + 7)); + if (n !== void 0) { + ((t += n[0]), (i += n[1])); + continue; + } + if (r[i + 1] === "\\") { + ((t += "\\"), i++); + continue; + } + r.length === i + 1 && (t += r[i]); + continue; + } + t += r[i]; + } + return t; + } + Dc.exports = Xi.default; + }); + var qc = v((Zi, Ic) => { + l(); + ("use strict"); + Zi.__esModule = !0; + Zi.default = Wv; + function Wv(r) { + for (var e = arguments.length, t = new Array(e > 1 ? e - 1 : 0), i = 1; i < e; i++) t[i - 1] = arguments[i]; + for (; t.length > 0; ) { + var n = t.shift(); + if (!r[n]) return; + r = r[n]; + } + return r; + } + Ic.exports = Zi.default; + }); + var Mc = v((en, Rc) => { + l(); + ("use strict"); + en.__esModule = !0; + en.default = Gv; + function Gv(r) { + for (var e = arguments.length, t = new Array(e > 1 ? e - 1 : 0), i = 1; i < e; i++) t[i - 1] = arguments[i]; + for (; t.length > 0; ) { + var n = t.shift(); + (r[n] || (r[n] = {}), (r = r[n])); + } + } + Rc.exports = en.default; + }); + var Fc = v((tn, Bc) => { + l(); + ("use strict"); + tn.__esModule = !0; + tn.default = Hv; + function Hv(r) { + for (var e = "", t = r.indexOf("/*"), i = 0; t >= 0; ) { + e = e + r.slice(i, t); + var n = r.indexOf("*/", t + 2); + if (n < 0) return e; + ((i = n + 2), (t = r.indexOf("/*", i))); + } + return ((e = e + r.slice(i)), e); + } + Bc.exports = tn.default; + }); + var Er = v((Re) => { + l(); + ("use strict"); + Re.__esModule = !0; + Re.unesc = Re.stripComments = Re.getProp = Re.ensureObject = void 0; + var Yv = rn(Ki()); + Re.unesc = Yv.default; + var Qv = rn(qc()); + Re.getProp = Qv.default; + var Jv = rn(Mc()); + Re.ensureObject = Jv.default; + var Xv = rn(Fc()); + Re.stripComments = Xv.default; + function rn(r) { + return r && r.__esModule ? r : { default: r }; + } + }); + var Ue = v((Tr, $c) => { + l(); + ("use strict"); + Tr.__esModule = !0; + Tr.default = void 0; + var Lc = Er(); + function Nc(r, e) { + for (var t = 0; t < e.length; t++) { + var i = e[t]; + ((i.enumerable = i.enumerable || !1), + (i.configurable = !0), + "value" in i && (i.writable = !0), + Object.defineProperty(r, i.key, i)); + } + } + function Kv(r, e, t) { + return (e && Nc(r.prototype, e), t && Nc(r, t), Object.defineProperty(r, "prototype", { writable: !1 }), r); + } + var Zv = function r(e, t) { + if (typeof e != "object" || e === null) return e; + var i = new e.constructor(); + for (var n in e) + if (!!e.hasOwnProperty(n)) { + var a = e[n], + s = typeof a; + n === "parent" && s === "object" + ? t && (i[n] = t) + : a instanceof Array + ? (i[n] = a.map(function (o) { + return r(o, i); + })) + : (i[n] = r(a, i)); + } + return i; + }, + ex = (function () { + function r(t) { + (t === void 0 && (t = {}), + Object.assign(this, t), + (this.spaces = this.spaces || {}), + (this.spaces.before = this.spaces.before || ""), + (this.spaces.after = this.spaces.after || "")); + } + var e = r.prototype; + return ( + (e.remove = function () { + return (this.parent && this.parent.removeChild(this), (this.parent = void 0), this); + }), + (e.replaceWith = function () { + if (this.parent) { + for (var i in arguments) this.parent.insertBefore(this, arguments[i]); + this.remove(); + } + return this; + }), + (e.next = function () { + return this.parent.at(this.parent.index(this) + 1); + }), + (e.prev = function () { + return this.parent.at(this.parent.index(this) - 1); + }), + (e.clone = function (i) { + i === void 0 && (i = {}); + var n = Zv(this); + for (var a in i) n[a] = i[a]; + return n; + }), + (e.appendToPropertyAndEscape = function (i, n, a) { + this.raws || (this.raws = {}); + var s = this[i], + o = this.raws[i]; + ((this[i] = s + n), o || a !== n ? (this.raws[i] = (o || s) + a) : delete this.raws[i]); + }), + (e.setPropertyAndEscape = function (i, n, a) { + (this.raws || (this.raws = {}), (this[i] = n), (this.raws[i] = a)); + }), + (e.setPropertyWithoutEscape = function (i, n) { + ((this[i] = n), this.raws && delete this.raws[i]); + }), + (e.isAtPosition = function (i, n) { + if (this.source && this.source.start && this.source.end) + return !( + this.source.start.line > i || + this.source.end.line < i || + (this.source.start.line === i && this.source.start.column > n) || + (this.source.end.line === i && this.source.end.column < n) + ); + }), + (e.stringifyProperty = function (i) { + return (this.raws && this.raws[i]) || this[i]; + }), + (e.valueToString = function () { + return String(this.stringifyProperty("value")); + }), + (e.toString = function () { + return [this.rawSpaceBefore, this.valueToString(), this.rawSpaceAfter].join(""); + }), + Kv(r, [ + { + key: "rawSpaceBefore", + get: function () { + var i = this.raws && this.raws.spaces && this.raws.spaces.before; + return (i === void 0 && (i = this.spaces && this.spaces.before), i || ""); + }, + set: function (i) { + ((0, Lc.ensureObject)(this, "raws", "spaces"), (this.raws.spaces.before = i)); + }, + }, + { + key: "rawSpaceAfter", + get: function () { + var i = this.raws && this.raws.spaces && this.raws.spaces.after; + return (i === void 0 && (i = this.spaces.after), i || ""); + }, + set: function (i) { + ((0, Lc.ensureObject)(this, "raws", "spaces"), (this.raws.spaces.after = i)); + }, + }, + ]), + r + ); + })(); + Tr.default = ex; + $c.exports = Tr.default; + }); + var ne = v((W) => { + l(); + ("use strict"); + W.__esModule = !0; + W.UNIVERSAL = + W.TAG = + W.STRING = + W.SELECTOR = + W.ROOT = + W.PSEUDO = + W.NESTING = + W.ID = + W.COMMENT = + W.COMBINATOR = + W.CLASS = + W.ATTRIBUTE = + void 0; + var tx = "tag"; + W.TAG = tx; + var rx = "string"; + W.STRING = rx; + var ix = "selector"; + W.SELECTOR = ix; + var nx = "root"; + W.ROOT = nx; + var sx = "pseudo"; + W.PSEUDO = sx; + var ax = "nesting"; + W.NESTING = ax; + var ox = "id"; + W.ID = ox; + var lx = "comment"; + W.COMMENT = lx; + var ux = "combinator"; + W.COMBINATOR = ux; + var fx = "class"; + W.CLASS = fx; + var cx = "attribute"; + W.ATTRIBUTE = cx; + var px = "universal"; + W.UNIVERSAL = px; + }); + var nn = v((Pr, Uc) => { + l(); + ("use strict"); + Pr.__esModule = !0; + Pr.default = void 0; + var dx = mx(Ue()), + We = hx(ne()); + function zc(r) { + if (typeof WeakMap != "function") return null; + var e = new WeakMap(), + t = new WeakMap(); + return (zc = function (n) { + return n ? t : e; + })(r); + } + function hx(r, e) { + if (!e && r && r.__esModule) return r; + if (r === null || (typeof r != "object" && typeof r != "function")) return { default: r }; + var t = zc(e); + if (t && t.has(r)) return t.get(r); + var i = {}, + n = Object.defineProperty && Object.getOwnPropertyDescriptor; + for (var a in r) + if (a !== "default" && Object.prototype.hasOwnProperty.call(r, a)) { + var s = n ? Object.getOwnPropertyDescriptor(r, a) : null; + s && (s.get || s.set) ? Object.defineProperty(i, a, s) : (i[a] = r[a]); + } + return ((i.default = r), t && t.set(r, i), i); + } + function mx(r) { + return r && r.__esModule ? r : { default: r }; + } + function gx(r, e) { + var t = (typeof Symbol != "undefined" && r[Symbol.iterator]) || r["@@iterator"]; + if (t) return (t = t.call(r)).next.bind(t); + if (Array.isArray(r) || (t = yx(r)) || (e && r && typeof r.length == "number")) { + t && (r = t); + var i = 0; + return function () { + return i >= r.length ? { done: !0 } : { done: !1, value: r[i++] }; + }; + } + throw new TypeError(`Invalid attempt to iterate non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`); + } + function yx(r, e) { + if (!!r) { + if (typeof r == "string") return jc(r, e); + var t = Object.prototype.toString.call(r).slice(8, -1); + if ((t === "Object" && r.constructor && (t = r.constructor.name), t === "Map" || t === "Set")) + return Array.from(r); + if (t === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)) return jc(r, e); + } + } + function jc(r, e) { + (e == null || e > r.length) && (e = r.length); + for (var t = 0, i = new Array(e); t < e; t++) i[t] = r[t]; + return i; + } + function Vc(r, e) { + for (var t = 0; t < e.length; t++) { + var i = e[t]; + ((i.enumerable = i.enumerable || !1), + (i.configurable = !0), + "value" in i && (i.writable = !0), + Object.defineProperty(r, i.key, i)); + } + } + function wx(r, e, t) { + return (e && Vc(r.prototype, e), t && Vc(r, t), Object.defineProperty(r, "prototype", { writable: !1 }), r); + } + function bx(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), Hs(r, e)); + } + function Hs(r, e) { + return ( + (Hs = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + Hs(r, e) + ); + } + var vx = (function (r) { + bx(e, r); + function e(i) { + var n; + return ((n = r.call(this, i) || this), n.nodes || (n.nodes = []), n); + } + var t = e.prototype; + return ( + (t.append = function (n) { + return ((n.parent = this), this.nodes.push(n), this); + }), + (t.prepend = function (n) { + return ((n.parent = this), this.nodes.unshift(n), this); + }), + (t.at = function (n) { + return this.nodes[n]; + }), + (t.index = function (n) { + return typeof n == "number" ? n : this.nodes.indexOf(n); + }), + (t.removeChild = function (n) { + ((n = this.index(n)), (this.at(n).parent = void 0), this.nodes.splice(n, 1)); + var a; + for (var s in this.indexes) ((a = this.indexes[s]), a >= n && (this.indexes[s] = a - 1)); + return this; + }), + (t.removeAll = function () { + for (var n = gx(this.nodes), a; !(a = n()).done; ) { + var s = a.value; + s.parent = void 0; + } + return ((this.nodes = []), this); + }), + (t.empty = function () { + return this.removeAll(); + }), + (t.insertAfter = function (n, a) { + a.parent = this; + var s = this.index(n); + (this.nodes.splice(s + 1, 0, a), (a.parent = this)); + var o; + for (var u in this.indexes) ((o = this.indexes[u]), s <= o && (this.indexes[u] = o + 1)); + return this; + }), + (t.insertBefore = function (n, a) { + a.parent = this; + var s = this.index(n); + (this.nodes.splice(s, 0, a), (a.parent = this)); + var o; + for (var u in this.indexes) ((o = this.indexes[u]), o <= s && (this.indexes[u] = o + 1)); + return this; + }), + (t._findChildAtPosition = function (n, a) { + var s = void 0; + return ( + this.each(function (o) { + if (o.atPosition) { + var u = o.atPosition(n, a); + if (u) return ((s = u), !1); + } else if (o.isAtPosition(n, a)) return ((s = o), !1); + }), + s + ); + }), + (t.atPosition = function (n, a) { + if (this.isAtPosition(n, a)) return this._findChildAtPosition(n, a) || this; + }), + (t._inferEndPosition = function () { + this.last && + this.last.source && + this.last.source.end && + ((this.source = this.source || {}), + (this.source.end = this.source.end || {}), + Object.assign(this.source.end, this.last.source.end)); + }), + (t.each = function (n) { + (this.lastEach || (this.lastEach = 0), this.indexes || (this.indexes = {}), this.lastEach++); + var a = this.lastEach; + if (((this.indexes[a] = 0), !!this.length)) { + for ( + var s, o; + this.indexes[a] < this.length && ((s = this.indexes[a]), (o = n(this.at(s), s)), o !== !1); + ) + this.indexes[a] += 1; + if ((delete this.indexes[a], o === !1)) return !1; + } + }), + (t.walk = function (n) { + return this.each(function (a, s) { + var o = n(a, s); + if ((o !== !1 && a.length && (o = a.walk(n)), o === !1)) return !1; + }); + }), + (t.walkAttributes = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.ATTRIBUTE) return n.call(a, s); + }); + }), + (t.walkClasses = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.CLASS) return n.call(a, s); + }); + }), + (t.walkCombinators = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.COMBINATOR) return n.call(a, s); + }); + }), + (t.walkComments = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.COMMENT) return n.call(a, s); + }); + }), + (t.walkIds = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.ID) return n.call(a, s); + }); + }), + (t.walkNesting = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.NESTING) return n.call(a, s); + }); + }), + (t.walkPseudos = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.PSEUDO) return n.call(a, s); + }); + }), + (t.walkTags = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.TAG) return n.call(a, s); + }); + }), + (t.walkUniversals = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.UNIVERSAL) return n.call(a, s); + }); + }), + (t.split = function (n) { + var a = this, + s = []; + return this.reduce(function (o, u, c) { + var f = n.call(a, u); + return (s.push(u), f ? (o.push(s), (s = [])) : c === a.length - 1 && o.push(s), o); + }, []); + }), + (t.map = function (n) { + return this.nodes.map(n); + }), + (t.reduce = function (n, a) { + return this.nodes.reduce(n, a); + }), + (t.every = function (n) { + return this.nodes.every(n); + }), + (t.some = function (n) { + return this.nodes.some(n); + }), + (t.filter = function (n) { + return this.nodes.filter(n); + }), + (t.sort = function (n) { + return this.nodes.sort(n); + }), + (t.toString = function () { + return this.map(String).join(""); + }), + wx(e, [ + { + key: "first", + get: function () { + return this.at(0); + }, + }, + { + key: "last", + get: function () { + return this.at(this.length - 1); + }, + }, + { + key: "length", + get: function () { + return this.nodes.length; + }, + }, + ]), + e + ); + })(dx.default); + Pr.default = vx; + Uc.exports = Pr.default; + }); + var Qs = v((Dr, Gc) => { + l(); + ("use strict"); + Dr.__esModule = !0; + Dr.default = void 0; + var xx = Sx(nn()), + kx = ne(); + function Sx(r) { + return r && r.__esModule ? r : { default: r }; + } + function Wc(r, e) { + for (var t = 0; t < e.length; t++) { + var i = e[t]; + ((i.enumerable = i.enumerable || !1), + (i.configurable = !0), + "value" in i && (i.writable = !0), + Object.defineProperty(r, i.key, i)); + } + } + function Cx(r, e, t) { + return (e && Wc(r.prototype, e), t && Wc(r, t), Object.defineProperty(r, "prototype", { writable: !1 }), r); + } + function Ax(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), Ys(r, e)); + } + function Ys(r, e) { + return ( + (Ys = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + Ys(r, e) + ); + } + var _x = (function (r) { + Ax(e, r); + function e(i) { + var n; + return ((n = r.call(this, i) || this), (n.type = kx.ROOT), n); + } + var t = e.prototype; + return ( + (t.toString = function () { + var n = this.reduce(function (a, s) { + return (a.push(String(s)), a); + }, []).join(","); + return this.trailingComma ? n + "," : n; + }), + (t.error = function (n, a) { + return this._error ? this._error(n, a) : new Error(n); + }), + Cx(e, [ + { + key: "errorGenerator", + set: function (n) { + this._error = n; + }, + }, + ]), + e + ); + })(xx.default); + Dr.default = _x; + Gc.exports = Dr.default; + }); + var Xs = v((Ir, Hc) => { + l(); + ("use strict"); + Ir.__esModule = !0; + Ir.default = void 0; + var Ox = Tx(nn()), + Ex = ne(); + function Tx(r) { + return r && r.__esModule ? r : { default: r }; + } + function Px(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), Js(r, e)); + } + function Js(r, e) { + return ( + (Js = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + Js(r, e) + ); + } + var Dx = (function (r) { + Px(e, r); + function e(t) { + var i; + return ((i = r.call(this, t) || this), (i.type = Ex.SELECTOR), i); + } + return e; + })(Ox.default); + Ir.default = Dx; + Hc.exports = Ir.default; + }); + var sn = v((bT, Yc) => { + l(); + ("use strict"); + var Ix = {}, + qx = Ix.hasOwnProperty, + Rx = function (e, t) { + if (!e) return t; + var i = {}; + for (var n in t) i[n] = qx.call(e, n) ? e[n] : t[n]; + return i; + }, + Mx = /[ -,\.\/:-@\[-\^`\{-~]/, + Bx = /[ -,\.\/:-@\[\]\^`\{-~]/, + Fx = /(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g, + Ks = function r(e, t) { + ((t = Rx(t, r.options)), t.quotes != "single" && t.quotes != "double" && (t.quotes = "single")); + for ( + var i = t.quotes == "double" ? '"' : "'", + n = t.isIdentifier, + a = e.charAt(0), + s = "", + o = 0, + u = e.length; + o < u; + ) { + var c = e.charAt(o++), + f = c.charCodeAt(), + d = void 0; + if (f < 32 || f > 126) { + if (f >= 55296 && f <= 56319 && o < u) { + var p = e.charCodeAt(o++); + (p & 64512) == 56320 ? (f = ((f & 1023) << 10) + (p & 1023) + 65536) : o--; + } + d = "\\" + f.toString(16).toUpperCase() + " "; + } else + t.escapeEverything + ? Mx.test(c) + ? (d = "\\" + c) + : (d = "\\" + f.toString(16).toUpperCase() + " ") + : /[\t\n\f\r\x0B]/.test(c) + ? (d = "\\" + f.toString(16).toUpperCase() + " ") + : c == "\\" || (!n && ((c == '"' && i == c) || (c == "'" && i == c))) || (n && Bx.test(c)) + ? (d = "\\" + c) + : (d = c); + s += d; + } + return ( + n && + (/^-[-\d]/.test(s) + ? (s = "\\-" + s.slice(1)) + : /\d/.test(a) && (s = "\\3" + a + " " + s.slice(1))), + (s = s.replace(Fx, function (m, b, x) { + return b && b.length % 2 ? m : (b || "") + x; + })), + !n && t.wrap ? i + s + i : s + ); + }; + Ks.options = { escapeEverything: !1, isIdentifier: !1, quotes: "single", wrap: !1 }; + Ks.version = "3.0.0"; + Yc.exports = Ks; + }); + var ea = v((qr, Xc) => { + l(); + ("use strict"); + qr.__esModule = !0; + qr.default = void 0; + var Lx = Qc(sn()), + Nx = Er(), + $x = Qc(Ue()), + zx = ne(); + function Qc(r) { + return r && r.__esModule ? r : { default: r }; + } + function Jc(r, e) { + for (var t = 0; t < e.length; t++) { + var i = e[t]; + ((i.enumerable = i.enumerable || !1), + (i.configurable = !0), + "value" in i && (i.writable = !0), + Object.defineProperty(r, i.key, i)); + } + } + function jx(r, e, t) { + return (e && Jc(r.prototype, e), t && Jc(r, t), Object.defineProperty(r, "prototype", { writable: !1 }), r); + } + function Vx(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), Zs(r, e)); + } + function Zs(r, e) { + return ( + (Zs = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + Zs(r, e) + ); + } + var Ux = (function (r) { + Vx(e, r); + function e(i) { + var n; + return ((n = r.call(this, i) || this), (n.type = zx.CLASS), (n._constructed = !0), n); + } + var t = e.prototype; + return ( + (t.valueToString = function () { + return "." + r.prototype.valueToString.call(this); + }), + jx(e, [ + { + key: "value", + get: function () { + return this._value; + }, + set: function (n) { + if (this._constructed) { + var a = (0, Lx.default)(n, { isIdentifier: !0 }); + a !== n + ? ((0, Nx.ensureObject)(this, "raws"), (this.raws.value = a)) + : this.raws && delete this.raws.value; + } + this._value = n; + }, + }, + ]), + e + ); + })($x.default); + qr.default = Ux; + Xc.exports = qr.default; + }); + var ra = v((Rr, Kc) => { + l(); + ("use strict"); + Rr.__esModule = !0; + Rr.default = void 0; + var Wx = Hx(Ue()), + Gx = ne(); + function Hx(r) { + return r && r.__esModule ? r : { default: r }; + } + function Yx(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), ta(r, e)); + } + function ta(r, e) { + return ( + (ta = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + ta(r, e) + ); + } + var Qx = (function (r) { + Yx(e, r); + function e(t) { + var i; + return ((i = r.call(this, t) || this), (i.type = Gx.COMMENT), i); + } + return e; + })(Wx.default); + Rr.default = Qx; + Kc.exports = Rr.default; + }); + var na = v((Mr, Zc) => { + l(); + ("use strict"); + Mr.__esModule = !0; + Mr.default = void 0; + var Jx = Kx(Ue()), + Xx = ne(); + function Kx(r) { + return r && r.__esModule ? r : { default: r }; + } + function Zx(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), ia(r, e)); + } + function ia(r, e) { + return ( + (ia = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + ia(r, e) + ); + } + var e1 = (function (r) { + Zx(e, r); + function e(i) { + var n; + return ((n = r.call(this, i) || this), (n.type = Xx.ID), n); + } + var t = e.prototype; + return ( + (t.valueToString = function () { + return "#" + r.prototype.valueToString.call(this); + }), + e + ); + })(Jx.default); + Mr.default = e1; + Zc.exports = Mr.default; + }); + var an = v((Br, rp) => { + l(); + ("use strict"); + Br.__esModule = !0; + Br.default = void 0; + var t1 = ep(sn()), + r1 = Er(), + i1 = ep(Ue()); + function ep(r) { + return r && r.__esModule ? r : { default: r }; + } + function tp(r, e) { + for (var t = 0; t < e.length; t++) { + var i = e[t]; + ((i.enumerable = i.enumerable || !1), + (i.configurable = !0), + "value" in i && (i.writable = !0), + Object.defineProperty(r, i.key, i)); + } + } + function n1(r, e, t) { + return (e && tp(r.prototype, e), t && tp(r, t), Object.defineProperty(r, "prototype", { writable: !1 }), r); + } + function s1(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), sa(r, e)); + } + function sa(r, e) { + return ( + (sa = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + sa(r, e) + ); + } + var a1 = (function (r) { + s1(e, r); + function e() { + return r.apply(this, arguments) || this; + } + var t = e.prototype; + return ( + (t.qualifiedName = function (n) { + return this.namespace ? this.namespaceString + "|" + n : n; + }), + (t.valueToString = function () { + return this.qualifiedName(r.prototype.valueToString.call(this)); + }), + n1(e, [ + { + key: "namespace", + get: function () { + return this._namespace; + }, + set: function (n) { + if (n === !0 || n === "*" || n === "&") { + ((this._namespace = n), this.raws && delete this.raws.namespace); + return; + } + var a = (0, t1.default)(n, { isIdentifier: !0 }); + ((this._namespace = n), + a !== n + ? ((0, r1.ensureObject)(this, "raws"), (this.raws.namespace = a)) + : this.raws && delete this.raws.namespace); + }, + }, + { + key: "ns", + get: function () { + return this._namespace; + }, + set: function (n) { + this.namespace = n; + }, + }, + { + key: "namespaceString", + get: function () { + if (this.namespace) { + var n = this.stringifyProperty("namespace"); + return n === !0 ? "" : n; + } else return ""; + }, + }, + ]), + e + ); + })(i1.default); + Br.default = a1; + rp.exports = Br.default; + }); + var oa = v((Fr, ip) => { + l(); + ("use strict"); + Fr.__esModule = !0; + Fr.default = void 0; + var o1 = u1(an()), + l1 = ne(); + function u1(r) { + return r && r.__esModule ? r : { default: r }; + } + function f1(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), aa(r, e)); + } + function aa(r, e) { + return ( + (aa = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + aa(r, e) + ); + } + var c1 = (function (r) { + f1(e, r); + function e(t) { + var i; + return ((i = r.call(this, t) || this), (i.type = l1.TAG), i); + } + return e; + })(o1.default); + Fr.default = c1; + ip.exports = Fr.default; + }); + var ua = v((Lr, np) => { + l(); + ("use strict"); + Lr.__esModule = !0; + Lr.default = void 0; + var p1 = h1(Ue()), + d1 = ne(); + function h1(r) { + return r && r.__esModule ? r : { default: r }; + } + function m1(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), la(r, e)); + } + function la(r, e) { + return ( + (la = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + la(r, e) + ); + } + var g1 = (function (r) { + m1(e, r); + function e(t) { + var i; + return ((i = r.call(this, t) || this), (i.type = d1.STRING), i); + } + return e; + })(p1.default); + Lr.default = g1; + np.exports = Lr.default; + }); + var ca = v((Nr, sp) => { + l(); + ("use strict"); + Nr.__esModule = !0; + Nr.default = void 0; + var y1 = b1(nn()), + w1 = ne(); + function b1(r) { + return r && r.__esModule ? r : { default: r }; + } + function v1(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), fa(r, e)); + } + function fa(r, e) { + return ( + (fa = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + fa(r, e) + ); + } + var x1 = (function (r) { + v1(e, r); + function e(i) { + var n; + return ((n = r.call(this, i) || this), (n.type = w1.PSEUDO), n); + } + var t = e.prototype; + return ( + (t.toString = function () { + var n = this.length ? "(" + this.map(String).join(",") + ")" : ""; + return [this.rawSpaceBefore, this.stringifyProperty("value"), n, this.rawSpaceAfter].join(""); + }), + e + ); + })(y1.default); + Nr.default = x1; + sp.exports = Nr.default; + }); + var ap = {}; + Ae(ap, { deprecate: () => k1 }); + function k1(r) { + return r; + } + var op = C(() => { + l(); + }); + var up = v((vT, lp) => { + l(); + lp.exports = (op(), ap).deprecate; + }); + var ya = v((jr) => { + l(); + ("use strict"); + jr.__esModule = !0; + jr.default = void 0; + jr.unescapeValue = ma; + var $r = da(sn()), + S1 = da(Ki()), + C1 = da(an()), + A1 = ne(), + pa; + function da(r) { + return r && r.__esModule ? r : { default: r }; + } + function fp(r, e) { + for (var t = 0; t < e.length; t++) { + var i = e[t]; + ((i.enumerable = i.enumerable || !1), + (i.configurable = !0), + "value" in i && (i.writable = !0), + Object.defineProperty(r, i.key, i)); + } + } + function _1(r, e, t) { + return (e && fp(r.prototype, e), t && fp(r, t), Object.defineProperty(r, "prototype", { writable: !1 }), r); + } + function O1(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), ha(r, e)); + } + function ha(r, e) { + return ( + (ha = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + ha(r, e) + ); + } + var zr = up(), + E1 = /^('|")([^]*)\1$/, + T1 = zr( + function () {}, + "Assigning an attribute a value containing characters that might need to be escaped is deprecated. Call attribute.setValue() instead." + ), + P1 = zr( + function () {}, + "Assigning attr.quoted is deprecated and has no effect. Assign to attr.quoteMark instead." + ), + D1 = zr( + function () {}, + "Constructing an Attribute selector with a value without specifying quoteMark is deprecated. Note: The value should be unescaped now." + ); + function ma(r) { + var e = !1, + t = null, + i = r, + n = i.match(E1); + return ( + n && ((t = n[1]), (i = n[2])), + (i = (0, S1.default)(i)), + i !== r && (e = !0), + { deprecatedUsage: e, unescaped: i, quoteMark: t } + ); + } + function I1(r) { + if (r.quoteMark !== void 0 || r.value === void 0) return r; + D1(); + var e = ma(r.value), + t = e.quoteMark, + i = e.unescaped; + return ( + r.raws || (r.raws = {}), + r.raws.value === void 0 && (r.raws.value = r.value), + (r.value = i), + (r.quoteMark = t), + r + ); + } + var on = (function (r) { + O1(e, r); + function e(i) { + var n; + return ( + i === void 0 && (i = {}), + (n = r.call(this, I1(i)) || this), + (n.type = A1.ATTRIBUTE), + (n.raws = n.raws || {}), + Object.defineProperty(n.raws, "unquoted", { + get: zr(function () { + return n.value; + }, "attr.raws.unquoted is deprecated. Call attr.value instead."), + set: zr(function () { + return n.value; + }, "Setting attr.raws.unquoted is deprecated and has no effect. attr.value is unescaped by default now."), + }), + (n._constructed = !0), + n + ); + } + var t = e.prototype; + return ( + (t.getQuotedValue = function (n) { + n === void 0 && (n = {}); + var a = this._determineQuoteMark(n), + s = ga[a], + o = (0, $r.default)(this._value, s); + return o; + }), + (t._determineQuoteMark = function (n) { + return n.smart ? this.smartQuoteMark(n) : this.preferredQuoteMark(n); + }), + (t.setValue = function (n, a) { + (a === void 0 && (a = {}), + (this._value = n), + (this._quoteMark = this._determineQuoteMark(a)), + this._syncRawValue()); + }), + (t.smartQuoteMark = function (n) { + var a = this.value, + s = a.replace(/[^']/g, "").length, + o = a.replace(/[^"]/g, "").length; + if (s + o === 0) { + var u = (0, $r.default)(a, { isIdentifier: !0 }); + if (u === a) return e.NO_QUOTE; + var c = this.preferredQuoteMark(n); + if (c === e.NO_QUOTE) { + var f = this.quoteMark || n.quoteMark || e.DOUBLE_QUOTE, + d = ga[f], + p = (0, $r.default)(a, d); + if (p.length < u.length) return f; + } + return c; + } else return o === s ? this.preferredQuoteMark(n) : o < s ? e.DOUBLE_QUOTE : e.SINGLE_QUOTE; + }), + (t.preferredQuoteMark = function (n) { + var a = n.preferCurrentQuoteMark ? this.quoteMark : n.quoteMark; + return ( + a === void 0 && (a = n.preferCurrentQuoteMark ? n.quoteMark : this.quoteMark), + a === void 0 && (a = e.DOUBLE_QUOTE), + a + ); + }), + (t._syncRawValue = function () { + var n = (0, $r.default)(this._value, ga[this.quoteMark]); + n === this._value ? this.raws && delete this.raws.value : (this.raws.value = n); + }), + (t._handleEscapes = function (n, a) { + if (this._constructed) { + var s = (0, $r.default)(a, { isIdentifier: !0 }); + s !== a ? (this.raws[n] = s) : delete this.raws[n]; + } + }), + (t._spacesFor = function (n) { + var a = { before: "", after: "" }, + s = this.spaces[n] || {}, + o = (this.raws.spaces && this.raws.spaces[n]) || {}; + return Object.assign(a, s, o); + }), + (t._stringFor = function (n, a, s) { + (a === void 0 && (a = n), s === void 0 && (s = cp)); + var o = this._spacesFor(a); + return s(this.stringifyProperty(n), o); + }), + (t.offsetOf = function (n) { + var a = 1, + s = this._spacesFor("attribute"); + if (((a += s.before.length), n === "namespace" || n === "ns")) return this.namespace ? a : -1; + if ( + n === "attributeNS" || + ((a += this.namespaceString.length), this.namespace && (a += 1), n === "attribute") + ) + return a; + ((a += this.stringifyProperty("attribute").length), (a += s.after.length)); + var o = this._spacesFor("operator"); + a += o.before.length; + var u = this.stringifyProperty("operator"); + if (n === "operator") return u ? a : -1; + ((a += u.length), (a += o.after.length)); + var c = this._spacesFor("value"); + a += c.before.length; + var f = this.stringifyProperty("value"); + if (n === "value") return f ? a : -1; + ((a += f.length), (a += c.after.length)); + var d = this._spacesFor("insensitive"); + return ((a += d.before.length), n === "insensitive" && this.insensitive ? a : -1); + }), + (t.toString = function () { + var n = this, + a = [this.rawSpaceBefore, "["]; + return ( + a.push(this._stringFor("qualifiedAttribute", "attribute")), + this.operator && + (this.value || this.value === "") && + (a.push(this._stringFor("operator")), + a.push(this._stringFor("value")), + a.push( + this._stringFor("insensitiveFlag", "insensitive", function (s, o) { + return ( + s.length > 0 && + !n.quoted && + o.before.length === 0 && + !(n.spaces.value && n.spaces.value.after) && + (o.before = " "), + cp(s, o) + ); + }) + )), + a.push("]"), + a.push(this.rawSpaceAfter), + a.join("") + ); + }), + _1(e, [ + { + key: "quoted", + get: function () { + var n = this.quoteMark; + return n === "'" || n === '"'; + }, + set: function (n) { + P1(); + }, + }, + { + key: "quoteMark", + get: function () { + return this._quoteMark; + }, + set: function (n) { + if (!this._constructed) { + this._quoteMark = n; + return; + } + this._quoteMark !== n && ((this._quoteMark = n), this._syncRawValue()); + }, + }, + { + key: "qualifiedAttribute", + get: function () { + return this.qualifiedName(this.raws.attribute || this.attribute); + }, + }, + { + key: "insensitiveFlag", + get: function () { + return this.insensitive ? "i" : ""; + }, + }, + { + key: "value", + get: function () { + return this._value; + }, + set: function (n) { + if (this._constructed) { + var a = ma(n), + s = a.deprecatedUsage, + o = a.unescaped, + u = a.quoteMark; + if ((s && T1(), o === this._value && u === this._quoteMark)) return; + ((this._value = o), (this._quoteMark = u), this._syncRawValue()); + } else this._value = n; + }, + }, + { + key: "insensitive", + get: function () { + return this._insensitive; + }, + set: function (n) { + (n || + ((this._insensitive = !1), + this.raws && + (this.raws.insensitiveFlag === "I" || this.raws.insensitiveFlag === "i") && + (this.raws.insensitiveFlag = void 0)), + (this._insensitive = n)); + }, + }, + { + key: "attribute", + get: function () { + return this._attribute; + }, + set: function (n) { + (this._handleEscapes("attribute", n), (this._attribute = n)); + }, + }, + ]), + e + ); + })(C1.default); + jr.default = on; + on.NO_QUOTE = null; + on.SINGLE_QUOTE = "'"; + on.DOUBLE_QUOTE = '"'; + var ga = + ((pa = { "'": { quotes: "single", wrap: !0 }, '"': { quotes: "double", wrap: !0 } }), + (pa[null] = { isIdentifier: !0 }), + pa); + function cp(r, e) { + return "" + e.before + r + e.after; + } + }); + var ba = v((Vr, pp) => { + l(); + ("use strict"); + Vr.__esModule = !0; + Vr.default = void 0; + var q1 = M1(an()), + R1 = ne(); + function M1(r) { + return r && r.__esModule ? r : { default: r }; + } + function B1(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), wa(r, e)); + } + function wa(r, e) { + return ( + (wa = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + wa(r, e) + ); + } + var F1 = (function (r) { + B1(e, r); + function e(t) { + var i; + return ((i = r.call(this, t) || this), (i.type = R1.UNIVERSAL), (i.value = "*"), i); + } + return e; + })(q1.default); + Vr.default = F1; + pp.exports = Vr.default; + }); + var xa = v((Ur, dp) => { + l(); + ("use strict"); + Ur.__esModule = !0; + Ur.default = void 0; + var L1 = $1(Ue()), + N1 = ne(); + function $1(r) { + return r && r.__esModule ? r : { default: r }; + } + function z1(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), va(r, e)); + } + function va(r, e) { + return ( + (va = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + va(r, e) + ); + } + var j1 = (function (r) { + z1(e, r); + function e(t) { + var i; + return ((i = r.call(this, t) || this), (i.type = N1.COMBINATOR), i); + } + return e; + })(L1.default); + Ur.default = j1; + dp.exports = Ur.default; + }); + var Sa = v((Wr, hp) => { + l(); + ("use strict"); + Wr.__esModule = !0; + Wr.default = void 0; + var V1 = W1(Ue()), + U1 = ne(); + function W1(r) { + return r && r.__esModule ? r : { default: r }; + } + function G1(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), ka(r, e)); + } + function ka(r, e) { + return ( + (ka = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + ka(r, e) + ); + } + var H1 = (function (r) { + G1(e, r); + function e(t) { + var i; + return ((i = r.call(this, t) || this), (i.type = U1.NESTING), (i.value = "&"), i); + } + return e; + })(V1.default); + Wr.default = H1; + hp.exports = Wr.default; + }); + var gp = v((ln, mp) => { + l(); + ("use strict"); + ln.__esModule = !0; + ln.default = Y1; + function Y1(r) { + return r.sort(function (e, t) { + return e - t; + }); + } + mp.exports = ln.default; + }); + var Ca = v((D) => { + l(); + ("use strict"); + D.__esModule = !0; + D.word = + D.tilde = + D.tab = + D.str = + D.space = + D.slash = + D.singleQuote = + D.semicolon = + D.plus = + D.pipe = + D.openSquare = + D.openParenthesis = + D.newline = + D.greaterThan = + D.feed = + D.equals = + D.doubleQuote = + D.dollar = + D.cr = + D.comment = + D.comma = + D.combinator = + D.colon = + D.closeSquare = + D.closeParenthesis = + D.caret = + D.bang = + D.backslash = + D.at = + D.asterisk = + D.ampersand = + void 0; + var Q1 = 38; + D.ampersand = Q1; + var J1 = 42; + D.asterisk = J1; + var X1 = 64; + D.at = X1; + var K1 = 44; + D.comma = K1; + var Z1 = 58; + D.colon = Z1; + var ek = 59; + D.semicolon = ek; + var tk = 40; + D.openParenthesis = tk; + var rk = 41; + D.closeParenthesis = rk; + var ik = 91; + D.openSquare = ik; + var nk = 93; + D.closeSquare = nk; + var sk = 36; + D.dollar = sk; + var ak = 126; + D.tilde = ak; + var ok = 94; + D.caret = ok; + var lk = 43; + D.plus = lk; + var uk = 61; + D.equals = uk; + var fk = 124; + D.pipe = fk; + var ck = 62; + D.greaterThan = ck; + var pk = 32; + D.space = pk; + var yp = 39; + D.singleQuote = yp; + var dk = 34; + D.doubleQuote = dk; + var hk = 47; + D.slash = hk; + var mk = 33; + D.bang = mk; + var gk = 92; + D.backslash = gk; + var yk = 13; + D.cr = yk; + var wk = 12; + D.feed = wk; + var bk = 10; + D.newline = bk; + var vk = 9; + D.tab = vk; + var xk = yp; + D.str = xk; + var kk = -1; + D.comment = kk; + var Sk = -2; + D.word = Sk; + var Ck = -3; + D.combinator = Ck; + }); + var vp = v((Gr) => { + l(); + ("use strict"); + Gr.__esModule = !0; + Gr.FIELDS = void 0; + Gr.default = Dk; + var O = Ak(Ca()), + Rt, + V; + function wp(r) { + if (typeof WeakMap != "function") return null; + var e = new WeakMap(), + t = new WeakMap(); + return (wp = function (n) { + return n ? t : e; + })(r); + } + function Ak(r, e) { + if (!e && r && r.__esModule) return r; + if (r === null || (typeof r != "object" && typeof r != "function")) return { default: r }; + var t = wp(e); + if (t && t.has(r)) return t.get(r); + var i = {}, + n = Object.defineProperty && Object.getOwnPropertyDescriptor; + for (var a in r) + if (a !== "default" && Object.prototype.hasOwnProperty.call(r, a)) { + var s = n ? Object.getOwnPropertyDescriptor(r, a) : null; + s && (s.get || s.set) ? Object.defineProperty(i, a, s) : (i[a] = r[a]); + } + return ((i.default = r), t && t.set(r, i), i); + } + var _k = ((Rt = {}), (Rt[O.tab] = !0), (Rt[O.newline] = !0), (Rt[O.cr] = !0), (Rt[O.feed] = !0), Rt), + Ok = + ((V = {}), + (V[O.space] = !0), + (V[O.tab] = !0), + (V[O.newline] = !0), + (V[O.cr] = !0), + (V[O.feed] = !0), + (V[O.ampersand] = !0), + (V[O.asterisk] = !0), + (V[O.bang] = !0), + (V[O.comma] = !0), + (V[O.colon] = !0), + (V[O.semicolon] = !0), + (V[O.openParenthesis] = !0), + (V[O.closeParenthesis] = !0), + (V[O.openSquare] = !0), + (V[O.closeSquare] = !0), + (V[O.singleQuote] = !0), + (V[O.doubleQuote] = !0), + (V[O.plus] = !0), + (V[O.pipe] = !0), + (V[O.tilde] = !0), + (V[O.greaterThan] = !0), + (V[O.equals] = !0), + (V[O.dollar] = !0), + (V[O.caret] = !0), + (V[O.slash] = !0), + V), + Aa = {}, + bp = "0123456789abcdefABCDEF"; + for (un = 0; un < bp.length; un++) Aa[bp.charCodeAt(un)] = !0; + var un; + function Ek(r, e) { + var t = e, + i; + do { + if (((i = r.charCodeAt(t)), Ok[i])) return t - 1; + i === O.backslash ? (t = Tk(r, t) + 1) : t++; + } while (t < r.length); + return t - 1; + } + function Tk(r, e) { + var t = e, + i = r.charCodeAt(t + 1); + if (!_k[i]) + if (Aa[i]) { + var n = 0; + do (t++, n++, (i = r.charCodeAt(t + 1))); + while (Aa[i] && n < 6); + n < 6 && i === O.space && t++; + } else t++; + return t; + } + var Pk = { TYPE: 0, START_LINE: 1, START_COL: 2, END_LINE: 3, END_COL: 4, START_POS: 5, END_POS: 6 }; + Gr.FIELDS = Pk; + function Dk(r) { + var e = [], + t = r.css.valueOf(), + i = t, + n = i.length, + a = -1, + s = 1, + o = 0, + u = 0, + c, + f, + d, + p, + m, + b, + x, + y, + w, + k, + S, + _, + E; + function I(q, R) { + if (r.safe) ((t += R), (w = t.length - 1)); + else throw r.error("Unclosed " + q, s, o - a, o); + } + for (; o < n; ) { + switch (((c = t.charCodeAt(o)), c === O.newline && ((a = o), (s += 1)), c)) { + case O.space: + case O.tab: + case O.newline: + case O.cr: + case O.feed: + w = o; + do ((w += 1), (c = t.charCodeAt(w)), c === O.newline && ((a = w), (s += 1))); + while (c === O.space || c === O.newline || c === O.tab || c === O.cr || c === O.feed); + ((E = O.space), (p = s), (d = w - a - 1), (u = w)); + break; + case O.plus: + case O.greaterThan: + case O.tilde: + case O.pipe: + w = o; + do ((w += 1), (c = t.charCodeAt(w))); + while (c === O.plus || c === O.greaterThan || c === O.tilde || c === O.pipe); + ((E = O.combinator), (p = s), (d = o - a), (u = w)); + break; + case O.asterisk: + case O.ampersand: + case O.bang: + case O.comma: + case O.equals: + case O.dollar: + case O.caret: + case O.openSquare: + case O.closeSquare: + case O.colon: + case O.semicolon: + case O.openParenthesis: + case O.closeParenthesis: + ((w = o), (E = c), (p = s), (d = o - a), (u = w + 1)); + break; + case O.singleQuote: + case O.doubleQuote: + ((_ = c === O.singleQuote ? "'" : '"'), (w = o)); + do + for ( + m = !1, w = t.indexOf(_, w + 1), w === -1 && I("quote", _), b = w; + t.charCodeAt(b - 1) === O.backslash; + ) + ((b -= 1), (m = !m)); + while (m); + ((E = O.str), (p = s), (d = o - a), (u = w + 1)); + break; + default: + (c === O.slash && t.charCodeAt(o + 1) === O.asterisk + ? ((w = t.indexOf("*/", o + 2) + 1), + w === 0 && I("comment", "*/"), + (f = t.slice(o, w + 1)), + (y = f.split(` +`)), + (x = y.length - 1), + x > 0 ? ((k = s + x), (S = w - y[x].length)) : ((k = s), (S = a)), + (E = O.comment), + (s = k), + (p = k), + (d = w - S)) + : c === O.slash + ? ((w = o), (E = c), (p = s), (d = o - a), (u = w + 1)) + : ((w = Ek(t, o)), (E = O.word), (p = s), (d = w - a)), + (u = w + 1)); + break; + } + (e.push([E, s, o - a, p, d, o, u]), S && ((a = S), (S = null)), (o = u)); + } + return e; + } + }); + var Ep = v((Hr, Op) => { + l(); + ("use strict"); + Hr.__esModule = !0; + Hr.default = void 0; + var Ik = be(Qs()), + _a = be(Xs()), + qk = be(ea()), + xp = be(ra()), + Rk = be(na()), + Mk = be(oa()), + Oa = be(ua()), + Bk = be(ca()), + kp = fn(ya()), + Fk = be(ba()), + Ea = be(xa()), + Lk = be(Sa()), + Nk = be(gp()), + A = fn(vp()), + T = fn(Ca()), + $k = fn(ne()), + Y = Er(), + xt, + Ta; + function Sp(r) { + if (typeof WeakMap != "function") return null; + var e = new WeakMap(), + t = new WeakMap(); + return (Sp = function (n) { + return n ? t : e; + })(r); + } + function fn(r, e) { + if (!e && r && r.__esModule) return r; + if (r === null || (typeof r != "object" && typeof r != "function")) return { default: r }; + var t = Sp(e); + if (t && t.has(r)) return t.get(r); + var i = {}, + n = Object.defineProperty && Object.getOwnPropertyDescriptor; + for (var a in r) + if (a !== "default" && Object.prototype.hasOwnProperty.call(r, a)) { + var s = n ? Object.getOwnPropertyDescriptor(r, a) : null; + s && (s.get || s.set) ? Object.defineProperty(i, a, s) : (i[a] = r[a]); + } + return ((i.default = r), t && t.set(r, i), i); + } + function be(r) { + return r && r.__esModule ? r : { default: r }; + } + function Cp(r, e) { + for (var t = 0; t < e.length; t++) { + var i = e[t]; + ((i.enumerable = i.enumerable || !1), + (i.configurable = !0), + "value" in i && (i.writable = !0), + Object.defineProperty(r, i.key, i)); + } + } + function zk(r, e, t) { + return (e && Cp(r.prototype, e), t && Cp(r, t), Object.defineProperty(r, "prototype", { writable: !1 }), r); + } + var Pa = + ((xt = {}), + (xt[T.space] = !0), + (xt[T.cr] = !0), + (xt[T.feed] = !0), + (xt[T.newline] = !0), + (xt[T.tab] = !0), + xt), + jk = Object.assign({}, Pa, ((Ta = {}), (Ta[T.comment] = !0), Ta)); + function Ap(r) { + return { line: r[A.FIELDS.START_LINE], column: r[A.FIELDS.START_COL] }; + } + function _p(r) { + return { line: r[A.FIELDS.END_LINE], column: r[A.FIELDS.END_COL] }; + } + function kt(r, e, t, i) { + return { start: { line: r, column: e }, end: { line: t, column: i } }; + } + function Mt(r) { + return kt(r[A.FIELDS.START_LINE], r[A.FIELDS.START_COL], r[A.FIELDS.END_LINE], r[A.FIELDS.END_COL]); + } + function Da(r, e) { + if (!!r) + return kt(r[A.FIELDS.START_LINE], r[A.FIELDS.START_COL], e[A.FIELDS.END_LINE], e[A.FIELDS.END_COL]); + } + function Bt(r, e) { + var t = r[e]; + if (typeof t == "string") + return ( + t.indexOf("\\") !== -1 && + ((0, Y.ensureObject)(r, "raws"), + (r[e] = (0, Y.unesc)(t)), + r.raws[e] === void 0 && (r.raws[e] = t)), + r + ); + } + function Ia(r, e) { + for (var t = -1, i = []; (t = r.indexOf(e, t + 1)) !== -1; ) i.push(t); + return i; + } + function Vk() { + var r = Array.prototype.concat.apply([], arguments); + return r.filter(function (e, t) { + return t === r.indexOf(e); + }); + } + var Uk = (function () { + function r(t, i) { + (i === void 0 && (i = {}), + (this.rule = t), + (this.options = Object.assign({ lossy: !1, safe: !1 }, i)), + (this.position = 0), + (this.css = typeof this.rule == "string" ? this.rule : this.rule.selector), + (this.tokens = (0, A.default)({ + css: this.css, + error: this._errorGenerator(), + safe: this.options.safe, + }))); + var n = Da(this.tokens[0], this.tokens[this.tokens.length - 1]); + ((this.root = new Ik.default({ source: n })), (this.root.errorGenerator = this._errorGenerator())); + var a = new _a.default({ source: { start: { line: 1, column: 1 } } }); + (this.root.append(a), (this.current = a), this.loop()); + } + var e = r.prototype; + return ( + (e._errorGenerator = function () { + var i = this; + return function (n, a) { + return typeof i.rule == "string" ? new Error(n) : i.rule.error(n, a); + }; + }), + (e.attribute = function () { + var i = [], + n = this.currToken; + for ( + this.position++; + this.position < this.tokens.length && this.currToken[A.FIELDS.TYPE] !== T.closeSquare; + ) + (i.push(this.currToken), this.position++); + if (this.currToken[A.FIELDS.TYPE] !== T.closeSquare) + return this.expected("closing square bracket", this.currToken[A.FIELDS.START_POS]); + var a = i.length, + s = { + source: kt(n[1], n[2], this.currToken[3], this.currToken[4]), + sourceIndex: n[A.FIELDS.START_POS], + }; + if (a === 1 && !~[T.word].indexOf(i[0][A.FIELDS.TYPE])) + return this.expected("attribute", i[0][A.FIELDS.START_POS]); + for (var o = 0, u = "", c = "", f = null, d = !1; o < a; ) { + var p = i[o], + m = this.content(p), + b = i[o + 1]; + switch (p[A.FIELDS.TYPE]) { + case T.space: + if (((d = !0), this.options.lossy)) break; + if (f) { + (0, Y.ensureObject)(s, "spaces", f); + var x = s.spaces[f].after || ""; + s.spaces[f].after = x + m; + var y = (0, Y.getProp)(s, "raws", "spaces", f, "after") || null; + y && (s.raws.spaces[f].after = y + m); + } else ((u = u + m), (c = c + m)); + break; + case T.asterisk: + if (b[A.FIELDS.TYPE] === T.equals) ((s.operator = m), (f = "operator")); + else if ((!s.namespace || (f === "namespace" && !d)) && b) { + (u && + ((0, Y.ensureObject)(s, "spaces", "attribute"), + (s.spaces.attribute.before = u), + (u = "")), + c && + ((0, Y.ensureObject)(s, "raws", "spaces", "attribute"), + (s.raws.spaces.attribute.before = u), + (c = "")), + (s.namespace = (s.namespace || "") + m)); + var w = (0, Y.getProp)(s, "raws", "namespace") || null; + (w && (s.raws.namespace += m), (f = "namespace")); + } + d = !1; + break; + case T.dollar: + if (f === "value") { + var k = (0, Y.getProp)(s, "raws", "value"); + ((s.value += "$"), k && (s.raws.value = k + "$")); + break; + } + case T.caret: + (b[A.FIELDS.TYPE] === T.equals && ((s.operator = m), (f = "operator")), (d = !1)); + break; + case T.combinator: + if ( + (m === "~" && b[A.FIELDS.TYPE] === T.equals && ((s.operator = m), (f = "operator")), + m !== "|") + ) { + d = !1; + break; + } + (b[A.FIELDS.TYPE] === T.equals + ? ((s.operator = m), (f = "operator")) + : !s.namespace && !s.attribute && (s.namespace = !0), + (d = !1)); + break; + case T.word: + if ( + b && + this.content(b) === "|" && + i[o + 2] && + i[o + 2][A.FIELDS.TYPE] !== T.equals && + !s.operator && + !s.namespace + ) + ((s.namespace = m), (f = "namespace")); + else if (!s.attribute || (f === "attribute" && !d)) { + (u && + ((0, Y.ensureObject)(s, "spaces", "attribute"), + (s.spaces.attribute.before = u), + (u = "")), + c && + ((0, Y.ensureObject)(s, "raws", "spaces", "attribute"), + (s.raws.spaces.attribute.before = c), + (c = "")), + (s.attribute = (s.attribute || "") + m)); + var S = (0, Y.getProp)(s, "raws", "attribute") || null; + (S && (s.raws.attribute += m), (f = "attribute")); + } else if ((!s.value && s.value !== "") || (f === "value" && !(d || s.quoteMark))) { + var _ = (0, Y.unesc)(m), + E = (0, Y.getProp)(s, "raws", "value") || "", + I = s.value || ""; + ((s.value = I + _), + (s.quoteMark = null), + (_ !== m || E) && + ((0, Y.ensureObject)(s, "raws"), (s.raws.value = (E || I) + m)), + (f = "value")); + } else { + var q = m === "i" || m === "I"; + (s.value || s.value === "") && (s.quoteMark || d) + ? ((s.insensitive = q), + (!q || m === "I") && + ((0, Y.ensureObject)(s, "raws"), (s.raws.insensitiveFlag = m)), + (f = "insensitive"), + u && + ((0, Y.ensureObject)(s, "spaces", "insensitive"), + (s.spaces.insensitive.before = u), + (u = "")), + c && + ((0, Y.ensureObject)(s, "raws", "spaces", "insensitive"), + (s.raws.spaces.insensitive.before = c), + (c = ""))) + : (s.value || s.value === "") && + ((f = "value"), (s.value += m), s.raws.value && (s.raws.value += m)); + } + d = !1; + break; + case T.str: + if (!s.attribute || !s.operator) + return this.error( + "Expected an attribute followed by an operator preceding the string.", + { index: p[A.FIELDS.START_POS] } + ); + var R = (0, kp.unescapeValue)(m), + J = R.unescaped, + ue = R.quoteMark; + ((s.value = J), + (s.quoteMark = ue), + (f = "value"), + (0, Y.ensureObject)(s, "raws"), + (s.raws.value = m), + (d = !1)); + break; + case T.equals: + if (!s.attribute) return this.expected("attribute", p[A.FIELDS.START_POS], m); + if (s.value) + return this.error('Unexpected "=" found; an operator was already defined.', { + index: p[A.FIELDS.START_POS], + }); + ((s.operator = s.operator ? s.operator + m : m), (f = "operator"), (d = !1)); + break; + case T.comment: + if (f) + if (d || (b && b[A.FIELDS.TYPE] === T.space) || f === "insensitive") { + var de = (0, Y.getProp)(s, "spaces", f, "after") || "", + De = (0, Y.getProp)(s, "raws", "spaces", f, "after") || de; + ((0, Y.ensureObject)(s, "raws", "spaces", f), + (s.raws.spaces[f].after = De + m)); + } else { + var ee = s[f] || "", + oe = (0, Y.getProp)(s, "raws", f) || ee; + ((0, Y.ensureObject)(s, "raws"), (s.raws[f] = oe + m)); + } + else c = c + m; + break; + default: + return this.error('Unexpected "' + m + '" found.', { index: p[A.FIELDS.START_POS] }); + } + o++; + } + (Bt(s, "attribute"), Bt(s, "namespace"), this.newNode(new kp.default(s)), this.position++); + }), + (e.parseWhitespaceEquivalentTokens = function (i) { + i < 0 && (i = this.tokens.length); + var n = this.position, + a = [], + s = "", + o = void 0; + do + if (Pa[this.currToken[A.FIELDS.TYPE]]) this.options.lossy || (s += this.content()); + else if (this.currToken[A.FIELDS.TYPE] === T.comment) { + var u = {}; + (s && ((u.before = s), (s = "")), + (o = new xp.default({ + value: this.content(), + source: Mt(this.currToken), + sourceIndex: this.currToken[A.FIELDS.START_POS], + spaces: u, + })), + a.push(o)); + } + while (++this.position < i); + if (s) { + if (o) o.spaces.after = s; + else if (!this.options.lossy) { + var c = this.tokens[n], + f = this.tokens[this.position - 1]; + a.push( + new Oa.default({ + value: "", + source: kt( + c[A.FIELDS.START_LINE], + c[A.FIELDS.START_COL], + f[A.FIELDS.END_LINE], + f[A.FIELDS.END_COL] + ), + sourceIndex: c[A.FIELDS.START_POS], + spaces: { before: s, after: "" }, + }) + ); + } + } + return a; + }), + (e.convertWhitespaceNodesToSpace = function (i, n) { + var a = this; + n === void 0 && (n = !1); + var s = "", + o = ""; + (i.forEach(function (c) { + var f = a.lossySpace(c.spaces.before, n), + d = a.lossySpace(c.rawSpaceBefore, n); + ((s += f + a.lossySpace(c.spaces.after, n && f.length === 0)), + (o += f + c.value + a.lossySpace(c.rawSpaceAfter, n && d.length === 0))); + }), + o === s && (o = void 0)); + var u = { space: s, rawSpace: o }; + return u; + }), + (e.isNamedCombinator = function (i) { + return ( + i === void 0 && (i = this.position), + this.tokens[i + 0] && + this.tokens[i + 0][A.FIELDS.TYPE] === T.slash && + this.tokens[i + 1] && + this.tokens[i + 1][A.FIELDS.TYPE] === T.word && + this.tokens[i + 2] && + this.tokens[i + 2][A.FIELDS.TYPE] === T.slash + ); + }), + (e.namedCombinator = function () { + if (this.isNamedCombinator()) { + var i = this.content(this.tokens[this.position + 1]), + n = (0, Y.unesc)(i).toLowerCase(), + a = {}; + n !== i && (a.value = "/" + i + "/"); + var s = new Ea.default({ + value: "/" + n + "/", + source: kt( + this.currToken[A.FIELDS.START_LINE], + this.currToken[A.FIELDS.START_COL], + this.tokens[this.position + 2][A.FIELDS.END_LINE], + this.tokens[this.position + 2][A.FIELDS.END_COL] + ), + sourceIndex: this.currToken[A.FIELDS.START_POS], + raws: a, + }); + return ((this.position = this.position + 3), s); + } else this.unexpected(); + }), + (e.combinator = function () { + var i = this; + if (this.content() === "|") return this.namespace(); + var n = this.locateNextMeaningfulToken(this.position); + if (n < 0 || this.tokens[n][A.FIELDS.TYPE] === T.comma) { + var a = this.parseWhitespaceEquivalentTokens(n); + if (a.length > 0) { + var s = this.current.last; + if (s) { + var o = this.convertWhitespaceNodesToSpace(a), + u = o.space, + c = o.rawSpace; + (c !== void 0 && (s.rawSpaceAfter += c), (s.spaces.after += u)); + } else + a.forEach(function (E) { + return i.newNode(E); + }); + } + return; + } + var f = this.currToken, + d = void 0; + n > this.position && (d = this.parseWhitespaceEquivalentTokens(n)); + var p; + if ( + (this.isNamedCombinator() + ? (p = this.namedCombinator()) + : this.currToken[A.FIELDS.TYPE] === T.combinator + ? ((p = new Ea.default({ + value: this.content(), + source: Mt(this.currToken), + sourceIndex: this.currToken[A.FIELDS.START_POS], + })), + this.position++) + : Pa[this.currToken[A.FIELDS.TYPE]] || d || this.unexpected(), + p) + ) { + if (d) { + var m = this.convertWhitespaceNodesToSpace(d), + b = m.space, + x = m.rawSpace; + ((p.spaces.before = b), (p.rawSpaceBefore = x)); + } + } else { + var y = this.convertWhitespaceNodesToSpace(d, !0), + w = y.space, + k = y.rawSpace; + k || (k = w); + var S = {}, + _ = { spaces: {} }; + (w.endsWith(" ") && k.endsWith(" ") + ? ((S.before = w.slice(0, w.length - 1)), (_.spaces.before = k.slice(0, k.length - 1))) + : w.startsWith(" ") && k.startsWith(" ") + ? ((S.after = w.slice(1)), (_.spaces.after = k.slice(1))) + : (_.value = k), + (p = new Ea.default({ + value: " ", + source: Da(f, this.tokens[this.position - 1]), + sourceIndex: f[A.FIELDS.START_POS], + spaces: S, + raws: _, + }))); + } + return ( + this.currToken && + this.currToken[A.FIELDS.TYPE] === T.space && + ((p.spaces.after = this.optionalSpace(this.content())), this.position++), + this.newNode(p) + ); + }), + (e.comma = function () { + if (this.position === this.tokens.length - 1) { + ((this.root.trailingComma = !0), this.position++); + return; + } + this.current._inferEndPosition(); + var i = new _a.default({ source: { start: Ap(this.tokens[this.position + 1]) } }); + (this.current.parent.append(i), (this.current = i), this.position++); + }), + (e.comment = function () { + var i = this.currToken; + (this.newNode( + new xp.default({ value: this.content(), source: Mt(i), sourceIndex: i[A.FIELDS.START_POS] }) + ), + this.position++); + }), + (e.error = function (i, n) { + throw this.root.error(i, n); + }), + (e.missingBackslash = function () { + return this.error("Expected a backslash preceding the semicolon.", { + index: this.currToken[A.FIELDS.START_POS], + }); + }), + (e.missingParenthesis = function () { + return this.expected("opening parenthesis", this.currToken[A.FIELDS.START_POS]); + }), + (e.missingSquareBracket = function () { + return this.expected("opening square bracket", this.currToken[A.FIELDS.START_POS]); + }), + (e.unexpected = function () { + return this.error( + "Unexpected '" + this.content() + "'. Escaping special characters with \\ may help.", + this.currToken[A.FIELDS.START_POS] + ); + }), + (e.unexpectedPipe = function () { + return this.error("Unexpected '|'.", this.currToken[A.FIELDS.START_POS]); + }), + (e.namespace = function () { + var i = (this.prevToken && this.content(this.prevToken)) || !0; + if (this.nextToken[A.FIELDS.TYPE] === T.word) return (this.position++, this.word(i)); + if (this.nextToken[A.FIELDS.TYPE] === T.asterisk) return (this.position++, this.universal(i)); + this.unexpectedPipe(); + }), + (e.nesting = function () { + if (this.nextToken) { + var i = this.content(this.nextToken); + if (i === "|") { + this.position++; + return; + } + } + var n = this.currToken; + (this.newNode( + new Lk.default({ value: this.content(), source: Mt(n), sourceIndex: n[A.FIELDS.START_POS] }) + ), + this.position++); + }), + (e.parentheses = function () { + var i = this.current.last, + n = 1; + if ((this.position++, i && i.type === $k.PSEUDO)) { + var a = new _a.default({ source: { start: Ap(this.tokens[this.position - 1]) } }), + s = this.current; + for (i.append(a), this.current = a; this.position < this.tokens.length && n; ) + (this.currToken[A.FIELDS.TYPE] === T.openParenthesis && n++, + this.currToken[A.FIELDS.TYPE] === T.closeParenthesis && n--, + n + ? this.parse() + : ((this.current.source.end = _p(this.currToken)), + (this.current.parent.source.end = _p(this.currToken)), + this.position++)); + this.current = s; + } else { + for (var o = this.currToken, u = "(", c; this.position < this.tokens.length && n; ) + (this.currToken[A.FIELDS.TYPE] === T.openParenthesis && n++, + this.currToken[A.FIELDS.TYPE] === T.closeParenthesis && n--, + (c = this.currToken), + (u += this.parseParenthesisToken(this.currToken)), + this.position++); + i + ? i.appendToPropertyAndEscape("value", u, u) + : this.newNode( + new Oa.default({ + value: u, + source: kt( + o[A.FIELDS.START_LINE], + o[A.FIELDS.START_COL], + c[A.FIELDS.END_LINE], + c[A.FIELDS.END_COL] + ), + sourceIndex: o[A.FIELDS.START_POS], + }) + ); + } + if (n) return this.expected("closing parenthesis", this.currToken[A.FIELDS.START_POS]); + }), + (e.pseudo = function () { + for ( + var i = this, n = "", a = this.currToken; + this.currToken && this.currToken[A.FIELDS.TYPE] === T.colon; + ) + ((n += this.content()), this.position++); + if (!this.currToken) return this.expected(["pseudo-class", "pseudo-element"], this.position - 1); + if (this.currToken[A.FIELDS.TYPE] === T.word) + this.splitWord(!1, function (s, o) { + ((n += s), + i.newNode( + new Bk.default({ + value: n, + source: Da(a, i.currToken), + sourceIndex: a[A.FIELDS.START_POS], + }) + ), + o > 1 && + i.nextToken && + i.nextToken[A.FIELDS.TYPE] === T.openParenthesis && + i.error("Misplaced parenthesis.", { index: i.nextToken[A.FIELDS.START_POS] })); + }); + else return this.expected(["pseudo-class", "pseudo-element"], this.currToken[A.FIELDS.START_POS]); + }), + (e.space = function () { + var i = this.content(); + this.position === 0 || + this.prevToken[A.FIELDS.TYPE] === T.comma || + this.prevToken[A.FIELDS.TYPE] === T.openParenthesis || + this.current.nodes.every(function (n) { + return n.type === "comment"; + }) + ? ((this.spaces = this.optionalSpace(i)), this.position++) + : this.position === this.tokens.length - 1 || + this.nextToken[A.FIELDS.TYPE] === T.comma || + this.nextToken[A.FIELDS.TYPE] === T.closeParenthesis + ? ((this.current.last.spaces.after = this.optionalSpace(i)), this.position++) + : this.combinator(); + }), + (e.string = function () { + var i = this.currToken; + (this.newNode( + new Oa.default({ value: this.content(), source: Mt(i), sourceIndex: i[A.FIELDS.START_POS] }) + ), + this.position++); + }), + (e.universal = function (i) { + var n = this.nextToken; + if (n && this.content(n) === "|") return (this.position++, this.namespace()); + var a = this.currToken; + (this.newNode( + new Fk.default({ value: this.content(), source: Mt(a), sourceIndex: a[A.FIELDS.START_POS] }), + i + ), + this.position++); + }), + (e.splitWord = function (i, n) { + for ( + var a = this, s = this.nextToken, o = this.content(); + s && ~[T.dollar, T.caret, T.equals, T.word].indexOf(s[A.FIELDS.TYPE]); + ) { + this.position++; + var u = this.content(); + if (((o += u), u.lastIndexOf("\\") === u.length - 1)) { + var c = this.nextToken; + c && + c[A.FIELDS.TYPE] === T.space && + ((o += this.requiredSpace(this.content(c))), this.position++); + } + s = this.nextToken; + } + var f = Ia(o, ".").filter(function (b) { + var x = o[b - 1] === "\\", + y = /^\d+\.\d+%$/.test(o); + return !x && !y; + }), + d = Ia(o, "#").filter(function (b) { + return o[b - 1] !== "\\"; + }), + p = Ia(o, "#{"); + p.length && + (d = d.filter(function (b) { + return !~p.indexOf(b); + })); + var m = (0, Nk.default)(Vk([0].concat(f, d))); + (m.forEach(function (b, x) { + var y = m[x + 1] || o.length, + w = o.slice(b, y); + if (x === 0 && n) return n.call(a, w, m.length); + var k, + S = a.currToken, + _ = S[A.FIELDS.START_POS] + m[x], + E = kt(S[1], S[2] + b, S[3], S[2] + (y - 1)); + if (~f.indexOf(b)) { + var I = { value: w.slice(1), source: E, sourceIndex: _ }; + k = new qk.default(Bt(I, "value")); + } else if (~d.indexOf(b)) { + var q = { value: w.slice(1), source: E, sourceIndex: _ }; + k = new Rk.default(Bt(q, "value")); + } else { + var R = { value: w, source: E, sourceIndex: _ }; + (Bt(R, "value"), (k = new Mk.default(R))); + } + (a.newNode(k, i), (i = null)); + }), + this.position++); + }), + (e.word = function (i) { + var n = this.nextToken; + return n && this.content(n) === "|" ? (this.position++, this.namespace()) : this.splitWord(i); + }), + (e.loop = function () { + for (; this.position < this.tokens.length; ) this.parse(!0); + return (this.current._inferEndPosition(), this.root); + }), + (e.parse = function (i) { + switch (this.currToken[A.FIELDS.TYPE]) { + case T.space: + this.space(); + break; + case T.comment: + this.comment(); + break; + case T.openParenthesis: + this.parentheses(); + break; + case T.closeParenthesis: + i && this.missingParenthesis(); + break; + case T.openSquare: + this.attribute(); + break; + case T.dollar: + case T.caret: + case T.equals: + case T.word: + this.word(); + break; + case T.colon: + this.pseudo(); + break; + case T.comma: + this.comma(); + break; + case T.asterisk: + this.universal(); + break; + case T.ampersand: + this.nesting(); + break; + case T.slash: + case T.combinator: + this.combinator(); + break; + case T.str: + this.string(); + break; + case T.closeSquare: + this.missingSquareBracket(); + case T.semicolon: + this.missingBackslash(); + default: + this.unexpected(); + } + }), + (e.expected = function (i, n, a) { + if (Array.isArray(i)) { + var s = i.pop(); + i = i.join(", ") + " or " + s; + } + var o = /^[aeiou]/.test(i[0]) ? "an" : "a"; + return a + ? this.error("Expected " + o + " " + i + ', found "' + a + '" instead.', { index: n }) + : this.error("Expected " + o + " " + i + ".", { index: n }); + }), + (e.requiredSpace = function (i) { + return this.options.lossy ? " " : i; + }), + (e.optionalSpace = function (i) { + return this.options.lossy ? "" : i; + }), + (e.lossySpace = function (i, n) { + return this.options.lossy ? (n ? " " : "") : i; + }), + (e.parseParenthesisToken = function (i) { + var n = this.content(i); + return i[A.FIELDS.TYPE] === T.space ? this.requiredSpace(n) : n; + }), + (e.newNode = function (i, n) { + return ( + n && + (/^ +$/.test(n) && + (this.options.lossy || (this.spaces = (this.spaces || "") + n), (n = !0)), + (i.namespace = n), + Bt(i, "namespace")), + this.spaces && ((i.spaces.before = this.spaces), (this.spaces = "")), + this.current.append(i) + ); + }), + (e.content = function (i) { + return ( + i === void 0 && (i = this.currToken), + this.css.slice(i[A.FIELDS.START_POS], i[A.FIELDS.END_POS]) + ); + }), + (e.locateNextMeaningfulToken = function (i) { + i === void 0 && (i = this.position + 1); + for (var n = i; n < this.tokens.length; ) + if (jk[this.tokens[n][A.FIELDS.TYPE]]) { + n++; + continue; + } else return n; + return -1; + }), + zk(r, [ + { + key: "currToken", + get: function () { + return this.tokens[this.position]; + }, + }, + { + key: "nextToken", + get: function () { + return this.tokens[this.position + 1]; + }, + }, + { + key: "prevToken", + get: function () { + return this.tokens[this.position - 1]; + }, + }, + ]), + r + ); + })(); + Hr.default = Uk; + Op.exports = Hr.default; + }); + var Pp = v((Yr, Tp) => { + l(); + ("use strict"); + Yr.__esModule = !0; + Yr.default = void 0; + var Wk = Gk(Ep()); + function Gk(r) { + return r && r.__esModule ? r : { default: r }; + } + var Hk = (function () { + function r(t, i) { + ((this.func = t || function () {}), (this.funcRes = null), (this.options = i)); + } + var e = r.prototype; + return ( + (e._shouldUpdateSelector = function (i, n) { + n === void 0 && (n = {}); + var a = Object.assign({}, this.options, n); + return a.updateSelector === !1 ? !1 : typeof i != "string"; + }), + (e._isLossy = function (i) { + i === void 0 && (i = {}); + var n = Object.assign({}, this.options, i); + return n.lossless === !1; + }), + (e._root = function (i, n) { + n === void 0 && (n = {}); + var a = new Wk.default(i, this._parseOptions(n)); + return a.root; + }), + (e._parseOptions = function (i) { + return { lossy: this._isLossy(i) }; + }), + (e._run = function (i, n) { + var a = this; + return ( + n === void 0 && (n = {}), + new Promise(function (s, o) { + try { + var u = a._root(i, n); + Promise.resolve(a.func(u)) + .then(function (c) { + var f = void 0; + return ( + a._shouldUpdateSelector(i, n) && ((f = u.toString()), (i.selector = f)), + { transform: c, root: u, string: f } + ); + }) + .then(s, o); + } catch (c) { + o(c); + return; + } + }) + ); + }), + (e._runSync = function (i, n) { + n === void 0 && (n = {}); + var a = this._root(i, n), + s = this.func(a); + if (s && typeof s.then == "function") + throw new Error("Selector processor returned a promise to a synchronous call."); + var o = void 0; + return ( + n.updateSelector && typeof i != "string" && ((o = a.toString()), (i.selector = o)), + { transform: s, root: a, string: o } + ); + }), + (e.ast = function (i, n) { + return this._run(i, n).then(function (a) { + return a.root; + }); + }), + (e.astSync = function (i, n) { + return this._runSync(i, n).root; + }), + (e.transform = function (i, n) { + return this._run(i, n).then(function (a) { + return a.transform; + }); + }), + (e.transformSync = function (i, n) { + return this._runSync(i, n).transform; + }), + (e.process = function (i, n) { + return this._run(i, n).then(function (a) { + return a.string || a.root.toString(); + }); + }), + (e.processSync = function (i, n) { + var a = this._runSync(i, n); + return a.string || a.root.toString(); + }), + r + ); + })(); + Yr.default = Hk; + Tp.exports = Yr.default; + }); + var Dp = v((G) => { + l(); + ("use strict"); + G.__esModule = !0; + G.universal = + G.tag = + G.string = + G.selector = + G.root = + G.pseudo = + G.nesting = + G.id = + G.comment = + G.combinator = + G.className = + G.attribute = + void 0; + var Yk = ve(ya()), + Qk = ve(ea()), + Jk = ve(xa()), + Xk = ve(ra()), + Kk = ve(na()), + Zk = ve(Sa()), + eS = ve(ca()), + tS = ve(Qs()), + rS = ve(Xs()), + iS = ve(ua()), + nS = ve(oa()), + sS = ve(ba()); + function ve(r) { + return r && r.__esModule ? r : { default: r }; + } + var aS = function (e) { + return new Yk.default(e); + }; + G.attribute = aS; + var oS = function (e) { + return new Qk.default(e); + }; + G.className = oS; + var lS = function (e) { + return new Jk.default(e); + }; + G.combinator = lS; + var uS = function (e) { + return new Xk.default(e); + }; + G.comment = uS; + var fS = function (e) { + return new Kk.default(e); + }; + G.id = fS; + var cS = function (e) { + return new Zk.default(e); + }; + G.nesting = cS; + var pS = function (e) { + return new eS.default(e); + }; + G.pseudo = pS; + var dS = function (e) { + return new tS.default(e); + }; + G.root = dS; + var hS = function (e) { + return new rS.default(e); + }; + G.selector = hS; + var mS = function (e) { + return new iS.default(e); + }; + G.string = mS; + var gS = function (e) { + return new nS.default(e); + }; + G.tag = gS; + var yS = function (e) { + return new sS.default(e); + }; + G.universal = yS; + }); + var Mp = v(($) => { + l(); + ("use strict"); + $.__esModule = !0; + $.isComment = $.isCombinator = $.isClassName = $.isAttribute = void 0; + $.isContainer = TS; + $.isIdentifier = void 0; + $.isNamespace = PS; + $.isNesting = void 0; + $.isNode = qa; + $.isPseudo = void 0; + $.isPseudoClass = ES; + $.isPseudoElement = Rp; + $.isUniversal = $.isTag = $.isString = $.isSelector = $.isRoot = void 0; + var Q = ne(), + fe, + wS = + ((fe = {}), + (fe[Q.ATTRIBUTE] = !0), + (fe[Q.CLASS] = !0), + (fe[Q.COMBINATOR] = !0), + (fe[Q.COMMENT] = !0), + (fe[Q.ID] = !0), + (fe[Q.NESTING] = !0), + (fe[Q.PSEUDO] = !0), + (fe[Q.ROOT] = !0), + (fe[Q.SELECTOR] = !0), + (fe[Q.STRING] = !0), + (fe[Q.TAG] = !0), + (fe[Q.UNIVERSAL] = !0), + fe); + function qa(r) { + return typeof r == "object" && wS[r.type]; + } + function xe(r, e) { + return qa(e) && e.type === r; + } + var Ip = xe.bind(null, Q.ATTRIBUTE); + $.isAttribute = Ip; + var bS = xe.bind(null, Q.CLASS); + $.isClassName = bS; + var vS = xe.bind(null, Q.COMBINATOR); + $.isCombinator = vS; + var xS = xe.bind(null, Q.COMMENT); + $.isComment = xS; + var kS = xe.bind(null, Q.ID); + $.isIdentifier = kS; + var SS = xe.bind(null, Q.NESTING); + $.isNesting = SS; + var Ra = xe.bind(null, Q.PSEUDO); + $.isPseudo = Ra; + var CS = xe.bind(null, Q.ROOT); + $.isRoot = CS; + var AS = xe.bind(null, Q.SELECTOR); + $.isSelector = AS; + var _S = xe.bind(null, Q.STRING); + $.isString = _S; + var qp = xe.bind(null, Q.TAG); + $.isTag = qp; + var OS = xe.bind(null, Q.UNIVERSAL); + $.isUniversal = OS; + function Rp(r) { + return ( + Ra(r) && + r.value && + (r.value.startsWith("::") || + r.value.toLowerCase() === ":before" || + r.value.toLowerCase() === ":after" || + r.value.toLowerCase() === ":first-letter" || + r.value.toLowerCase() === ":first-line") + ); + } + function ES(r) { + return Ra(r) && !Rp(r); + } + function TS(r) { + return !!(qa(r) && r.walk); + } + function PS(r) { + return Ip(r) || qp(r); + } + }); + var Bp = v((Ee) => { + l(); + ("use strict"); + Ee.__esModule = !0; + var Ma = ne(); + Object.keys(Ma).forEach(function (r) { + r === "default" || r === "__esModule" || (r in Ee && Ee[r] === Ma[r]) || (Ee[r] = Ma[r]); + }); + var Ba = Dp(); + Object.keys(Ba).forEach(function (r) { + r === "default" || r === "__esModule" || (r in Ee && Ee[r] === Ba[r]) || (Ee[r] = Ba[r]); + }); + var Fa = Mp(); + Object.keys(Fa).forEach(function (r) { + r === "default" || r === "__esModule" || (r in Ee && Ee[r] === Fa[r]) || (Ee[r] = Fa[r]); + }); + }); + var Me = v((Qr, Lp) => { + l(); + ("use strict"); + Qr.__esModule = !0; + Qr.default = void 0; + var DS = RS(Pp()), + IS = qS(Bp()); + function Fp(r) { + if (typeof WeakMap != "function") return null; + var e = new WeakMap(), + t = new WeakMap(); + return (Fp = function (n) { + return n ? t : e; + })(r); + } + function qS(r, e) { + if (!e && r && r.__esModule) return r; + if (r === null || (typeof r != "object" && typeof r != "function")) return { default: r }; + var t = Fp(e); + if (t && t.has(r)) return t.get(r); + var i = {}, + n = Object.defineProperty && Object.getOwnPropertyDescriptor; + for (var a in r) + if (a !== "default" && Object.prototype.hasOwnProperty.call(r, a)) { + var s = n ? Object.getOwnPropertyDescriptor(r, a) : null; + s && (s.get || s.set) ? Object.defineProperty(i, a, s) : (i[a] = r[a]); + } + return ((i.default = r), t && t.set(r, i), i); + } + function RS(r) { + return r && r.__esModule ? r : { default: r }; + } + var La = function (e) { + return new DS.default(e); + }; + Object.assign(La, IS); + delete La.__esModule; + var MS = La; + Qr.default = MS; + Lp.exports = Qr.default; + }); + function Ge(r) { + return ["fontSize", "outline"].includes(r) + ? (e) => (typeof e == "function" && (e = e({})), Array.isArray(e) && (e = e[0]), e) + : r === "fontFamily" + ? (e) => { + typeof e == "function" && (e = e({})); + let t = Array.isArray(e) && ie(e[1]) ? e[0] : e; + return Array.isArray(t) ? t.join(", ") : t; + } + : [ + "boxShadow", + "transitionProperty", + "transitionDuration", + "transitionDelay", + "transitionTimingFunction", + "backgroundImage", + "backgroundSize", + "backgroundColor", + "cursor", + "animation", + ].includes(r) + ? (e) => (typeof e == "function" && (e = e({})), Array.isArray(e) && (e = e.join(", ")), e) + : ["gridTemplateColumns", "gridTemplateRows", "objectPosition"].includes(r) + ? (e) => ( + typeof e == "function" && (e = e({})), + typeof e == "string" && (e = j.list.comma(e).join(" ")), + e + ) + : (e, t = {}) => (typeof e == "function" && (e = e(t)), e); + } + var Jr = C(() => { + l(); + st(); + At(); + }); + var Wp = v((PT, Va) => { + l(); + var { Rule: Np, AtRule: BS } = ge(), + $p = Me(); + function Na(r, e) { + let t; + try { + $p((i) => { + t = i; + }).processSync(r); + } catch (i) { + throw r.includes(":") ? (e ? e.error("Missed semicolon") : i) : e ? e.error(i.message) : i; + } + return t.at(0); + } + function zp(r, e) { + let t = !1; + return ( + r.each((i) => { + if (i.type === "nesting") { + let n = e.clone({}); + (i.value !== "&" ? i.replaceWith(Na(i.value.replace("&", n.toString()))) : i.replaceWith(n), + (t = !0)); + } else "nodes" in i && i.nodes && zp(i, e) && (t = !0); + }), + t + ); + } + function jp(r, e) { + let t = []; + return ( + r.selectors.forEach((i) => { + let n = Na(i, r); + e.selectors.forEach((a) => { + if (!a) return; + let s = Na(a, e); + (zp(s, n) || (s.prepend($p.combinator({ value: " " })), s.prepend(n.clone({}))), + t.push(s.toString())); + }); + }), + t + ); + } + function cn(r, e) { + let t = r.prev(); + for (e.after(r); t && t.type === "comment"; ) { + let i = t.prev(); + (e.after(t), (t = i)); + } + return r; + } + function FS(r) { + return function e(t, i, n, a = n) { + let s = []; + if ( + (i.each((o) => { + o.type === "rule" && n + ? a && (o.selectors = jp(t, o)) + : o.type === "atrule" && o.nodes + ? r[o.name] + ? e(t, o, a) + : i[za] !== !1 && s.push(o) + : s.push(o); + }), + n && s.length) + ) { + let o = t.clone({ nodes: [] }); + for (let u of s) o.append(u); + i.prepend(o); + } + }; + } + function $a(r, e, t) { + let i = new Np({ selector: r, nodes: [] }); + return (i.append(e), t.after(i), i); + } + function Vp(r, e) { + let t = {}; + for (let i of r) t[i] = !0; + if (e) for (let i of e) t[i.replace(/^@/, "")] = !0; + return t; + } + function LS(r) { + r = r.trim(); + let e = r.match(/^\((.*)\)$/); + if (!e) return { type: "basic", selector: r }; + let t = e[1].match(/^(with(?:out)?):(.+)$/); + if (t) { + let i = t[1] === "with", + n = Object.fromEntries( + t[2] + .trim() + .split(/\s+/) + .map((s) => [s, !0]) + ); + if (i && n.all) return { type: "noop" }; + let a = (s) => !!n[s]; + return ( + n.all ? (a = () => !0) : i && (a = (s) => (s === "all" ? !1 : !n[s])), + { type: "withrules", escapes: a } + ); + } + return { type: "unknown" }; + } + function NS(r) { + let e = [], + t = r.parent; + for (; t && t instanceof BS; ) (e.push(t), (t = t.parent)); + return e; + } + function $S(r) { + let e = r[Up]; + if (!e) r.after(r.nodes); + else { + let t = r.nodes, + i, + n = -1, + a, + s, + o, + u = NS(r); + if ( + (u.forEach((c, f) => { + if (e(c.name)) ((i = c), (n = f), (s = o)); + else { + let d = o; + ((o = c.clone({ nodes: [] })), d && o.append(d), (a = a || o)); + } + }), + i ? (s ? (a.append(t), i.after(s)) : i.after(t)) : r.after(t), + r.next() && i) + ) { + let c; + (u.slice(0, n + 1).forEach((f, d, p) => { + let m = c; + ((c = f.clone({ nodes: [] })), m && c.append(m)); + let b = [], + y = (p[d - 1] || r).next(); + for (; y; ) (b.push(y), (y = y.next())); + c.append(b); + }), + c && (s || t[t.length - 1]).after(c)); + } + } + r.remove(); + } + var za = Symbol("rootRuleMergeSel"), + Up = Symbol("rootRuleEscapes"); + function zS(r) { + let { params: e } = r, + { type: t, selector: i, escapes: n } = LS(e); + if (t === "unknown") throw r.error(`Unknown @${r.name} parameter ${JSON.stringify(e)}`); + if (t === "basic" && i) { + let a = new Np({ selector: i, nodes: r.nodes }); + (r.removeAll(), r.append(a)); + } + ((r[Up] = n), (r[za] = n ? !n("all") : t === "noop")); + } + var ja = Symbol("hasRootRule"); + Va.exports = (r = {}) => { + let e = Vp(["media", "supports", "layer", "container"], r.bubble), + t = FS(e), + i = Vp(["document", "font-face", "keyframes", "-webkit-keyframes", "-moz-keyframes"], r.unwrap), + n = (r.rootRuleName || "at-root").replace(/^@/, ""), + a = r.preserveEmpty; + return { + postcssPlugin: "postcss-nested", + Once(s) { + s.walkAtRules(n, (o) => { + (zS(o), (s[ja] = !0)); + }); + }, + Rule(s) { + let o = !1, + u = s, + c = !1, + f = []; + (s.each((d) => { + d.type === "rule" + ? (f.length && ((u = $a(s.selector, f, u)), (f = [])), + (c = !0), + (o = !0), + (d.selectors = jp(s, d)), + (u = cn(d, u))) + : d.type === "atrule" + ? (f.length && ((u = $a(s.selector, f, u)), (f = [])), + d.name === n + ? ((o = !0), t(s, d, !0, d[za]), (u = cn(d, u))) + : e[d.name] + ? ((c = !0), (o = !0), t(s, d, !0), (u = cn(d, u))) + : i[d.name] + ? ((c = !0), (o = !0), t(s, d, !1), (u = cn(d, u))) + : c && f.push(d)) + : d.type === "decl" && c && f.push(d); + }), + f.length && (u = $a(s.selector, f, u)), + o && a !== !0 && ((s.raws.semicolon = !0), s.nodes.length === 0 && s.remove())); + }, + RootExit(s) { + s[ja] && (s.walkAtRules(n, $S), (s[ja] = !1)); + }, + }; + }; + Va.exports.postcss = !0; + }); + var Qp = v((DT, Yp) => { + l(); + ("use strict"); + var Gp = /-(\w|$)/g, + Hp = (r, e) => e.toUpperCase(), + jS = (r) => ( + (r = r.toLowerCase()), + r === "float" ? "cssFloat" : r.startsWith("-ms-") ? r.substr(1).replace(Gp, Hp) : r.replace(Gp, Hp) + ); + Yp.exports = jS; + }); + var Ga = v((IT, Jp) => { + l(); + var VS = Qp(), + US = { + boxFlex: !0, + boxFlexGroup: !0, + columnCount: !0, + flex: !0, + flexGrow: !0, + flexPositive: !0, + flexShrink: !0, + flexNegative: !0, + fontWeight: !0, + lineClamp: !0, + lineHeight: !0, + opacity: !0, + order: !0, + orphans: !0, + tabSize: !0, + widows: !0, + zIndex: !0, + zoom: !0, + fillOpacity: !0, + strokeDashoffset: !0, + strokeOpacity: !0, + strokeWidth: !0, + }; + function Ua(r) { + return typeof r.nodes == "undefined" ? !0 : Wa(r); + } + function Wa(r) { + let e, + t = {}; + return ( + r.each((i) => { + if (i.type === "atrule") + ((e = "@" + i.name), + i.params && (e += " " + i.params), + typeof t[e] == "undefined" + ? (t[e] = Ua(i)) + : Array.isArray(t[e]) + ? t[e].push(Ua(i)) + : (t[e] = [t[e], Ua(i)])); + else if (i.type === "rule") { + let n = Wa(i); + if (t[i.selector]) for (let a in n) t[i.selector][a] = n[a]; + else t[i.selector] = n; + } else if (i.type === "decl") { + (i.prop[0] === "-" && i.prop[1] === "-") || (i.parent && i.parent.selector === ":export") + ? (e = i.prop) + : (e = VS(i.prop)); + let n = i.value; + (!isNaN(i.value) && US[e] && (n = parseFloat(i.value)), + i.important && (n += " !important"), + typeof t[e] == "undefined" + ? (t[e] = n) + : Array.isArray(t[e]) + ? t[e].push(n) + : (t[e] = [t[e], n])); + } + }), + t + ); + } + Jp.exports = Wa; + }); + var pn = v((qT, ed) => { + l(); + var Xr = ge(), + Xp = /\s*!important\s*$/i, + WS = { + "box-flex": !0, + "box-flex-group": !0, + "column-count": !0, + flex: !0, + "flex-grow": !0, + "flex-positive": !0, + "flex-shrink": !0, + "flex-negative": !0, + "font-weight": !0, + "line-clamp": !0, + "line-height": !0, + opacity: !0, + order: !0, + orphans: !0, + "tab-size": !0, + widows: !0, + "z-index": !0, + zoom: !0, + "fill-opacity": !0, + "stroke-dashoffset": !0, + "stroke-opacity": !0, + "stroke-width": !0, + }; + function GS(r) { + return r + .replace(/([A-Z])/g, "-$1") + .replace(/^ms-/, "-ms-") + .toLowerCase(); + } + function Kp(r, e, t) { + t === !1 || + t === null || + (e.startsWith("--") || (e = GS(e)), + typeof t == "number" && (t === 0 || WS[e] ? (t = t.toString()) : (t += "px")), + e === "css-float" && (e = "float"), + Xp.test(t) + ? ((t = t.replace(Xp, "")), r.push(Xr.decl({ prop: e, value: t, important: !0 }))) + : r.push(Xr.decl({ prop: e, value: t }))); + } + function Zp(r, e, t) { + let i = Xr.atRule({ name: e[1], params: e[3] || "" }); + (typeof t == "object" && ((i.nodes = []), Ha(t, i)), r.push(i)); + } + function Ha(r, e) { + let t, i, n; + for (t in r) + if (((i = r[t]), !(i === null || typeof i == "undefined"))) + if (t[0] === "@") { + let a = t.match(/@(\S+)(\s+([\W\w]*)\s*)?/); + if (Array.isArray(i)) for (let s of i) Zp(e, a, s); + else Zp(e, a, i); + } else if (Array.isArray(i)) for (let a of i) Kp(e, t, a); + else typeof i == "object" ? ((n = Xr.rule({ selector: t })), Ha(i, n), e.push(n)) : Kp(e, t, i); + } + ed.exports = function (r) { + let e = Xr.root(); + return (Ha(r, e), e); + }; + }); + var Ya = v((RT, td) => { + l(); + var HS = Ga(); + td.exports = function (e) { + return ( + console && + console.warn && + e.warnings().forEach((t) => { + let i = t.plugin || "PostCSS"; + console.warn(i + ": " + t.text); + }), + HS(e.root) + ); + }; + }); + var id = v((MT, rd) => { + l(); + var YS = ge(), + QS = Ya(), + JS = pn(); + rd.exports = function (e) { + let t = YS(e); + return async (i) => { + let n = await t.process(i, { parser: JS, from: void 0 }); + return QS(n); + }; + }; + }); + var sd = v((BT, nd) => { + l(); + var XS = ge(), + KS = Ya(), + ZS = pn(); + nd.exports = function (r) { + let e = XS(r); + return (t) => { + let i = e.process(t, { parser: ZS, from: void 0 }); + return KS(i); + }; + }; + }); + var od = v((FT, ad) => { + l(); + var e2 = Ga(), + t2 = pn(), + r2 = id(), + i2 = sd(); + ad.exports = { objectify: e2, parse: t2, async: r2, sync: i2 }; + }); + var Ft, + ld, + LT, + NT, + $T, + zT, + ud = C(() => { + l(); + ((Ft = X(od())), + (ld = Ft.default), + (LT = Ft.default.objectify), + (NT = Ft.default.parse), + ($T = Ft.default.async), + (zT = Ft.default.sync)); + }); + function Lt(r) { + return Array.isArray(r) + ? r.flatMap((e) => j([(0, fd.default)({ bubble: ["screen"] })]).process(e, { parser: ld }).root.nodes) + : Lt([r]); + } + var fd, + Qa = C(() => { + l(); + st(); + fd = X(Wp()); + ud(); + }); + function Nt(r, e, t = !1) { + if (r === "") return e; + let i = typeof e == "string" ? (0, cd.default)().astSync(e) : e; + return ( + i.walkClasses((n) => { + let a = n.value, + s = t && a.startsWith("-"); + n.value = s ? `-${r}${a.slice(1)}` : `${r}${a}`; + }), + typeof e == "string" ? i.toString() : i + ); + } + var cd, + dn = C(() => { + l(); + cd = X(Me()); + }); + function ce(r) { + let e = pd.default.className(); + return ((e.value = r), wt(e?.raws?.value ?? e.value)); + } + var pd, + $t = C(() => { + l(); + pd = X(Me()); + bi(); + }); + function Ja(r) { + return wt(`.${ce(r)}`); + } + function hn(r, e) { + return Ja(Kr(r, e)); + } + function Kr(r, e) { + return e === "DEFAULT" + ? r + : e === "-" || e === "-DEFAULT" + ? `-${r}` + : e.startsWith("-") + ? `-${r}${e}` + : e.startsWith("/") + ? `${r}${e}` + : `${r}-${e}`; + } + var Xa = C(() => { + l(); + $t(); + bi(); + }); + function P(r, e = [[r, [r]]], { filterDefault: t = !1, ...i } = {}) { + let n = Ge(r); + return function ({ matchUtilities: a, theme: s }) { + for (let o of e) { + let u = Array.isArray(o[0]) ? o : [o]; + a( + u.reduce( + (c, [f, d]) => + Object.assign(c, { + [f]: (p) => + d.reduce( + (m, b) => + Array.isArray(b) + ? Object.assign(m, { [b[0]]: b[1] }) + : Object.assign(m, { [b]: n(p) }), + {} + ), + }), + {} + ), + { + ...i, + values: t + ? Object.fromEntries(Object.entries(s(r) ?? {}).filter(([c]) => c !== "DEFAULT")) + : s(r), + } + ); + } + }; + } + var dd = C(() => { + l(); + Jr(); + }); + function at(r) { + return ( + (r = Array.isArray(r) ? r : [r]), + r + .map((e) => { + let t = e.values.map((i) => + i.raw !== void 0 + ? i.raw + : [i.min && `(min-width: ${i.min})`, i.max && `(max-width: ${i.max})`] + .filter(Boolean) + .join(" and ") + ); + return e.not ? `not all and ${t}` : t; + }) + .join(", ") + ); + } + var mn = C(() => { + l(); + }); + function Ka(r) { + return r.split(f2).map((t) => { + let i = t.trim(), + n = { value: i }, + a = i.split(c2), + s = new Set(); + for (let o of a) + !s.has("DIRECTIONS") && n2.has(o) + ? ((n.direction = o), s.add("DIRECTIONS")) + : !s.has("PLAY_STATES") && s2.has(o) + ? ((n.playState = o), s.add("PLAY_STATES")) + : !s.has("FILL_MODES") && a2.has(o) + ? ((n.fillMode = o), s.add("FILL_MODES")) + : !s.has("ITERATION_COUNTS") && (o2.has(o) || p2.test(o)) + ? ((n.iterationCount = o), s.add("ITERATION_COUNTS")) + : (!s.has("TIMING_FUNCTION") && l2.has(o)) || + (!s.has("TIMING_FUNCTION") && u2.some((u) => o.startsWith(`${u}(`))) + ? ((n.timingFunction = o), s.add("TIMING_FUNCTION")) + : !s.has("DURATION") && hd.test(o) + ? ((n.duration = o), s.add("DURATION")) + : !s.has("DELAY") && hd.test(o) + ? ((n.delay = o), s.add("DELAY")) + : s.has("NAME") + ? (n.unknown || (n.unknown = []), n.unknown.push(o)) + : ((n.name = o), s.add("NAME")); + return n; + }); + } + var n2, + s2, + a2, + o2, + l2, + u2, + f2, + c2, + hd, + p2, + md = C(() => { + l(); + ((n2 = new Set(["normal", "reverse", "alternate", "alternate-reverse"])), + (s2 = new Set(["running", "paused"])), + (a2 = new Set(["none", "forwards", "backwards", "both"])), + (o2 = new Set(["infinite"])), + (l2 = new Set(["linear", "ease", "ease-in", "ease-out", "ease-in-out", "step-start", "step-end"])), + (u2 = ["cubic-bezier", "steps"]), + (f2 = /\,(?![^(]*\))/g), + (c2 = /\ +(?![^(]*\))/g), + (hd = /^(-?[\d.]+m?s)$/), + (p2 = /^(\d+)$/)); + }); + var gd, + re, + yd = C(() => { + l(); + ((gd = (r) => + Object.assign( + {}, + ...Object.entries(r ?? {}).flatMap(([e, t]) => + typeof t == "object" + ? Object.entries(gd(t)).map(([i, n]) => ({ [e + (i === "DEFAULT" ? "" : `-${i}`)]: n })) + : [{ [`${e}`]: t }] + ) + )), + (re = gd)); + }); + var bd, + wd = C(() => { + bd = "3.4.3"; + }); + function ot(r, e = !0) { + return Array.isArray(r) + ? r.map((t) => { + if (e && Array.isArray(t)) throw new Error("The tuple syntax is not supported for `screens`."); + if (typeof t == "string") return { name: t.toString(), not: !1, values: [{ min: t, max: void 0 }] }; + let [i, n] = t; + return ( + (i = i.toString()), + typeof n == "string" + ? { name: i, not: !1, values: [{ min: n, max: void 0 }] } + : Array.isArray(n) + ? { name: i, not: !1, values: n.map((a) => xd(a)) } + : { name: i, not: !1, values: [xd(n)] } + ); + }) + : ot(Object.entries(r ?? {}), !1); + } + function gn(r) { + return r.values.length !== 1 + ? { result: !1, reason: "multiple-values" } + : r.values[0].raw !== void 0 + ? { result: !1, reason: "raw-values" } + : r.values[0].min !== void 0 && r.values[0].max !== void 0 + ? { result: !1, reason: "min-and-max" } + : { result: !0, reason: null }; + } + function vd(r, e, t) { + let i = yn(e, r), + n = yn(t, r), + a = gn(i), + s = gn(n); + if (a.reason === "multiple-values" || s.reason === "multiple-values") + throw new Error( + "Attempted to sort a screen with multiple values. This should never happen. Please open a bug report." + ); + if (a.reason === "raw-values" || s.reason === "raw-values") + throw new Error( + "Attempted to sort a screen with raw values. This should never happen. Please open a bug report." + ); + if (a.reason === "min-and-max" || s.reason === "min-and-max") + throw new Error( + "Attempted to sort a screen with both min and max values. This should never happen. Please open a bug report." + ); + let { min: o, max: u } = i.values[0], + { min: c, max: f } = n.values[0]; + (e.not && ([o, u] = [u, o]), + t.not && ([c, f] = [f, c]), + (o = o === void 0 ? o : parseFloat(o)), + (u = u === void 0 ? u : parseFloat(u)), + (c = c === void 0 ? c : parseFloat(c)), + (f = f === void 0 ? f : parseFloat(f))); + let [d, p] = r === "min" ? [o, c] : [f, u]; + return d - p; + } + function yn(r, e) { + return typeof r == "object" ? r : { name: "arbitrary-screen", values: [{ [e]: r }] }; + } + function xd({ "min-width": r, min: e = r, max: t, raw: i } = {}) { + return { min: e, max: t, raw: i }; + } + var wn = C(() => { + l(); + }); + function bn(r, e) { + r.walkDecls((t) => { + if (e.includes(t.prop)) { + t.remove(); + return; + } + for (let i of e) t.value.includes(`/ var(${i})`) && (t.value = t.value.replace(`/ var(${i})`, "")); + }); + } + var kd = C(() => { + l(); + }); + var H, + Te, + Be, + Fe, + Sd, + Cd = C(() => { + l(); + ze(); + bt(); + st(); + dd(); + mn(); + $t(); + md(); + yd(); + fr(); + ws(); + At(); + Jr(); + wd(); + Oe(); + wn(); + cs(); + kd(); + je(); + dr(); + ei(); + ((H = { + childVariant: ({ addVariant: r }) => { + r("*", "& > *"); + }, + pseudoElementVariants: ({ addVariant: r }) => { + (r("first-letter", "&::first-letter"), + r("first-line", "&::first-line"), + r("marker", [ + ({ container: e }) => (bn(e, ["--tw-text-opacity"]), "& *::marker"), + ({ container: e }) => (bn(e, ["--tw-text-opacity"]), "&::marker"), + ]), + r("selection", ["& *::selection", "&::selection"]), + r("file", "&::file-selector-button"), + r("placeholder", "&::placeholder"), + r("backdrop", "&::backdrop"), + r( + "before", + ({ container: e }) => ( + e.walkRules((t) => { + let i = !1; + (t.walkDecls("content", () => { + i = !0; + }), + i || t.prepend(j.decl({ prop: "content", value: "var(--tw-content)" }))); + }), + "&::before" + ) + ), + r( + "after", + ({ container: e }) => ( + e.walkRules((t) => { + let i = !1; + (t.walkDecls("content", () => { + i = !0; + }), + i || t.prepend(j.decl({ prop: "content", value: "var(--tw-content)" }))); + }), + "&::after" + ) + )); + }, + pseudoClassVariants: ({ addVariant: r, matchVariant: e, config: t, prefix: i }) => { + let n = [ + ["first", "&:first-child"], + ["last", "&:last-child"], + ["only", "&:only-child"], + ["odd", "&:nth-child(odd)"], + ["even", "&:nth-child(even)"], + "first-of-type", + "last-of-type", + "only-of-type", + [ + "visited", + ({ container: s }) => ( + bn(s, ["--tw-text-opacity", "--tw-border-opacity", "--tw-bg-opacity"]), + "&:visited" + ), + ], + "target", + ["open", "&[open]"], + "default", + "checked", + "indeterminate", + "placeholder-shown", + "autofill", + "optional", + "required", + "valid", + "invalid", + "in-range", + "out-of-range", + "read-only", + "empty", + "focus-within", + [ + "hover", + K(t(), "hoverOnlyWhenSupported") + ? "@media (hover: hover) and (pointer: fine) { &:hover }" + : "&:hover", + ], + "focus", + "focus-visible", + "active", + "enabled", + "disabled", + ].map((s) => (Array.isArray(s) ? s : [s, `&:${s}`])); + for (let [s, o] of n) r(s, (u) => (typeof o == "function" ? o(u) : o)); + let a = { + group: (s, { modifier: o }) => + o ? [`:merge(${i(".group")}\\/${ce(o)})`, " &"] : [`:merge(${i(".group")})`, " &"], + peer: (s, { modifier: o }) => + o ? [`:merge(${i(".peer")}\\/${ce(o)})`, " ~ &"] : [`:merge(${i(".peer")})`, " ~ &"], + }; + for (let [s, o] of Object.entries(a)) + e( + s, + (u = "", c) => { + let f = L(typeof u == "function" ? u(c) : u); + f.includes("&") || (f = "&" + f); + let [d, p] = o("", c), + m = null, + b = null, + x = 0; + for (let y = 0; y < f.length; ++y) { + let w = f[y]; + w === "&" + ? (m = y) + : w === "'" || w === '"' + ? (x += 1) + : m !== null && w === " " && !x && (b = y); + } + return ( + m !== null && b === null && (b = f.length), + f.slice(0, m) + d + f.slice(m + 1, b) + p + f.slice(b) + ); + }, + { values: Object.fromEntries(n), [Zr]: { respectPrefix: !1 } } + ); + }, + directionVariants: ({ addVariant: r }) => { + (r("ltr", '&:where([dir="ltr"], [dir="ltr"] *)'), r("rtl", '&:where([dir="rtl"], [dir="rtl"] *)')); + }, + reducedMotionVariants: ({ addVariant: r }) => { + (r("motion-safe", "@media (prefers-reduced-motion: no-preference)"), + r("motion-reduce", "@media (prefers-reduced-motion: reduce)")); + }, + darkVariants: ({ config: r, addVariant: e }) => { + let [t, i = ".dark"] = [].concat(r("darkMode", "media")); + if ( + (t === !1 && + ((t = "media"), + F.warn("darkmode-false", [ + "The `darkMode` option in your Tailwind CSS configuration is set to `false`, which now behaves the same as `media`.", + "Change `darkMode` to `media` or remove it entirely.", + "https://tailwindcss.com/docs/upgrade-guide#remove-dark-mode-configuration", + ])), + t === "variant") + ) { + let n; + if ( + (Array.isArray(i) || typeof i == "function" ? (n = i) : typeof i == "string" && (n = [i]), + Array.isArray(n)) + ) + for (let a of n) + a === ".dark" + ? ((t = !1), + F.warn("darkmode-variant-without-selector", [ + "When using `variant` for `darkMode`, you must provide a selector.", + 'Example: `darkMode: ["variant", ".your-selector &"]`', + ])) + : a.includes("&") || + ((t = !1), + F.warn("darkmode-variant-without-ampersand", [ + "When using `variant` for `darkMode`, your selector must contain `&`.", + 'Example `darkMode: ["variant", ".your-selector &"]`', + ])); + i = n; + } + t === "selector" + ? e("dark", `&:where(${i}, ${i} *)`) + : t === "media" + ? e("dark", "@media (prefers-color-scheme: dark)") + : t === "variant" + ? e("dark", i) + : t === "class" && e("dark", `&:is(${i} *)`); + }, + printVariant: ({ addVariant: r }) => { + r("print", "@media print"); + }, + screenVariants: ({ theme: r, addVariant: e, matchVariant: t }) => { + let i = r("screens") ?? {}, + n = Object.values(i).every((w) => typeof w == "string"), + a = ot(r("screens")), + s = new Set([]); + function o(w) { + return w.match(/(\D+)$/)?.[1] ?? "(none)"; + } + function u(w) { + w !== void 0 && s.add(o(w)); + } + function c(w) { + return (u(w), s.size === 1); + } + for (let w of a) for (let k of w.values) (u(k.min), u(k.max)); + let f = s.size <= 1; + function d(w) { + return Object.fromEntries( + a + .filter((k) => gn(k).result) + .map((k) => { + let { min: S, max: _ } = k.values[0]; + if (w === "min" && S !== void 0) return k; + if (w === "min" && _ !== void 0) return { ...k, not: !k.not }; + if (w === "max" && _ !== void 0) return k; + if (w === "max" && S !== void 0) return { ...k, not: !k.not }; + }) + .map((k) => [k.name, k]) + ); + } + function p(w) { + return (k, S) => vd(w, k.value, S.value); + } + let m = p("max"), + b = p("min"); + function x(w) { + return (k) => { + if (n) + if (f) { + if (typeof k == "string" && !c(k)) + return ( + F.warn("minmax-have-mixed-units", [ + "The `min-*` and `max-*` variants are not supported with a `screens` configuration containing mixed units.", + ]), + [] + ); + } else + return ( + F.warn("mixed-screen-units", [ + "The `min-*` and `max-*` variants are not supported with a `screens` configuration containing mixed units.", + ]), + [] + ); + else + return ( + F.warn("complex-screen-config", [ + "The `min-*` and `max-*` variants are not supported with a `screens` configuration containing objects.", + ]), + [] + ); + return [`@media ${at(yn(k, w))}`]; + }; + } + t("max", x("max"), { sort: m, values: n ? d("max") : {} }); + let y = "min-screens"; + for (let w of a) e(w.name, `@media ${at(w)}`, { id: y, sort: n && f ? b : void 0, value: w }); + t("min", x("min"), { id: y, sort: b }); + }, + supportsVariants: ({ matchVariant: r, theme: e }) => { + r( + "supports", + (t = "") => { + let i = L(t), + n = /^\w*\s*\(/.test(i); + return ( + (i = n ? i.replace(/\b(and|or|not)\b/g, " $1 ") : i), + n + ? `@supports ${i}` + : (i.includes(":") || (i = `${i}: var(--tw)`), + (i.startsWith("(") && i.endsWith(")")) || (i = `(${i})`), + `@supports ${i}`) + ); + }, + { values: e("supports") ?? {} } + ); + }, + hasVariants: ({ matchVariant: r }) => { + (r("has", (e) => `&:has(${L(e)})`, { values: {} }), + r( + "group-has", + (e, { modifier: t }) => + t ? `:merge(.group\\/${t}):has(${L(e)}) &` : `:merge(.group):has(${L(e)}) &`, + { values: {} } + ), + r( + "peer-has", + (e, { modifier: t }) => + t ? `:merge(.peer\\/${t}):has(${L(e)}) ~ &` : `:merge(.peer):has(${L(e)}) ~ &`, + { values: {} } + )); + }, + ariaVariants: ({ matchVariant: r, theme: e }) => { + (r("aria", (t) => `&[aria-${L(t)}]`, { values: e("aria") ?? {} }), + r( + "group-aria", + (t, { modifier: i }) => + i ? `:merge(.group\\/${i})[aria-${L(t)}] &` : `:merge(.group)[aria-${L(t)}] &`, + { values: e("aria") ?? {} } + ), + r( + "peer-aria", + (t, { modifier: i }) => + i ? `:merge(.peer\\/${i})[aria-${L(t)}] ~ &` : `:merge(.peer)[aria-${L(t)}] ~ &`, + { values: e("aria") ?? {} } + )); + }, + dataVariants: ({ matchVariant: r, theme: e }) => { + (r("data", (t) => `&[data-${L(t)}]`, { values: e("data") ?? {} }), + r( + "group-data", + (t, { modifier: i }) => + i ? `:merge(.group\\/${i})[data-${L(t)}] &` : `:merge(.group)[data-${L(t)}] &`, + { values: e("data") ?? {} } + ), + r( + "peer-data", + (t, { modifier: i }) => + i ? `:merge(.peer\\/${i})[data-${L(t)}] ~ &` : `:merge(.peer)[data-${L(t)}] ~ &`, + { values: e("data") ?? {} } + )); + }, + orientationVariants: ({ addVariant: r }) => { + (r("portrait", "@media (orientation: portrait)"), + r("landscape", "@media (orientation: landscape)")); + }, + prefersContrastVariants: ({ addVariant: r }) => { + (r("contrast-more", "@media (prefers-contrast: more)"), + r("contrast-less", "@media (prefers-contrast: less)")); + }, + forcedColorsVariants: ({ addVariant: r }) => { + r("forced-colors", "@media (forced-colors: active)"); + }, + }), + (Te = [ + "translate(var(--tw-translate-x), var(--tw-translate-y))", + "rotate(var(--tw-rotate))", + "skewX(var(--tw-skew-x))", + "skewY(var(--tw-skew-y))", + "scaleX(var(--tw-scale-x))", + "scaleY(var(--tw-scale-y))", + ].join(" ")), + (Be = [ + "var(--tw-blur)", + "var(--tw-brightness)", + "var(--tw-contrast)", + "var(--tw-grayscale)", + "var(--tw-hue-rotate)", + "var(--tw-invert)", + "var(--tw-saturate)", + "var(--tw-sepia)", + "var(--tw-drop-shadow)", + ].join(" ")), + (Fe = [ + "var(--tw-backdrop-blur)", + "var(--tw-backdrop-brightness)", + "var(--tw-backdrop-contrast)", + "var(--tw-backdrop-grayscale)", + "var(--tw-backdrop-hue-rotate)", + "var(--tw-backdrop-invert)", + "var(--tw-backdrop-opacity)", + "var(--tw-backdrop-saturate)", + "var(--tw-backdrop-sepia)", + ].join(" ")), + (Sd = { + preflight: ({ addBase: r }) => { + let e = j.parse( + `*,::after,::before{box-sizing:border-box;border-width:0;border-style:solid;border-color:theme('borderColor.DEFAULT', currentColor)}::after,::before{--tw-content:''}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:theme('fontFamily.sans', ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:theme('fontFamily.sans[1].fontFeatureSettings', normal);font-variation-settings:theme('fontFamily.sans[1].fontVariationSettings', normal);-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:theme('fontFamily.mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:theme('fontFamily.mono[1].fontFeatureSettings', normal);font-variation-settings:theme('fontFamily.mono[1].fontVariationSettings', normal);font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:theme('colors.gray.4', #9ca3af)}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}` + ); + r([ + j.comment({ text: `! tailwindcss v${bd} | MIT License | https://tailwindcss.com` }), + ...e.nodes, + ]); + }, + container: (() => { + function r(t = []) { + return t.flatMap((i) => i.values.map((n) => n.min)).filter((i) => i !== void 0); + } + function e(t, i, n) { + if (typeof n == "undefined") return []; + if (!(typeof n == "object" && n !== null)) + return [{ screen: "DEFAULT", minWidth: 0, padding: n }]; + let a = []; + n.DEFAULT && a.push({ screen: "DEFAULT", minWidth: 0, padding: n.DEFAULT }); + for (let s of t) + for (let o of i) + for (let { min: u } of o.values) + u === s && a.push({ minWidth: s, padding: n[o.name] }); + return a; + } + return function ({ addComponents: t, theme: i }) { + let n = ot(i("container.screens", i("screens"))), + a = r(n), + s = e(a, n, i("container.padding")), + o = (c) => { + let f = s.find((d) => d.minWidth === c); + return f ? { paddingRight: f.padding, paddingLeft: f.padding } : {}; + }, + u = Array.from(new Set(a.slice().sort((c, f) => parseInt(c) - parseInt(f)))).map( + (c) => ({ + [`@media (min-width: ${c})`]: { ".container": { "max-width": c, ...o(c) } }, + }) + ); + t([ + { + ".container": Object.assign( + { width: "100%" }, + i("container.center", !1) ? { marginRight: "auto", marginLeft: "auto" } : {}, + o(0) + ), + }, + ...u, + ]); + }; + })(), + accessibility: ({ addUtilities: r }) => { + r({ + ".sr-only": { + position: "absolute", + width: "1px", + height: "1px", + padding: "0", + margin: "-1px", + overflow: "hidden", + clip: "rect(0, 0, 0, 0)", + whiteSpace: "nowrap", + borderWidth: "0", + }, + ".not-sr-only": { + position: "static", + width: "auto", + height: "auto", + padding: "0", + margin: "0", + overflow: "visible", + clip: "auto", + whiteSpace: "normal", + }, + }); + }, + pointerEvents: ({ addUtilities: r }) => { + r({ + ".pointer-events-none": { "pointer-events": "none" }, + ".pointer-events-auto": { "pointer-events": "auto" }, + }); + }, + visibility: ({ addUtilities: r }) => { + r({ + ".visible": { visibility: "visible" }, + ".invisible": { visibility: "hidden" }, + ".collapse": { visibility: "collapse" }, + }); + }, + position: ({ addUtilities: r }) => { + r({ + ".static": { position: "static" }, + ".fixed": { position: "fixed" }, + ".absolute": { position: "absolute" }, + ".relative": { position: "relative" }, + ".sticky": { position: "sticky" }, + }); + }, + inset: P( + "inset", + [ + ["inset", ["inset"]], + [ + ["inset-x", ["left", "right"]], + ["inset-y", ["top", "bottom"]], + ], + [ + ["start", ["inset-inline-start"]], + ["end", ["inset-inline-end"]], + ["top", ["top"]], + ["right", ["right"]], + ["bottom", ["bottom"]], + ["left", ["left"]], + ], + ], + { supportsNegativeValues: !0 } + ), + isolation: ({ addUtilities: r }) => { + r({ ".isolate": { isolation: "isolate" }, ".isolation-auto": { isolation: "auto" } }); + }, + zIndex: P("zIndex", [["z", ["zIndex"]]], { supportsNegativeValues: !0 }), + order: P("order", void 0, { supportsNegativeValues: !0 }), + gridColumn: P("gridColumn", [["col", ["gridColumn"]]]), + gridColumnStart: P("gridColumnStart", [["col-start", ["gridColumnStart"]]]), + gridColumnEnd: P("gridColumnEnd", [["col-end", ["gridColumnEnd"]]]), + gridRow: P("gridRow", [["row", ["gridRow"]]]), + gridRowStart: P("gridRowStart", [["row-start", ["gridRowStart"]]]), + gridRowEnd: P("gridRowEnd", [["row-end", ["gridRowEnd"]]]), + float: ({ addUtilities: r }) => { + r({ + ".float-start": { float: "inline-start" }, + ".float-end": { float: "inline-end" }, + ".float-right": { float: "right" }, + ".float-left": { float: "left" }, + ".float-none": { float: "none" }, + }); + }, + clear: ({ addUtilities: r }) => { + r({ + ".clear-start": { clear: "inline-start" }, + ".clear-end": { clear: "inline-end" }, + ".clear-left": { clear: "left" }, + ".clear-right": { clear: "right" }, + ".clear-both": { clear: "both" }, + ".clear-none": { clear: "none" }, + }); + }, + margin: P( + "margin", + [ + ["m", ["margin"]], + [ + ["mx", ["margin-left", "margin-right"]], + ["my", ["margin-top", "margin-bottom"]], + ], + [ + ["ms", ["margin-inline-start"]], + ["me", ["margin-inline-end"]], + ["mt", ["margin-top"]], + ["mr", ["margin-right"]], + ["mb", ["margin-bottom"]], + ["ml", ["margin-left"]], + ], + ], + { supportsNegativeValues: !0 } + ), + boxSizing: ({ addUtilities: r }) => { + r({ + ".box-border": { "box-sizing": "border-box" }, + ".box-content": { "box-sizing": "content-box" }, + }); + }, + lineClamp: ({ matchUtilities: r, addUtilities: e, theme: t }) => { + (r( + { + "line-clamp": (i) => ({ + overflow: "hidden", + display: "-webkit-box", + "-webkit-box-orient": "vertical", + "-webkit-line-clamp": `${i}`, + }), + }, + { values: t("lineClamp") } + ), + e({ + ".line-clamp-none": { + overflow: "visible", + display: "block", + "-webkit-box-orient": "horizontal", + "-webkit-line-clamp": "none", + }, + })); + }, + display: ({ addUtilities: r }) => { + r({ + ".block": { display: "block" }, + ".inline-block": { display: "inline-block" }, + ".inline": { display: "inline" }, + ".flex": { display: "flex" }, + ".inline-flex": { display: "inline-flex" }, + ".table": { display: "table" }, + ".inline-table": { display: "inline-table" }, + ".table-caption": { display: "table-caption" }, + ".table-cell": { display: "table-cell" }, + ".table-column": { display: "table-column" }, + ".table-column-group": { display: "table-column-group" }, + ".table-footer-group": { display: "table-footer-group" }, + ".table-header-group": { display: "table-header-group" }, + ".table-row-group": { display: "table-row-group" }, + ".table-row": { display: "table-row" }, + ".flow-root": { display: "flow-root" }, + ".grid": { display: "grid" }, + ".inline-grid": { display: "inline-grid" }, + ".contents": { display: "contents" }, + ".list-item": { display: "list-item" }, + ".hidden": { display: "none" }, + }); + }, + aspectRatio: P("aspectRatio", [["aspect", ["aspect-ratio"]]]), + size: P("size", [["size", ["width", "height"]]]), + height: P("height", [["h", ["height"]]]), + maxHeight: P("maxHeight", [["max-h", ["maxHeight"]]]), + minHeight: P("minHeight", [["min-h", ["minHeight"]]]), + width: P("width", [["w", ["width"]]]), + minWidth: P("minWidth", [["min-w", ["minWidth"]]]), + maxWidth: P("maxWidth", [["max-w", ["maxWidth"]]]), + flex: P("flex"), + flexShrink: P("flexShrink", [ + ["flex-shrink", ["flex-shrink"]], + ["shrink", ["flex-shrink"]], + ]), + flexGrow: P("flexGrow", [ + ["flex-grow", ["flex-grow"]], + ["grow", ["flex-grow"]], + ]), + flexBasis: P("flexBasis", [["basis", ["flex-basis"]]]), + tableLayout: ({ addUtilities: r }) => { + r({ ".table-auto": { "table-layout": "auto" }, ".table-fixed": { "table-layout": "fixed" } }); + }, + captionSide: ({ addUtilities: r }) => { + r({ + ".caption-top": { "caption-side": "top" }, + ".caption-bottom": { "caption-side": "bottom" }, + }); + }, + borderCollapse: ({ addUtilities: r }) => { + r({ + ".border-collapse": { "border-collapse": "collapse" }, + ".border-separate": { "border-collapse": "separate" }, + }); + }, + borderSpacing: ({ addDefaults: r, matchUtilities: e, theme: t }) => { + (r("border-spacing", { "--tw-border-spacing-x": 0, "--tw-border-spacing-y": 0 }), + e( + { + "border-spacing": (i) => ({ + "--tw-border-spacing-x": i, + "--tw-border-spacing-y": i, + "@defaults border-spacing": {}, + "border-spacing": "var(--tw-border-spacing-x) var(--tw-border-spacing-y)", + }), + "border-spacing-x": (i) => ({ + "--tw-border-spacing-x": i, + "@defaults border-spacing": {}, + "border-spacing": "var(--tw-border-spacing-x) var(--tw-border-spacing-y)", + }), + "border-spacing-y": (i) => ({ + "--tw-border-spacing-y": i, + "@defaults border-spacing": {}, + "border-spacing": "var(--tw-border-spacing-x) var(--tw-border-spacing-y)", + }), + }, + { values: t("borderSpacing") } + )); + }, + transformOrigin: P("transformOrigin", [["origin", ["transformOrigin"]]]), + translate: P( + "translate", + [ + [ + ["translate-x", [["@defaults transform", {}], "--tw-translate-x", ["transform", Te]]], + ["translate-y", [["@defaults transform", {}], "--tw-translate-y", ["transform", Te]]], + ], + ], + { supportsNegativeValues: !0 } + ), + rotate: P("rotate", [["rotate", [["@defaults transform", {}], "--tw-rotate", ["transform", Te]]]], { + supportsNegativeValues: !0, + }), + skew: P( + "skew", + [ + [ + ["skew-x", [["@defaults transform", {}], "--tw-skew-x", ["transform", Te]]], + ["skew-y", [["@defaults transform", {}], "--tw-skew-y", ["transform", Te]]], + ], + ], + { supportsNegativeValues: !0 } + ), + scale: P( + "scale", + [ + ["scale", [["@defaults transform", {}], "--tw-scale-x", "--tw-scale-y", ["transform", Te]]], + [ + ["scale-x", [["@defaults transform", {}], "--tw-scale-x", ["transform", Te]]], + ["scale-y", [["@defaults transform", {}], "--tw-scale-y", ["transform", Te]]], + ], + ], + { supportsNegativeValues: !0 } + ), + transform: ({ addDefaults: r, addUtilities: e }) => { + (r("transform", { + "--tw-translate-x": "0", + "--tw-translate-y": "0", + "--tw-rotate": "0", + "--tw-skew-x": "0", + "--tw-skew-y": "0", + "--tw-scale-x": "1", + "--tw-scale-y": "1", + }), + e({ + ".transform": { "@defaults transform": {}, transform: Te }, + ".transform-cpu": { transform: Te }, + ".transform-gpu": { + transform: Te.replace( + "translate(var(--tw-translate-x), var(--tw-translate-y))", + "translate3d(var(--tw-translate-x), var(--tw-translate-y), 0)" + ), + }, + ".transform-none": { transform: "none" }, + })); + }, + animation: ({ matchUtilities: r, theme: e, config: t }) => { + let i = (a) => ce(t("prefix") + a), + n = Object.fromEntries( + Object.entries(e("keyframes") ?? {}).map(([a, s]) => [a, { [`@keyframes ${i(a)}`]: s }]) + ); + r( + { + animate: (a) => { + let s = Ka(a); + return [ + ...s.flatMap((o) => n[o.name]), + { + animation: s + .map(({ name: o, value: u }) => + o === void 0 || n[o] === void 0 ? u : u.replace(o, i(o)) + ) + .join(", "), + }, + ]; + }, + }, + { values: e("animation") } + ); + }, + cursor: P("cursor"), + touchAction: ({ addDefaults: r, addUtilities: e }) => { + r("touch-action", { "--tw-pan-x": " ", "--tw-pan-y": " ", "--tw-pinch-zoom": " " }); + let t = "var(--tw-pan-x) var(--tw-pan-y) var(--tw-pinch-zoom)"; + e({ + ".touch-auto": { "touch-action": "auto" }, + ".touch-none": { "touch-action": "none" }, + ".touch-pan-x": { "@defaults touch-action": {}, "--tw-pan-x": "pan-x", "touch-action": t }, + ".touch-pan-left": { + "@defaults touch-action": {}, + "--tw-pan-x": "pan-left", + "touch-action": t, + }, + ".touch-pan-right": { + "@defaults touch-action": {}, + "--tw-pan-x": "pan-right", + "touch-action": t, + }, + ".touch-pan-y": { "@defaults touch-action": {}, "--tw-pan-y": "pan-y", "touch-action": t }, + ".touch-pan-up": { + "@defaults touch-action": {}, + "--tw-pan-y": "pan-up", + "touch-action": t, + }, + ".touch-pan-down": { + "@defaults touch-action": {}, + "--tw-pan-y": "pan-down", + "touch-action": t, + }, + ".touch-pinch-zoom": { + "@defaults touch-action": {}, + "--tw-pinch-zoom": "pinch-zoom", + "touch-action": t, + }, + ".touch-manipulation": { "touch-action": "manipulation" }, + }); + }, + userSelect: ({ addUtilities: r }) => { + r({ + ".select-none": { "user-select": "none" }, + ".select-text": { "user-select": "text" }, + ".select-all": { "user-select": "all" }, + ".select-auto": { "user-select": "auto" }, + }); + }, + resize: ({ addUtilities: r }) => { + r({ + ".resize-none": { resize: "none" }, + ".resize-y": { resize: "vertical" }, + ".resize-x": { resize: "horizontal" }, + ".resize": { resize: "both" }, + }); + }, + scrollSnapType: ({ addDefaults: r, addUtilities: e }) => { + (r("scroll-snap-type", { "--tw-scroll-snap-strictness": "proximity" }), + e({ + ".snap-none": { "scroll-snap-type": "none" }, + ".snap-x": { + "@defaults scroll-snap-type": {}, + "scroll-snap-type": "x var(--tw-scroll-snap-strictness)", + }, + ".snap-y": { + "@defaults scroll-snap-type": {}, + "scroll-snap-type": "y var(--tw-scroll-snap-strictness)", + }, + ".snap-both": { + "@defaults scroll-snap-type": {}, + "scroll-snap-type": "both var(--tw-scroll-snap-strictness)", + }, + ".snap-mandatory": { "--tw-scroll-snap-strictness": "mandatory" }, + ".snap-proximity": { "--tw-scroll-snap-strictness": "proximity" }, + })); + }, + scrollSnapAlign: ({ addUtilities: r }) => { + r({ + ".snap-start": { "scroll-snap-align": "start" }, + ".snap-end": { "scroll-snap-align": "end" }, + ".snap-center": { "scroll-snap-align": "center" }, + ".snap-align-none": { "scroll-snap-align": "none" }, + }); + }, + scrollSnapStop: ({ addUtilities: r }) => { + r({ + ".snap-normal": { "scroll-snap-stop": "normal" }, + ".snap-always": { "scroll-snap-stop": "always" }, + }); + }, + scrollMargin: P( + "scrollMargin", + [ + ["scroll-m", ["scroll-margin"]], + [ + ["scroll-mx", ["scroll-margin-left", "scroll-margin-right"]], + ["scroll-my", ["scroll-margin-top", "scroll-margin-bottom"]], + ], + [ + ["scroll-ms", ["scroll-margin-inline-start"]], + ["scroll-me", ["scroll-margin-inline-end"]], + ["scroll-mt", ["scroll-margin-top"]], + ["scroll-mr", ["scroll-margin-right"]], + ["scroll-mb", ["scroll-margin-bottom"]], + ["scroll-ml", ["scroll-margin-left"]], + ], + ], + { supportsNegativeValues: !0 } + ), + scrollPadding: P("scrollPadding", [ + ["scroll-p", ["scroll-padding"]], + [ + ["scroll-px", ["scroll-padding-left", "scroll-padding-right"]], + ["scroll-py", ["scroll-padding-top", "scroll-padding-bottom"]], + ], + [ + ["scroll-ps", ["scroll-padding-inline-start"]], + ["scroll-pe", ["scroll-padding-inline-end"]], + ["scroll-pt", ["scroll-padding-top"]], + ["scroll-pr", ["scroll-padding-right"]], + ["scroll-pb", ["scroll-padding-bottom"]], + ["scroll-pl", ["scroll-padding-left"]], + ], + ]), + listStylePosition: ({ addUtilities: r }) => { + r({ + ".list-inside": { "list-style-position": "inside" }, + ".list-outside": { "list-style-position": "outside" }, + }); + }, + listStyleType: P("listStyleType", [["list", ["listStyleType"]]]), + listStyleImage: P("listStyleImage", [["list-image", ["listStyleImage"]]]), + appearance: ({ addUtilities: r }) => { + r({ ".appearance-none": { appearance: "none" }, ".appearance-auto": { appearance: "auto" } }); + }, + columns: P("columns", [["columns", ["columns"]]]), + breakBefore: ({ addUtilities: r }) => { + r({ + ".break-before-auto": { "break-before": "auto" }, + ".break-before-avoid": { "break-before": "avoid" }, + ".break-before-all": { "break-before": "all" }, + ".break-before-avoid-page": { "break-before": "avoid-page" }, + ".break-before-page": { "break-before": "page" }, + ".break-before-left": { "break-before": "left" }, + ".break-before-right": { "break-before": "right" }, + ".break-before-column": { "break-before": "column" }, + }); + }, + breakInside: ({ addUtilities: r }) => { + r({ + ".break-inside-auto": { "break-inside": "auto" }, + ".break-inside-avoid": { "break-inside": "avoid" }, + ".break-inside-avoid-page": { "break-inside": "avoid-page" }, + ".break-inside-avoid-column": { "break-inside": "avoid-column" }, + }); + }, + breakAfter: ({ addUtilities: r }) => { + r({ + ".break-after-auto": { "break-after": "auto" }, + ".break-after-avoid": { "break-after": "avoid" }, + ".break-after-all": { "break-after": "all" }, + ".break-after-avoid-page": { "break-after": "avoid-page" }, + ".break-after-page": { "break-after": "page" }, + ".break-after-left": { "break-after": "left" }, + ".break-after-right": { "break-after": "right" }, + ".break-after-column": { "break-after": "column" }, + }); + }, + gridAutoColumns: P("gridAutoColumns", [["auto-cols", ["gridAutoColumns"]]]), + gridAutoFlow: ({ addUtilities: r }) => { + r({ + ".grid-flow-row": { gridAutoFlow: "row" }, + ".grid-flow-col": { gridAutoFlow: "column" }, + ".grid-flow-dense": { gridAutoFlow: "dense" }, + ".grid-flow-row-dense": { gridAutoFlow: "row dense" }, + ".grid-flow-col-dense": { gridAutoFlow: "column dense" }, + }); + }, + gridAutoRows: P("gridAutoRows", [["auto-rows", ["gridAutoRows"]]]), + gridTemplateColumns: P("gridTemplateColumns", [["grid-cols", ["gridTemplateColumns"]]]), + gridTemplateRows: P("gridTemplateRows", [["grid-rows", ["gridTemplateRows"]]]), + flexDirection: ({ addUtilities: r }) => { + r({ + ".flex-row": { "flex-direction": "row" }, + ".flex-row-reverse": { "flex-direction": "row-reverse" }, + ".flex-col": { "flex-direction": "column" }, + ".flex-col-reverse": { "flex-direction": "column-reverse" }, + }); + }, + flexWrap: ({ addUtilities: r }) => { + r({ + ".flex-wrap": { "flex-wrap": "wrap" }, + ".flex-wrap-reverse": { "flex-wrap": "wrap-reverse" }, + ".flex-nowrap": { "flex-wrap": "nowrap" }, + }); + }, + placeContent: ({ addUtilities: r }) => { + r({ + ".place-content-center": { "place-content": "center" }, + ".place-content-start": { "place-content": "start" }, + ".place-content-end": { "place-content": "end" }, + ".place-content-between": { "place-content": "space-between" }, + ".place-content-around": { "place-content": "space-around" }, + ".place-content-evenly": { "place-content": "space-evenly" }, + ".place-content-baseline": { "place-content": "baseline" }, + ".place-content-stretch": { "place-content": "stretch" }, + }); + }, + placeItems: ({ addUtilities: r }) => { + r({ + ".place-items-start": { "place-items": "start" }, + ".place-items-end": { "place-items": "end" }, + ".place-items-center": { "place-items": "center" }, + ".place-items-baseline": { "place-items": "baseline" }, + ".place-items-stretch": { "place-items": "stretch" }, + }); + }, + alignContent: ({ addUtilities: r }) => { + r({ + ".content-normal": { "align-content": "normal" }, + ".content-center": { "align-content": "center" }, + ".content-start": { "align-content": "flex-start" }, + ".content-end": { "align-content": "flex-end" }, + ".content-between": { "align-content": "space-between" }, + ".content-around": { "align-content": "space-around" }, + ".content-evenly": { "align-content": "space-evenly" }, + ".content-baseline": { "align-content": "baseline" }, + ".content-stretch": { "align-content": "stretch" }, + }); + }, + alignItems: ({ addUtilities: r }) => { + r({ + ".items-start": { "align-items": "flex-start" }, + ".items-end": { "align-items": "flex-end" }, + ".items-center": { "align-items": "center" }, + ".items-baseline": { "align-items": "baseline" }, + ".items-stretch": { "align-items": "stretch" }, + }); + }, + justifyContent: ({ addUtilities: r }) => { + r({ + ".justify-normal": { "justify-content": "normal" }, + ".justify-start": { "justify-content": "flex-start" }, + ".justify-end": { "justify-content": "flex-end" }, + ".justify-center": { "justify-content": "center" }, + ".justify-between": { "justify-content": "space-between" }, + ".justify-around": { "justify-content": "space-around" }, + ".justify-evenly": { "justify-content": "space-evenly" }, + ".justify-stretch": { "justify-content": "stretch" }, + }); + }, + justifyItems: ({ addUtilities: r }) => { + r({ + ".justify-items-start": { "justify-items": "start" }, + ".justify-items-end": { "justify-items": "end" }, + ".justify-items-center": { "justify-items": "center" }, + ".justify-items-stretch": { "justify-items": "stretch" }, + }); + }, + gap: P("gap", [ + ["gap", ["gap"]], + [ + ["gap-x", ["columnGap"]], + ["gap-y", ["rowGap"]], + ], + ]), + space: ({ matchUtilities: r, addUtilities: e, theme: t }) => { + (r( + { + "space-x": (i) => ( + (i = i === "0" ? "0px" : i), + { + "& > :not([hidden]) ~ :not([hidden])": { + "--tw-space-x-reverse": "0", + "margin-right": `calc(${i} * var(--tw-space-x-reverse))`, + "margin-left": `calc(${i} * calc(1 - var(--tw-space-x-reverse)))`, + }, + } + ), + "space-y": (i) => ( + (i = i === "0" ? "0px" : i), + { + "& > :not([hidden]) ~ :not([hidden])": { + "--tw-space-y-reverse": "0", + "margin-top": `calc(${i} * calc(1 - var(--tw-space-y-reverse)))`, + "margin-bottom": `calc(${i} * var(--tw-space-y-reverse))`, + }, + } + ), + }, + { values: t("space"), supportsNegativeValues: !0 } + ), + e({ + ".space-y-reverse > :not([hidden]) ~ :not([hidden])": { "--tw-space-y-reverse": "1" }, + ".space-x-reverse > :not([hidden]) ~ :not([hidden])": { "--tw-space-x-reverse": "1" }, + })); + }, + divideWidth: ({ matchUtilities: r, addUtilities: e, theme: t }) => { + (r( + { + "divide-x": (i) => ( + (i = i === "0" ? "0px" : i), + { + "& > :not([hidden]) ~ :not([hidden])": { + "@defaults border-width": {}, + "--tw-divide-x-reverse": "0", + "border-right-width": `calc(${i} * var(--tw-divide-x-reverse))`, + "border-left-width": `calc(${i} * calc(1 - var(--tw-divide-x-reverse)))`, + }, + } + ), + "divide-y": (i) => ( + (i = i === "0" ? "0px" : i), + { + "& > :not([hidden]) ~ :not([hidden])": { + "@defaults border-width": {}, + "--tw-divide-y-reverse": "0", + "border-top-width": `calc(${i} * calc(1 - var(--tw-divide-y-reverse)))`, + "border-bottom-width": `calc(${i} * var(--tw-divide-y-reverse))`, + }, + } + ), + }, + { values: t("divideWidth"), type: ["line-width", "length", "any"] } + ), + e({ + ".divide-y-reverse > :not([hidden]) ~ :not([hidden])": { + "@defaults border-width": {}, + "--tw-divide-y-reverse": "1", + }, + ".divide-x-reverse > :not([hidden]) ~ :not([hidden])": { + "@defaults border-width": {}, + "--tw-divide-x-reverse": "1", + }, + })); + }, + divideStyle: ({ addUtilities: r }) => { + r({ + ".divide-solid > :not([hidden]) ~ :not([hidden])": { "border-style": "solid" }, + ".divide-dashed > :not([hidden]) ~ :not([hidden])": { "border-style": "dashed" }, + ".divide-dotted > :not([hidden]) ~ :not([hidden])": { "border-style": "dotted" }, + ".divide-double > :not([hidden]) ~ :not([hidden])": { "border-style": "double" }, + ".divide-none > :not([hidden]) ~ :not([hidden])": { "border-style": "none" }, + }); + }, + divideColor: ({ matchUtilities: r, theme: e, corePlugins: t }) => { + r( + { + divide: (i) => + t("divideOpacity") + ? { + ["& > :not([hidden]) ~ :not([hidden])"]: se({ + color: i, + property: "border-color", + variable: "--tw-divide-opacity", + }), + } + : { ["& > :not([hidden]) ~ :not([hidden])"]: { "border-color": N(i) } }, + }, + { values: (({ DEFAULT: i, ...n }) => n)(re(e("divideColor"))), type: ["color", "any"] } + ); + }, + divideOpacity: ({ matchUtilities: r, theme: e }) => { + r( + { + "divide-opacity": (t) => ({ + ["& > :not([hidden]) ~ :not([hidden])"]: { "--tw-divide-opacity": t }, + }), + }, + { values: e("divideOpacity") } + ); + }, + placeSelf: ({ addUtilities: r }) => { + r({ + ".place-self-auto": { "place-self": "auto" }, + ".place-self-start": { "place-self": "start" }, + ".place-self-end": { "place-self": "end" }, + ".place-self-center": { "place-self": "center" }, + ".place-self-stretch": { "place-self": "stretch" }, + }); + }, + alignSelf: ({ addUtilities: r }) => { + r({ + ".self-auto": { "align-self": "auto" }, + ".self-start": { "align-self": "flex-start" }, + ".self-end": { "align-self": "flex-end" }, + ".self-center": { "align-self": "center" }, + ".self-stretch": { "align-self": "stretch" }, + ".self-baseline": { "align-self": "baseline" }, + }); + }, + justifySelf: ({ addUtilities: r }) => { + r({ + ".justify-self-auto": { "justify-self": "auto" }, + ".justify-self-start": { "justify-self": "start" }, + ".justify-self-end": { "justify-self": "end" }, + ".justify-self-center": { "justify-self": "center" }, + ".justify-self-stretch": { "justify-self": "stretch" }, + }); + }, + overflow: ({ addUtilities: r }) => { + r({ + ".overflow-auto": { overflow: "auto" }, + ".overflow-hidden": { overflow: "hidden" }, + ".overflow-clip": { overflow: "clip" }, + ".overflow-visible": { overflow: "visible" }, + ".overflow-scroll": { overflow: "scroll" }, + ".overflow-x-auto": { "overflow-x": "auto" }, + ".overflow-y-auto": { "overflow-y": "auto" }, + ".overflow-x-hidden": { "overflow-x": "hidden" }, + ".overflow-y-hidden": { "overflow-y": "hidden" }, + ".overflow-x-clip": { "overflow-x": "clip" }, + ".overflow-y-clip": { "overflow-y": "clip" }, + ".overflow-x-visible": { "overflow-x": "visible" }, + ".overflow-y-visible": { "overflow-y": "visible" }, + ".overflow-x-scroll": { "overflow-x": "scroll" }, + ".overflow-y-scroll": { "overflow-y": "scroll" }, + }); + }, + overscrollBehavior: ({ addUtilities: r }) => { + r({ + ".overscroll-auto": { "overscroll-behavior": "auto" }, + ".overscroll-contain": { "overscroll-behavior": "contain" }, + ".overscroll-none": { "overscroll-behavior": "none" }, + ".overscroll-y-auto": { "overscroll-behavior-y": "auto" }, + ".overscroll-y-contain": { "overscroll-behavior-y": "contain" }, + ".overscroll-y-none": { "overscroll-behavior-y": "none" }, + ".overscroll-x-auto": { "overscroll-behavior-x": "auto" }, + ".overscroll-x-contain": { "overscroll-behavior-x": "contain" }, + ".overscroll-x-none": { "overscroll-behavior-x": "none" }, + }); + }, + scrollBehavior: ({ addUtilities: r }) => { + r({ + ".scroll-auto": { "scroll-behavior": "auto" }, + ".scroll-smooth": { "scroll-behavior": "smooth" }, + }); + }, + textOverflow: ({ addUtilities: r }) => { + r({ + ".truncate": { overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }, + ".overflow-ellipsis": { "text-overflow": "ellipsis" }, + ".text-ellipsis": { "text-overflow": "ellipsis" }, + ".text-clip": { "text-overflow": "clip" }, + }); + }, + hyphens: ({ addUtilities: r }) => { + r({ + ".hyphens-none": { hyphens: "none" }, + ".hyphens-manual": { hyphens: "manual" }, + ".hyphens-auto": { hyphens: "auto" }, + }); + }, + whitespace: ({ addUtilities: r }) => { + r({ + ".whitespace-normal": { "white-space": "normal" }, + ".whitespace-nowrap": { "white-space": "nowrap" }, + ".whitespace-pre": { "white-space": "pre" }, + ".whitespace-pre-line": { "white-space": "pre-line" }, + ".whitespace-pre-wrap": { "white-space": "pre-wrap" }, + ".whitespace-break-spaces": { "white-space": "break-spaces" }, + }); + }, + textWrap: ({ addUtilities: r }) => { + r({ + ".text-wrap": { "text-wrap": "wrap" }, + ".text-nowrap": { "text-wrap": "nowrap" }, + ".text-balance": { "text-wrap": "balance" }, + ".text-pretty": { "text-wrap": "pretty" }, + }); + }, + wordBreak: ({ addUtilities: r }) => { + r({ + ".break-normal": { "overflow-wrap": "normal", "word-break": "normal" }, + ".break-words": { "overflow-wrap": "break-word" }, + ".break-all": { "word-break": "break-all" }, + ".break-keep": { "word-break": "keep-all" }, + }); + }, + borderRadius: P("borderRadius", [ + ["rounded", ["border-radius"]], + [ + ["rounded-s", ["border-start-start-radius", "border-end-start-radius"]], + ["rounded-e", ["border-start-end-radius", "border-end-end-radius"]], + ["rounded-t", ["border-top-left-radius", "border-top-right-radius"]], + ["rounded-r", ["border-top-right-radius", "border-bottom-right-radius"]], + ["rounded-b", ["border-bottom-right-radius", "border-bottom-left-radius"]], + ["rounded-l", ["border-top-left-radius", "border-bottom-left-radius"]], + ], + [ + ["rounded-ss", ["border-start-start-radius"]], + ["rounded-se", ["border-start-end-radius"]], + ["rounded-ee", ["border-end-end-radius"]], + ["rounded-es", ["border-end-start-radius"]], + ["rounded-tl", ["border-top-left-radius"]], + ["rounded-tr", ["border-top-right-radius"]], + ["rounded-br", ["border-bottom-right-radius"]], + ["rounded-bl", ["border-bottom-left-radius"]], + ], + ]), + borderWidth: P( + "borderWidth", + [ + ["border", [["@defaults border-width", {}], "border-width"]], + [ + [ + "border-x", + [["@defaults border-width", {}], "border-left-width", "border-right-width"], + ], + [ + "border-y", + [["@defaults border-width", {}], "border-top-width", "border-bottom-width"], + ], + ], + [ + ["border-s", [["@defaults border-width", {}], "border-inline-start-width"]], + ["border-e", [["@defaults border-width", {}], "border-inline-end-width"]], + ["border-t", [["@defaults border-width", {}], "border-top-width"]], + ["border-r", [["@defaults border-width", {}], "border-right-width"]], + ["border-b", [["@defaults border-width", {}], "border-bottom-width"]], + ["border-l", [["@defaults border-width", {}], "border-left-width"]], + ], + ], + { type: ["line-width", "length"] } + ), + borderStyle: ({ addUtilities: r }) => { + r({ + ".border-solid": { "border-style": "solid" }, + ".border-dashed": { "border-style": "dashed" }, + ".border-dotted": { "border-style": "dotted" }, + ".border-double": { "border-style": "double" }, + ".border-hidden": { "border-style": "hidden" }, + ".border-none": { "border-style": "none" }, + }); + }, + borderColor: ({ matchUtilities: r, theme: e, corePlugins: t }) => { + (r( + { + border: (i) => + t("borderOpacity") + ? se({ color: i, property: "border-color", variable: "--tw-border-opacity" }) + : { "border-color": N(i) }, + }, + { values: (({ DEFAULT: i, ...n }) => n)(re(e("borderColor"))), type: ["color", "any"] } + ), + r( + { + "border-x": (i) => + t("borderOpacity") + ? se({ + color: i, + property: ["border-left-color", "border-right-color"], + variable: "--tw-border-opacity", + }) + : { "border-left-color": N(i), "border-right-color": N(i) }, + "border-y": (i) => + t("borderOpacity") + ? se({ + color: i, + property: ["border-top-color", "border-bottom-color"], + variable: "--tw-border-opacity", + }) + : { "border-top-color": N(i), "border-bottom-color": N(i) }, + }, + { values: (({ DEFAULT: i, ...n }) => n)(re(e("borderColor"))), type: ["color", "any"] } + ), + r( + { + "border-s": (i) => + t("borderOpacity") + ? se({ + color: i, + property: "border-inline-start-color", + variable: "--tw-border-opacity", + }) + : { "border-inline-start-color": N(i) }, + "border-e": (i) => + t("borderOpacity") + ? se({ + color: i, + property: "border-inline-end-color", + variable: "--tw-border-opacity", + }) + : { "border-inline-end-color": N(i) }, + "border-t": (i) => + t("borderOpacity") + ? se({ + color: i, + property: "border-top-color", + variable: "--tw-border-opacity", + }) + : { "border-top-color": N(i) }, + "border-r": (i) => + t("borderOpacity") + ? se({ + color: i, + property: "border-right-color", + variable: "--tw-border-opacity", + }) + : { "border-right-color": N(i) }, + "border-b": (i) => + t("borderOpacity") + ? se({ + color: i, + property: "border-bottom-color", + variable: "--tw-border-opacity", + }) + : { "border-bottom-color": N(i) }, + "border-l": (i) => + t("borderOpacity") + ? se({ + color: i, + property: "border-left-color", + variable: "--tw-border-opacity", + }) + : { "border-left-color": N(i) }, + }, + { values: (({ DEFAULT: i, ...n }) => n)(re(e("borderColor"))), type: ["color", "any"] } + )); + }, + borderOpacity: P("borderOpacity", [["border-opacity", ["--tw-border-opacity"]]]), + backgroundColor: ({ matchUtilities: r, theme: e, corePlugins: t }) => { + r( + { + bg: (i) => + t("backgroundOpacity") + ? se({ color: i, property: "background-color", variable: "--tw-bg-opacity" }) + : { "background-color": N(i) }, + }, + { values: re(e("backgroundColor")), type: ["color", "any"] } + ); + }, + backgroundOpacity: P("backgroundOpacity", [["bg-opacity", ["--tw-bg-opacity"]]]), + backgroundImage: P("backgroundImage", [["bg", ["background-image"]]], { + type: ["lookup", "image", "url"], + }), + gradientColorStops: (() => { + function r(e) { + return Ie(e, 0, "rgb(255 255 255 / 0)"); + } + return function ({ matchUtilities: e, theme: t, addDefaults: i }) { + i("gradient-color-stops", { + "--tw-gradient-from-position": " ", + "--tw-gradient-via-position": " ", + "--tw-gradient-to-position": " ", + }); + let n = { values: re(t("gradientColorStops")), type: ["color", "any"] }, + a = { values: t("gradientColorStopPositions"), type: ["length", "percentage"] }; + (e( + { + from: (s) => { + let o = r(s); + return { + "@defaults gradient-color-stops": {}, + "--tw-gradient-from": `${N(s)} var(--tw-gradient-from-position)`, + "--tw-gradient-to": `${o} var(--tw-gradient-to-position)`, + "--tw-gradient-stops": "var(--tw-gradient-from), var(--tw-gradient-to)", + }; + }, + }, + n + ), + e({ from: (s) => ({ "--tw-gradient-from-position": s }) }, a), + e( + { + via: (s) => { + let o = r(s); + return { + "@defaults gradient-color-stops": {}, + "--tw-gradient-to": `${o} var(--tw-gradient-to-position)`, + "--tw-gradient-stops": `var(--tw-gradient-from), ${N(s)} var(--tw-gradient-via-position), var(--tw-gradient-to)`, + }; + }, + }, + n + ), + e({ via: (s) => ({ "--tw-gradient-via-position": s }) }, a), + e( + { + to: (s) => ({ + "@defaults gradient-color-stops": {}, + "--tw-gradient-to": `${N(s)} var(--tw-gradient-to-position)`, + }), + }, + n + ), + e({ to: (s) => ({ "--tw-gradient-to-position": s }) }, a)); + }; + })(), + boxDecorationBreak: ({ addUtilities: r }) => { + r({ + ".decoration-slice": { "box-decoration-break": "slice" }, + ".decoration-clone": { "box-decoration-break": "clone" }, + ".box-decoration-slice": { "box-decoration-break": "slice" }, + ".box-decoration-clone": { "box-decoration-break": "clone" }, + }); + }, + backgroundSize: P("backgroundSize", [["bg", ["background-size"]]], { + type: ["lookup", "length", "percentage", "size"], + }), + backgroundAttachment: ({ addUtilities: r }) => { + r({ + ".bg-fixed": { "background-attachment": "fixed" }, + ".bg-local": { "background-attachment": "local" }, + ".bg-scroll": { "background-attachment": "scroll" }, + }); + }, + backgroundClip: ({ addUtilities: r }) => { + r({ + ".bg-clip-border": { "background-clip": "border-box" }, + ".bg-clip-padding": { "background-clip": "padding-box" }, + ".bg-clip-content": { "background-clip": "content-box" }, + ".bg-clip-text": { "background-clip": "text" }, + }); + }, + backgroundPosition: P("backgroundPosition", [["bg", ["background-position"]]], { + type: ["lookup", ["position", { preferOnConflict: !0 }]], + }), + backgroundRepeat: ({ addUtilities: r }) => { + r({ + ".bg-repeat": { "background-repeat": "repeat" }, + ".bg-no-repeat": { "background-repeat": "no-repeat" }, + ".bg-repeat-x": { "background-repeat": "repeat-x" }, + ".bg-repeat-y": { "background-repeat": "repeat-y" }, + ".bg-repeat-round": { "background-repeat": "round" }, + ".bg-repeat-space": { "background-repeat": "space" }, + }); + }, + backgroundOrigin: ({ addUtilities: r }) => { + r({ + ".bg-origin-border": { "background-origin": "border-box" }, + ".bg-origin-padding": { "background-origin": "padding-box" }, + ".bg-origin-content": { "background-origin": "content-box" }, + }); + }, + fill: ({ matchUtilities: r, theme: e }) => { + r({ fill: (t) => ({ fill: N(t) }) }, { values: re(e("fill")), type: ["color", "any"] }); + }, + stroke: ({ matchUtilities: r, theme: e }) => { + r( + { stroke: (t) => ({ stroke: N(t) }) }, + { values: re(e("stroke")), type: ["color", "url", "any"] } + ); + }, + strokeWidth: P("strokeWidth", [["stroke", ["stroke-width"]]], { + type: ["length", "number", "percentage"], + }), + objectFit: ({ addUtilities: r }) => { + r({ + ".object-contain": { "object-fit": "contain" }, + ".object-cover": { "object-fit": "cover" }, + ".object-fill": { "object-fit": "fill" }, + ".object-none": { "object-fit": "none" }, + ".object-scale-down": { "object-fit": "scale-down" }, + }); + }, + objectPosition: P("objectPosition", [["object", ["object-position"]]]), + padding: P("padding", [ + ["p", ["padding"]], + [ + ["px", ["padding-left", "padding-right"]], + ["py", ["padding-top", "padding-bottom"]], + ], + [ + ["ps", ["padding-inline-start"]], + ["pe", ["padding-inline-end"]], + ["pt", ["padding-top"]], + ["pr", ["padding-right"]], + ["pb", ["padding-bottom"]], + ["pl", ["padding-left"]], + ], + ]), + textAlign: ({ addUtilities: r }) => { + r({ + ".text-left": { "text-align": "left" }, + ".text-center": { "text-align": "center" }, + ".text-right": { "text-align": "right" }, + ".text-justify": { "text-align": "justify" }, + ".text-start": { "text-align": "start" }, + ".text-end": { "text-align": "end" }, + }); + }, + textIndent: P("textIndent", [["indent", ["text-indent"]]], { supportsNegativeValues: !0 }), + verticalAlign: ({ addUtilities: r, matchUtilities: e }) => { + (r({ + ".align-baseline": { "vertical-align": "baseline" }, + ".align-top": { "vertical-align": "top" }, + ".align-middle": { "vertical-align": "middle" }, + ".align-bottom": { "vertical-align": "bottom" }, + ".align-text-top": { "vertical-align": "text-top" }, + ".align-text-bottom": { "vertical-align": "text-bottom" }, + ".align-sub": { "vertical-align": "sub" }, + ".align-super": { "vertical-align": "super" }, + }), + e({ align: (t) => ({ "vertical-align": t }) })); + }, + fontFamily: ({ matchUtilities: r, theme: e }) => { + r( + { + font: (t) => { + let [i, n = {}] = Array.isArray(t) && ie(t[1]) ? t : [t], + { fontFeatureSettings: a, fontVariationSettings: s } = n; + return { + "font-family": Array.isArray(i) ? i.join(", ") : i, + ...(a === void 0 ? {} : { "font-feature-settings": a }), + ...(s === void 0 ? {} : { "font-variation-settings": s }), + }; + }, + }, + { values: e("fontFamily"), type: ["lookup", "generic-name", "family-name"] } + ); + }, + fontSize: ({ matchUtilities: r, theme: e }) => { + r( + { + text: (t, { modifier: i }) => { + let [n, a] = Array.isArray(t) ? t : [t]; + if (i) return { "font-size": n, "line-height": i }; + let { + lineHeight: s, + letterSpacing: o, + fontWeight: u, + } = ie(a) ? a : { lineHeight: a }; + return { + "font-size": n, + ...(s === void 0 ? {} : { "line-height": s }), + ...(o === void 0 ? {} : { "letter-spacing": o }), + ...(u === void 0 ? {} : { "font-weight": u }), + }; + }, + }, + { + values: e("fontSize"), + modifiers: e("lineHeight"), + type: ["absolute-size", "relative-size", "length", "percentage"], + } + ); + }, + fontWeight: P("fontWeight", [["font", ["fontWeight"]]], { type: ["lookup", "number", "any"] }), + textTransform: ({ addUtilities: r }) => { + r({ + ".uppercase": { "text-transform": "uppercase" }, + ".lowercase": { "text-transform": "lowercase" }, + ".capitalize": { "text-transform": "capitalize" }, + ".normal-case": { "text-transform": "none" }, + }); + }, + fontStyle: ({ addUtilities: r }) => { + r({ ".italic": { "font-style": "italic" }, ".not-italic": { "font-style": "normal" } }); + }, + fontVariantNumeric: ({ addDefaults: r, addUtilities: e }) => { + let t = + "var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)"; + (r("font-variant-numeric", { + "--tw-ordinal": " ", + "--tw-slashed-zero": " ", + "--tw-numeric-figure": " ", + "--tw-numeric-spacing": " ", + "--tw-numeric-fraction": " ", + }), + e({ + ".normal-nums": { "font-variant-numeric": "normal" }, + ".ordinal": { + "@defaults font-variant-numeric": {}, + "--tw-ordinal": "ordinal", + "font-variant-numeric": t, + }, + ".slashed-zero": { + "@defaults font-variant-numeric": {}, + "--tw-slashed-zero": "slashed-zero", + "font-variant-numeric": t, + }, + ".lining-nums": { + "@defaults font-variant-numeric": {}, + "--tw-numeric-figure": "lining-nums", + "font-variant-numeric": t, + }, + ".oldstyle-nums": { + "@defaults font-variant-numeric": {}, + "--tw-numeric-figure": "oldstyle-nums", + "font-variant-numeric": t, + }, + ".proportional-nums": { + "@defaults font-variant-numeric": {}, + "--tw-numeric-spacing": "proportional-nums", + "font-variant-numeric": t, + }, + ".tabular-nums": { + "@defaults font-variant-numeric": {}, + "--tw-numeric-spacing": "tabular-nums", + "font-variant-numeric": t, + }, + ".diagonal-fractions": { + "@defaults font-variant-numeric": {}, + "--tw-numeric-fraction": "diagonal-fractions", + "font-variant-numeric": t, + }, + ".stacked-fractions": { + "@defaults font-variant-numeric": {}, + "--tw-numeric-fraction": "stacked-fractions", + "font-variant-numeric": t, + }, + })); + }, + lineHeight: P("lineHeight", [["leading", ["lineHeight"]]]), + letterSpacing: P("letterSpacing", [["tracking", ["letterSpacing"]]], { + supportsNegativeValues: !0, + }), + textColor: ({ matchUtilities: r, theme: e, corePlugins: t }) => { + r( + { + text: (i) => + t("textOpacity") + ? se({ color: i, property: "color", variable: "--tw-text-opacity" }) + : { color: N(i) }, + }, + { values: re(e("textColor")), type: ["color", "any"] } + ); + }, + textOpacity: P("textOpacity", [["text-opacity", ["--tw-text-opacity"]]]), + textDecoration: ({ addUtilities: r }) => { + r({ + ".underline": { "text-decoration-line": "underline" }, + ".overline": { "text-decoration-line": "overline" }, + ".line-through": { "text-decoration-line": "line-through" }, + ".no-underline": { "text-decoration-line": "none" }, + }); + }, + textDecorationColor: ({ matchUtilities: r, theme: e }) => { + r( + { decoration: (t) => ({ "text-decoration-color": N(t) }) }, + { values: re(e("textDecorationColor")), type: ["color", "any"] } + ); + }, + textDecorationStyle: ({ addUtilities: r }) => { + r({ + ".decoration-solid": { "text-decoration-style": "solid" }, + ".decoration-double": { "text-decoration-style": "double" }, + ".decoration-dotted": { "text-decoration-style": "dotted" }, + ".decoration-dashed": { "text-decoration-style": "dashed" }, + ".decoration-wavy": { "text-decoration-style": "wavy" }, + }); + }, + textDecorationThickness: P( + "textDecorationThickness", + [["decoration", ["text-decoration-thickness"]]], + { type: ["length", "percentage"] } + ), + textUnderlineOffset: P("textUnderlineOffset", [["underline-offset", ["text-underline-offset"]]], { + type: ["length", "percentage", "any"], + }), + fontSmoothing: ({ addUtilities: r }) => { + r({ + ".antialiased": { + "-webkit-font-smoothing": "antialiased", + "-moz-osx-font-smoothing": "grayscale", + }, + ".subpixel-antialiased": { + "-webkit-font-smoothing": "auto", + "-moz-osx-font-smoothing": "auto", + }, + }); + }, + placeholderColor: ({ matchUtilities: r, theme: e, corePlugins: t }) => { + r( + { + placeholder: (i) => + t("placeholderOpacity") + ? { + "&::placeholder": se({ + color: i, + property: "color", + variable: "--tw-placeholder-opacity", + }), + } + : { "&::placeholder": { color: N(i) } }, + }, + { values: re(e("placeholderColor")), type: ["color", "any"] } + ); + }, + placeholderOpacity: ({ matchUtilities: r, theme: e }) => { + r( + { + "placeholder-opacity": (t) => ({ + ["&::placeholder"]: { "--tw-placeholder-opacity": t }, + }), + }, + { values: e("placeholderOpacity") } + ); + }, + caretColor: ({ matchUtilities: r, theme: e }) => { + r( + { caret: (t) => ({ "caret-color": N(t) }) }, + { values: re(e("caretColor")), type: ["color", "any"] } + ); + }, + accentColor: ({ matchUtilities: r, theme: e }) => { + r( + { accent: (t) => ({ "accent-color": N(t) }) }, + { values: re(e("accentColor")), type: ["color", "any"] } + ); + }, + opacity: P("opacity", [["opacity", ["opacity"]]]), + backgroundBlendMode: ({ addUtilities: r }) => { + r({ + ".bg-blend-normal": { "background-blend-mode": "normal" }, + ".bg-blend-multiply": { "background-blend-mode": "multiply" }, + ".bg-blend-screen": { "background-blend-mode": "screen" }, + ".bg-blend-overlay": { "background-blend-mode": "overlay" }, + ".bg-blend-darken": { "background-blend-mode": "darken" }, + ".bg-blend-lighten": { "background-blend-mode": "lighten" }, + ".bg-blend-color-dodge": { "background-blend-mode": "color-dodge" }, + ".bg-blend-color-burn": { "background-blend-mode": "color-burn" }, + ".bg-blend-hard-light": { "background-blend-mode": "hard-light" }, + ".bg-blend-soft-light": { "background-blend-mode": "soft-light" }, + ".bg-blend-difference": { "background-blend-mode": "difference" }, + ".bg-blend-exclusion": { "background-blend-mode": "exclusion" }, + ".bg-blend-hue": { "background-blend-mode": "hue" }, + ".bg-blend-saturation": { "background-blend-mode": "saturation" }, + ".bg-blend-color": { "background-blend-mode": "color" }, + ".bg-blend-luminosity": { "background-blend-mode": "luminosity" }, + }); + }, + mixBlendMode: ({ addUtilities: r }) => { + r({ + ".mix-blend-normal": { "mix-blend-mode": "normal" }, + ".mix-blend-multiply": { "mix-blend-mode": "multiply" }, + ".mix-blend-screen": { "mix-blend-mode": "screen" }, + ".mix-blend-overlay": { "mix-blend-mode": "overlay" }, + ".mix-blend-darken": { "mix-blend-mode": "darken" }, + ".mix-blend-lighten": { "mix-blend-mode": "lighten" }, + ".mix-blend-color-dodge": { "mix-blend-mode": "color-dodge" }, + ".mix-blend-color-burn": { "mix-blend-mode": "color-burn" }, + ".mix-blend-hard-light": { "mix-blend-mode": "hard-light" }, + ".mix-blend-soft-light": { "mix-blend-mode": "soft-light" }, + ".mix-blend-difference": { "mix-blend-mode": "difference" }, + ".mix-blend-exclusion": { "mix-blend-mode": "exclusion" }, + ".mix-blend-hue": { "mix-blend-mode": "hue" }, + ".mix-blend-saturation": { "mix-blend-mode": "saturation" }, + ".mix-blend-color": { "mix-blend-mode": "color" }, + ".mix-blend-luminosity": { "mix-blend-mode": "luminosity" }, + ".mix-blend-plus-darker": { "mix-blend-mode": "plus-darker" }, + ".mix-blend-plus-lighter": { "mix-blend-mode": "plus-lighter" }, + }); + }, + boxShadow: (() => { + let r = Ge("boxShadow"), + e = [ + "var(--tw-ring-offset-shadow, 0 0 #0000)", + "var(--tw-ring-shadow, 0 0 #0000)", + "var(--tw-shadow)", + ].join(", "); + return function ({ matchUtilities: t, addDefaults: i, theme: n }) { + (i("box-shadow", { + "--tw-ring-offset-shadow": "0 0 #0000", + "--tw-ring-shadow": "0 0 #0000", + "--tw-shadow": "0 0 #0000", + "--tw-shadow-colored": "0 0 #0000", + }), + t( + { + shadow: (a) => { + a = r(a); + let s = xi(a); + for (let o of s) !o.valid || (o.color = "var(--tw-shadow-color)"); + return { + "@defaults box-shadow": {}, + "--tw-shadow": a === "none" ? "0 0 #0000" : a, + "--tw-shadow-colored": a === "none" ? "0 0 #0000" : Lu(s), + "box-shadow": e, + }; + }, + }, + { values: n("boxShadow"), type: ["shadow"] } + )); + }; + })(), + boxShadowColor: ({ matchUtilities: r, theme: e }) => { + r( + { + shadow: (t) => ({ + "--tw-shadow-color": N(t), + "--tw-shadow": "var(--tw-shadow-colored)", + }), + }, + { values: re(e("boxShadowColor")), type: ["color", "any"] } + ); + }, + outlineStyle: ({ addUtilities: r }) => { + r({ + ".outline-none": { outline: "2px solid transparent", "outline-offset": "2px" }, + ".outline": { "outline-style": "solid" }, + ".outline-dashed": { "outline-style": "dashed" }, + ".outline-dotted": { "outline-style": "dotted" }, + ".outline-double": { "outline-style": "double" }, + }); + }, + outlineWidth: P("outlineWidth", [["outline", ["outline-width"]]], { + type: ["length", "number", "percentage"], + }), + outlineOffset: P("outlineOffset", [["outline-offset", ["outline-offset"]]], { + type: ["length", "number", "percentage", "any"], + supportsNegativeValues: !0, + }), + outlineColor: ({ matchUtilities: r, theme: e }) => { + r( + { outline: (t) => ({ "outline-color": N(t) }) }, + { values: re(e("outlineColor")), type: ["color", "any"] } + ); + }, + ringWidth: ({ matchUtilities: r, addDefaults: e, addUtilities: t, theme: i, config: n }) => { + let a = (() => { + if (K(n(), "respectDefaultRingColorOpacity")) return i("ringColor.DEFAULT"); + let s = i("ringOpacity.DEFAULT", "0.5"); + return i("ringColor")?.DEFAULT + ? Ie(i("ringColor")?.DEFAULT, s, `rgb(147 197 253 / ${s})`) + : `rgb(147 197 253 / ${s})`; + })(); + (e("ring-width", { + "--tw-ring-inset": " ", + "--tw-ring-offset-width": i("ringOffsetWidth.DEFAULT", "0px"), + "--tw-ring-offset-color": i("ringOffsetColor.DEFAULT", "#fff"), + "--tw-ring-color": a, + "--tw-ring-offset-shadow": "0 0 #0000", + "--tw-ring-shadow": "0 0 #0000", + "--tw-shadow": "0 0 #0000", + "--tw-shadow-colored": "0 0 #0000", + }), + r( + { + ring: (s) => ({ + "@defaults ring-width": {}, + "--tw-ring-offset-shadow": + "var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)", + "--tw-ring-shadow": `var(--tw-ring-inset) 0 0 0 calc(${s} + var(--tw-ring-offset-width)) var(--tw-ring-color)`, + "box-shadow": [ + "var(--tw-ring-offset-shadow)", + "var(--tw-ring-shadow)", + "var(--tw-shadow, 0 0 #0000)", + ].join(", "), + }), + }, + { values: i("ringWidth"), type: "length" } + ), + t({ ".ring-inset": { "@defaults ring-width": {}, "--tw-ring-inset": "inset" } })); + }, + ringColor: ({ matchUtilities: r, theme: e, corePlugins: t }) => { + r( + { + ring: (i) => + t("ringOpacity") + ? se({ color: i, property: "--tw-ring-color", variable: "--tw-ring-opacity" }) + : { "--tw-ring-color": N(i) }, + }, + { + values: Object.fromEntries( + Object.entries(re(e("ringColor"))).filter(([i]) => i !== "DEFAULT") + ), + type: ["color", "any"], + } + ); + }, + ringOpacity: (r) => { + let { config: e } = r; + return P("ringOpacity", [["ring-opacity", ["--tw-ring-opacity"]]], { + filterDefault: !K(e(), "respectDefaultRingColorOpacity"), + })(r); + }, + ringOffsetWidth: P("ringOffsetWidth", [["ring-offset", ["--tw-ring-offset-width"]]], { + type: "length", + }), + ringOffsetColor: ({ matchUtilities: r, theme: e }) => { + r( + { "ring-offset": (t) => ({ "--tw-ring-offset-color": N(t) }) }, + { values: re(e("ringOffsetColor")), type: ["color", "any"] } + ); + }, + blur: ({ matchUtilities: r, theme: e }) => { + r( + { blur: (t) => ({ "--tw-blur": `blur(${t})`, "@defaults filter": {}, filter: Be }) }, + { values: e("blur") } + ); + }, + brightness: ({ matchUtilities: r, theme: e }) => { + r( + { + brightness: (t) => ({ + "--tw-brightness": `brightness(${t})`, + "@defaults filter": {}, + filter: Be, + }), + }, + { values: e("brightness") } + ); + }, + contrast: ({ matchUtilities: r, theme: e }) => { + r( + { + contrast: (t) => ({ + "--tw-contrast": `contrast(${t})`, + "@defaults filter": {}, + filter: Be, + }), + }, + { values: e("contrast") } + ); + }, + dropShadow: ({ matchUtilities: r, theme: e }) => { + r( + { + "drop-shadow": (t) => ({ + "--tw-drop-shadow": Array.isArray(t) + ? t.map((i) => `drop-shadow(${i})`).join(" ") + : `drop-shadow(${t})`, + "@defaults filter": {}, + filter: Be, + }), + }, + { values: e("dropShadow") } + ); + }, + grayscale: ({ matchUtilities: r, theme: e }) => { + r( + { + grayscale: (t) => ({ + "--tw-grayscale": `grayscale(${t})`, + "@defaults filter": {}, + filter: Be, + }), + }, + { values: e("grayscale") } + ); + }, + hueRotate: ({ matchUtilities: r, theme: e }) => { + r( + { + "hue-rotate": (t) => ({ + "--tw-hue-rotate": `hue-rotate(${t})`, + "@defaults filter": {}, + filter: Be, + }), + }, + { values: e("hueRotate"), supportsNegativeValues: !0 } + ); + }, + invert: ({ matchUtilities: r, theme: e }) => { + r( + { invert: (t) => ({ "--tw-invert": `invert(${t})`, "@defaults filter": {}, filter: Be }) }, + { values: e("invert") } + ); + }, + saturate: ({ matchUtilities: r, theme: e }) => { + r( + { + saturate: (t) => ({ + "--tw-saturate": `saturate(${t})`, + "@defaults filter": {}, + filter: Be, + }), + }, + { values: e("saturate") } + ); + }, + sepia: ({ matchUtilities: r, theme: e }) => { + r( + { sepia: (t) => ({ "--tw-sepia": `sepia(${t})`, "@defaults filter": {}, filter: Be }) }, + { values: e("sepia") } + ); + }, + filter: ({ addDefaults: r, addUtilities: e }) => { + (r("filter", { + "--tw-blur": " ", + "--tw-brightness": " ", + "--tw-contrast": " ", + "--tw-grayscale": " ", + "--tw-hue-rotate": " ", + "--tw-invert": " ", + "--tw-saturate": " ", + "--tw-sepia": " ", + "--tw-drop-shadow": " ", + }), + e({ + ".filter": { "@defaults filter": {}, filter: Be }, + ".filter-none": { filter: "none" }, + })); + }, + backdropBlur: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-blur": (t) => ({ + "--tw-backdrop-blur": `blur(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropBlur") } + ); + }, + backdropBrightness: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-brightness": (t) => ({ + "--tw-backdrop-brightness": `brightness(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropBrightness") } + ); + }, + backdropContrast: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-contrast": (t) => ({ + "--tw-backdrop-contrast": `contrast(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropContrast") } + ); + }, + backdropGrayscale: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-grayscale": (t) => ({ + "--tw-backdrop-grayscale": `grayscale(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropGrayscale") } + ); + }, + backdropHueRotate: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-hue-rotate": (t) => ({ + "--tw-backdrop-hue-rotate": `hue-rotate(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropHueRotate"), supportsNegativeValues: !0 } + ); + }, + backdropInvert: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-invert": (t) => ({ + "--tw-backdrop-invert": `invert(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropInvert") } + ); + }, + backdropOpacity: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-opacity": (t) => ({ + "--tw-backdrop-opacity": `opacity(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropOpacity") } + ); + }, + backdropSaturate: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-saturate": (t) => ({ + "--tw-backdrop-saturate": `saturate(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropSaturate") } + ); + }, + backdropSepia: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-sepia": (t) => ({ + "--tw-backdrop-sepia": `sepia(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropSepia") } + ); + }, + backdropFilter: ({ addDefaults: r, addUtilities: e }) => { + (r("backdrop-filter", { + "--tw-backdrop-blur": " ", + "--tw-backdrop-brightness": " ", + "--tw-backdrop-contrast": " ", + "--tw-backdrop-grayscale": " ", + "--tw-backdrop-hue-rotate": " ", + "--tw-backdrop-invert": " ", + "--tw-backdrop-opacity": " ", + "--tw-backdrop-saturate": " ", + "--tw-backdrop-sepia": " ", + }), + e({ + ".backdrop-filter": { "@defaults backdrop-filter": {}, "backdrop-filter": Fe }, + ".backdrop-filter-none": { "backdrop-filter": "none" }, + })); + }, + transitionProperty: ({ matchUtilities: r, theme: e }) => { + let t = e("transitionTimingFunction.DEFAULT"), + i = e("transitionDuration.DEFAULT"); + r( + { + transition: (n) => ({ + "transition-property": n, + ...(n === "none" + ? {} + : { "transition-timing-function": t, "transition-duration": i }), + }), + }, + { values: e("transitionProperty") } + ); + }, + transitionDelay: P("transitionDelay", [["delay", ["transitionDelay"]]]), + transitionDuration: P("transitionDuration", [["duration", ["transitionDuration"]]], { + filterDefault: !0, + }), + transitionTimingFunction: P("transitionTimingFunction", [["ease", ["transitionTimingFunction"]]], { + filterDefault: !0, + }), + willChange: P("willChange", [["will-change", ["will-change"]]]), + contain: ({ addDefaults: r, addUtilities: e }) => { + let t = + "var(--tw-contain-size) var(--tw-contain-layout) var(--tw-contain-paint) var(--tw-contain-style)"; + (r("contain", { + "--tw-contain-size": " ", + "--tw-contain-layout": " ", + "--tw-contain-paint": " ", + "--tw-contain-style": " ", + }), + e({ + ".contain-none": { contain: "none" }, + ".contain-content": { contain: "content" }, + ".contain-strict": { contain: "strict" }, + ".contain-size": { "@defaults contain": {}, "--tw-contain-size": "size", contain: t }, + ".contain-inline-size": { + "@defaults contain": {}, + "--tw-contain-size": "inline-size", + contain: t, + }, + ".contain-layout": { + "@defaults contain": {}, + "--tw-contain-layout": "layout", + contain: t, + }, + ".contain-paint": { + "@defaults contain": {}, + "--tw-contain-paint": "paint", + contain: t, + }, + ".contain-style": { + "@defaults contain": {}, + "--tw-contain-style": "style", + contain: t, + }, + })); + }, + content: P("content", [["content", ["--tw-content", ["content", "var(--tw-content)"]]]]), + forcedColorAdjust: ({ addUtilities: r }) => { + r({ + ".forced-color-adjust-auto": { "forced-color-adjust": "auto" }, + ".forced-color-adjust-none": { "forced-color-adjust": "none" }, + }); + }, + })); + }); + function h2(r) { + if (r === void 0) return !1; + if (r === "true" || r === "1") return !0; + if (r === "false" || r === "0") return !1; + if (r === "*") return !0; + let e = r.split(",").map((t) => t.split(":")[0]); + return e.includes("-tailwindcss") ? !1 : !!e.includes("tailwindcss"); + } + var Pe, + Ad, + _d, + vn, + Za, + He, + ti, + lt = C(() => { + l(); + ((Pe = + typeof h != "undefined" + ? { NODE_ENV: "production", DEBUG: h2(h.env.DEBUG) } + : { NODE_ENV: "production", DEBUG: !1 }), + (Ad = new Map()), + (_d = new Map()), + (vn = new Map()), + (Za = new Map()), + (He = new String("*")), + (ti = Symbol("__NONE__"))); + }); + function zt(r) { + let e = [], + t = !1; + for (let i = 0; i < r.length; i++) { + let n = r[i]; + if (n === ":" && !t && e.length === 0) return !1; + if ((m2.has(n) && r[i - 1] !== "\\" && (t = !t), !t && r[i - 1] !== "\\")) { + if (Od.has(n)) e.push(n); + else if (Ed.has(n)) { + let a = Ed.get(n); + if (e.length <= 0 || e.pop() !== a) return !1; + } + } + } + return !(e.length > 0); + } + var Od, + Ed, + m2, + eo = C(() => { + l(); + ((Od = new Map([ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ])), + (Ed = new Map(Array.from(Od.entries()).map(([r, e]) => [e, r]))), + (m2 = new Set(['"', "'", "`"]))); + }); + function jt(r) { + let [e] = Td(r); + return (e.forEach(([t, i]) => t.removeChild(i)), r.nodes.push(...e.map(([, t]) => t)), r); + } + function Td(r) { + let e = [], + t = null; + for (let i of r.nodes) + if (i.type === "combinator") ((e = e.filter(([, n]) => ro(n).includes("jumpable"))), (t = null)); + else if (i.type === "pseudo") { + g2(i) ? ((t = i), e.push([r, i, null])) : t && y2(i, t) ? e.push([r, i, t]) : (t = null); + for (let n of i.nodes ?? []) { + let [a, s] = Td(n); + ((t = s || t), e.push(...a)); + } + } + return [e, t]; + } + function Pd(r) { + return r.value.startsWith("::") || to[r.value] !== void 0; + } + function g2(r) { + return Pd(r) && ro(r).includes("terminal"); + } + function y2(r, e) { + return r.type !== "pseudo" || Pd(r) ? !1 : ro(e).includes("actionable"); + } + function ro(r) { + return to[r.value] ?? to.__default__; + } + var to, + xn = C(() => { + l(); + to = { + "::after": ["terminal", "jumpable"], + "::backdrop": ["terminal", "jumpable"], + "::before": ["terminal", "jumpable"], + "::cue": ["terminal"], + "::cue-region": ["terminal"], + "::first-letter": ["terminal", "jumpable"], + "::first-line": ["terminal", "jumpable"], + "::grammar-error": ["terminal"], + "::marker": ["terminal", "jumpable"], + "::part": ["terminal", "actionable"], + "::placeholder": ["terminal", "jumpable"], + "::selection": ["terminal", "jumpable"], + "::slotted": ["terminal"], + "::spelling-error": ["terminal"], + "::target-text": ["terminal"], + "::file-selector-button": ["terminal", "actionable"], + "::deep": ["actionable"], + "::v-deep": ["actionable"], + "::ng-deep": ["actionable"], + ":after": ["terminal", "jumpable"], + ":before": ["terminal", "jumpable"], + ":first-letter": ["terminal", "jumpable"], + ":first-line": ["terminal", "jumpable"], + ":where": [], + ":is": [], + ":has": [], + __default__: ["terminal", "actionable"], + }; + }); + function Vt(r, { context: e, candidate: t }) { + let i = e?.tailwindConfig.prefix ?? "", + n = r.map((s) => { + let o = (0, Le.default)().astSync(s.format); + return { ...s, ast: s.respectPrefix ? Nt(i, o) : o }; + }), + a = Le.default.root({ nodes: [Le.default.selector({ nodes: [Le.default.className({ value: ce(t) })] })] }); + for (let { ast: s } of n) + (([a, s] = b2(a, s)), s.walkNesting((o) => o.replaceWith(...a.nodes[0].nodes)), (a = s)); + return a; + } + function Id(r) { + let e = []; + for (; r.prev() && r.prev().type !== "combinator"; ) r = r.prev(); + for (; r && r.type !== "combinator"; ) (e.push(r), (r = r.next())); + return e; + } + function w2(r) { + return ( + r.sort((e, t) => + e.type === "tag" && t.type === "class" + ? -1 + : e.type === "class" && t.type === "tag" + ? 1 + : e.type === "class" && t.type === "pseudo" && t.value.startsWith("::") + ? -1 + : e.type === "pseudo" && e.value.startsWith("::") && t.type === "class" + ? 1 + : r.index(e) - r.index(t) + ), + r + ); + } + function no(r, e) { + let t = !1; + (r.walk((i) => { + if (i.type === "class" && i.value === e) return ((t = !0), !1); + }), + t || r.remove()); + } + function kn(r, e, { context: t, candidate: i, base: n }) { + let a = t?.tailwindConfig?.separator ?? ":"; + n = n ?? ae(i, a).pop(); + let s = (0, Le.default)().astSync(r); + if ( + (s.walkClasses((f) => { + f.raws && f.value.includes(n) && (f.raws.value = ce((0, Dd.default)(f.raws.value))); + }), + s.each((f) => no(f, n)), + s.length === 0) + ) + return null; + let o = Array.isArray(e) ? Vt(e, { context: t, candidate: i }) : e; + if (o === null) return s.toString(); + let u = Le.default.comment({ value: "/*__simple__*/" }), + c = Le.default.comment({ value: "/*__simple__*/" }); + return ( + s.walkClasses((f) => { + if (f.value !== n) return; + let d = f.parent, + p = o.nodes[0].nodes; + if (d.nodes.length === 1) { + f.replaceWith(...p); + return; + } + let m = Id(f); + (d.insertBefore(m[0], u), d.insertAfter(m[m.length - 1], c)); + for (let x of p) d.insertBefore(m[0], x.clone()); + (f.remove(), (m = Id(u))); + let b = d.index(u); + (d.nodes.splice(b, m.length, ...w2(Le.default.selector({ nodes: m })).nodes), u.remove(), c.remove()); + }), + s.walkPseudos((f) => { + f.value === io && f.replaceWith(f.nodes); + }), + s.each((f) => jt(f)), + s.toString() + ); + } + function b2(r, e) { + let t = []; + return ( + r.walkPseudos((i) => { + i.value === io && t.push({ pseudo: i, value: i.nodes[0].toString() }); + }), + e.walkPseudos((i) => { + if (i.value !== io) return; + let n = i.nodes[0].toString(), + a = t.find((c) => c.value === n); + if (!a) return; + let s = [], + o = i.next(); + for (; o && o.type !== "combinator"; ) (s.push(o), (o = o.next())); + let u = o; + (a.pseudo.parent.insertAfter(a.pseudo, Le.default.selector({ nodes: s.map((c) => c.clone()) })), + i.remove(), + s.forEach((c) => c.remove()), + u && u.type === "combinator" && u.remove()); + }), + [r, e] + ); + } + var Le, + Dd, + io, + so = C(() => { + l(); + ((Le = X(Me())), (Dd = X(Ki()))); + $t(); + dn(); + xn(); + _t(); + io = ":merge"; + }); + function Sn(r, e) { + let t = (0, ao.default)().astSync(r); + return ( + t.each((i) => { + ((i.nodes[0].type === "pseudo" && + i.nodes[0].value === ":is" && + i.nodes.every((a) => a.type !== "combinator")) || + (i.nodes = [ao.default.pseudo({ value: ":is", nodes: [i.clone()] })]), + jt(i)); + }), + `${e} ${t.toString()}` + ); + } + var ao, + oo = C(() => { + l(); + ao = X(Me()); + xn(); + }); + function lo(r) { + return v2.transformSync(r); + } + function* x2(r) { + let e = 1 / 0; + for (; e >= 0; ) { + let t, + i = !1; + if (e === 1 / 0 && r.endsWith("]")) { + let s = r.indexOf("["); + r[s - 1] === "-" ? (t = s - 1) : r[s - 1] === "/" ? ((t = s - 1), (i = !0)) : (t = -1); + } else e === 1 / 0 && r.includes("/") ? ((t = r.lastIndexOf("/")), (i = !0)) : (t = r.lastIndexOf("-", e)); + if (t < 0) break; + let n = r.slice(0, t), + a = r.slice(i ? t : t + 1); + ((e = t - 1), !(n === "" || a === "/") && (yield [n, a])); + } + } + function k2(r, e) { + if (r.length === 0 || e.tailwindConfig.prefix === "") return r; + for (let t of r) { + let [i] = t; + if (i.options.respectPrefix) { + let n = j.root({ nodes: [t[1].clone()] }), + a = t[1].raws.tailwind.classCandidate; + (n.walkRules((s) => { + let o = a.startsWith("-"); + s.selector = Nt(e.tailwindConfig.prefix, s.selector, o); + }), + (t[1] = n.nodes[0])); + } + } + return r; + } + function S2(r, e) { + if (r.length === 0) return r; + let t = []; + function i(n) { + return n.parent && n.parent.type === "atrule" && n.parent.name === "keyframes"; + } + for (let [n, a] of r) { + let s = j.root({ nodes: [a.clone()] }); + (s.walkRules((o) => { + if (i(o)) return; + let u = (0, Cn.default)().astSync(o.selector); + (u.each((c) => no(c, e)), + Ju(u, (c) => (c === e ? `!${c}` : c)), + (o.selector = u.toString()), + o.walkDecls((c) => (c.important = !0))); + }), + t.push([{ ...n, important: !0 }, s.nodes[0]])); + } + return t; + } + function C2(r, e, t) { + if (e.length === 0) return e; + let i = { modifier: null, value: ti }; + { + let [n, ...a] = ae(r, "/"); + if ( + (a.length > 1 && ((n = n + "/" + a.slice(0, -1).join("/")), (a = a.slice(-1))), + a.length && + !t.variantMap.has(r) && + ((r = n), (i.modifier = a[0]), !K(t.tailwindConfig, "generalizedModifiers"))) + ) + return []; + } + if (r.endsWith("]") && !r.startsWith("[")) { + let n = /(.)(-?)\[(.*)\]/g.exec(r); + if (n) { + let [, a, s, o] = n; + if (a === "@" && s === "-") return []; + if (a !== "@" && s === "") return []; + ((r = r.replace(`${s}[${o}]`, "")), (i.value = o)); + } + } + if (co(r) && !t.variantMap.has(r)) { + let n = t.offsets.recordVariant(r), + a = L(r.slice(1, -1)), + s = ae(a, ","); + if (s.length > 1) return []; + if (!s.every(En)) return []; + let o = s.map((u, c) => [t.offsets.applyParallelOffset(n, c), ri(u.trim())]); + t.variantMap.set(r, o); + } + if (t.variantMap.has(r)) { + let n = co(r), + a = t.variantOptions.get(r)?.[Zr] ?? {}, + s = t.variantMap.get(r).slice(), + o = [], + u = (() => !(n || a.respectPrefix === !1))(); + for (let [c, f] of e) { + if (c.layer === "user") continue; + let d = j.root({ nodes: [f.clone()] }); + for (let [p, m, b] of s) { + let w = function () { + x.raws.neededBackup || + ((x.raws.neededBackup = !0), + x.walkRules((E) => (E.raws.originalSelector = E.selector))); + }, + k = function (E) { + return ( + w(), + x.each((I) => { + I.type === "rule" && + (I.selectors = I.selectors.map((q) => + E({ + get className() { + return lo(q); + }, + selector: q, + }) + )); + }), + x + ); + }, + x = (b ?? d).clone(), + y = [], + S = m({ + get container() { + return (w(), x); + }, + separator: t.tailwindConfig.separator, + modifySelectors: k, + wrap(E) { + let I = x.nodes; + (x.removeAll(), E.append(I), x.append(E)); + }, + format(E) { + y.push({ format: E, respectPrefix: u }); + }, + args: i, + }); + if (Array.isArray(S)) { + for (let [E, I] of S.entries()) s.push([t.offsets.applyParallelOffset(p, E), I, x.clone()]); + continue; + } + if ((typeof S == "string" && y.push({ format: S, respectPrefix: u }), S === null)) continue; + (x.raws.neededBackup && + (delete x.raws.neededBackup, + x.walkRules((E) => { + let I = E.raws.originalSelector; + if (!I || (delete E.raws.originalSelector, I === E.selector)) return; + let q = E.selector, + R = (0, Cn.default)((J) => { + J.walkClasses((ue) => { + ue.value = `${r}${t.tailwindConfig.separator}${ue.value}`; + }); + }).processSync(I); + (y.push({ format: q.replace(R, "&"), respectPrefix: u }), (E.selector = I)); + })), + (x.nodes[0].raws.tailwind = { ...x.nodes[0].raws.tailwind, parentLayer: c.layer })); + let _ = [ + { + ...c, + sort: t.offsets.applyVariantOffset(c.sort, p, Object.assign(i, t.variantOptions.get(r))), + collectedFormats: (c.collectedFormats ?? []).concat(y), + }, + x.nodes[0], + ]; + o.push(_); + } + } + return o; + } + return []; + } + function uo(r, e, t = {}) { + return !ie(r) && !Array.isArray(r) + ? [[r], t] + : Array.isArray(r) + ? uo(r[0], e, r[1]) + : (e.has(r) || e.set(r, Lt(r)), [e.get(r), t]); + } + function _2(r) { + return A2.test(r); + } + function O2(r) { + if (!r.includes("://")) return !1; + try { + let e = new URL(r); + return e.scheme !== "" && e.host !== ""; + } catch (e) { + return !1; + } + } + function qd(r) { + let e = !0; + return ( + r.walkDecls((t) => { + if (!Rd(t.prop, t.value)) return ((e = !1), !1); + }), + e + ); + } + function Rd(r, e) { + if (O2(`${r}:${e}`)) return !1; + try { + return (j.parse(`a{${r}:${e}}`).toResult(), !0); + } catch (t) { + return !1; + } + } + function E2(r, e) { + let [, t, i] = r.match(/^\[([a-zA-Z0-9-_]+):(\S+)\]$/) ?? []; + if (i === void 0 || !_2(t) || !zt(i)) return null; + let n = L(i, { property: t }); + return Rd(t, n) + ? [ + [ + { sort: e.offsets.arbitraryProperty(r), layer: "utilities", options: { respectImportant: !0 } }, + () => ({ [Ja(r)]: { [t]: n } }), + ], + ] + : null; + } + function* T2(r, e) { + (e.candidateRuleMap.has(r) && (yield [e.candidateRuleMap.get(r), "DEFAULT"]), + yield* (function* (o) { + o !== null && (yield [o, "DEFAULT"]); + })(E2(r, e))); + let t = r, + i = !1, + n = e.tailwindConfig.prefix, + a = n.length, + s = t.startsWith(n) || t.startsWith(`-${n}`); + (t[a] === "-" && s && ((i = !0), (t = n + t.slice(a + 1))), + i && e.candidateRuleMap.has(t) && (yield [e.candidateRuleMap.get(t), "-DEFAULT"])); + for (let [o, u] of x2(t)) e.candidateRuleMap.has(o) && (yield [e.candidateRuleMap.get(o), i ? `-${u}` : u]); + } + function P2(r, e) { + return r === He ? [He] : ae(r, e); + } + function* D2(r, e) { + for (let t of r) + ((t[1].raws.tailwind = { + ...t[1].raws.tailwind, + classCandidate: e, + preserveSource: t[0].options?.preserveSource ?? !1, + }), + yield t); + } + function* fo(r, e) { + let t = e.tailwindConfig.separator, + [i, ...n] = P2(r, t).reverse(), + a = !1; + i.startsWith("!") && ((a = !0), (i = i.slice(1))); + for (let s of T2(i, e)) { + let o = [], + u = new Map(), + [c, f] = s, + d = c.length === 1; + for (let [p, m] of c) { + let b = []; + if (typeof m == "function") + for (let x of [].concat(m(f, { isOnlyPlugin: d }))) { + let [y, w] = uo(x, e.postCssNodeCache); + for (let k of y) b.push([{ ...p, options: { ...p.options, ...w } }, k]); + } + else if (f === "DEFAULT" || f === "-DEFAULT") { + let x = m, + [y, w] = uo(x, e.postCssNodeCache); + for (let k of y) b.push([{ ...p, options: { ...p.options, ...w } }, k]); + } + if (b.length > 0) { + let x = Array.from(ys(p.options?.types ?? [], f, p.options ?? {}, e.tailwindConfig)).map( + ([y, w]) => w + ); + (x.length > 0 && u.set(b, x), o.push(b)); + } + } + if (co(f)) { + if (o.length > 1) { + let b = function (y) { + return y.length === 1 + ? y[0] + : y.find((w) => { + let k = u.get(w); + return w.some(([{ options: S }, _]) => + qd(_) + ? S.types.some(({ type: E, preferOnConflict: I }) => k.includes(E) && I) + : !1 + ); + }); + }, + [p, m] = o.reduce( + (y, w) => ( + w.some(([{ options: S }]) => S.types.some(({ type: _ }) => _ === "any")) + ? y[0].push(w) + : y[1].push(w), + y + ), + [[], []] + ), + x = b(m) ?? b(p); + if (x) o = [x]; + else { + let y = o.map((k) => new Set([...(u.get(k) ?? [])])); + for (let k of y) + for (let S of k) { + let _ = !1; + for (let E of y) k !== E && E.has(S) && (E.delete(S), (_ = !0)); + _ && k.delete(S); + } + let w = []; + for (let [k, S] of y.entries()) + for (let _ of S) { + let E = o[k] + .map(([, I]) => I) + .flat() + .map((I) => + I.toString() + .split( + ` +` + ) + .slice(1, -1) + .map((q) => q.trim()) + .map((q) => ` ${q}`).join(` +`) + ).join(` -`);w.push(` Use \`${r.replace("[",`[${_}:`)}\` for \`${E.trim()}\``);break}F.warn([`The class \`${r}\` is ambiguous and matches multiple utilities.`,...w,`If this is content and not a class, replace it with \`${r.replace("[","[").replace("]","]")}\` to silence this warning.`]);continue}}o=o.map(p=>p.filter(m=>qd(m[1])))}o=o.flat(),o=Array.from(D2(o,i)),o=k2(o,e),a&&(o=S2(o,i));for(let p of n)o=C2(p,o,e);for(let p of o)p[1].raws.tailwind={...p[1].raws.tailwind,candidate:r},p=I2(p,{context:e,candidate:r}),p!==null&&(yield p)}}function I2(r,{context:e,candidate:t}){if(!r[0].collectedFormats)return r;let i=!0,n;try{n=Vt(r[0].collectedFormats,{context:e,candidate:t})}catch{return null}let a=j.root({nodes:[r[1].clone()]});return a.walkRules(s=>{if(!An(s))try{let o=kn(s.selector,n,{candidate:t,context:e});if(o===null){s.remove();return}s.selector=o}catch{return i=!1,!1}}),!i||a.nodes.length===0?null:(r[1]=a.nodes[0],r)}function An(r){return r.parent&&r.parent.type==="atrule"&&r.parent.name==="keyframes"}function q2(r){if(r===!0)return e=>{An(e)||e.walkDecls(t=>{t.parent.type==="rule"&&!An(t.parent)&&(t.important=!0)})};if(typeof r=="string")return e=>{An(e)||(e.selectors=e.selectors.map(t=>Sn(t,r)))}}function _n(r,e,t=!1){let i=[],n=q2(e.tailwindConfig.important);for(let a of r){if(e.notClassCache.has(a))continue;if(e.candidateRuleCache.has(a)){i=i.concat(Array.from(e.candidateRuleCache.get(a)));continue}let s=Array.from(fo(a,e));if(s.length===0){e.notClassCache.add(a);continue}e.classCache.set(a,s);let o=e.candidateRuleCache.get(a)??new Set;e.candidateRuleCache.set(a,o);for(let u of s){let[{sort:c,options:f},d]=u;if(f.respectImportant&&n){let m=j.root({nodes:[d.clone()]});m.walkRules(n),d=m.nodes[0]}let p=[c,t?d.clone():d];o.add(p),e.ruleCache.add(p),i.push(p)}}return i}function co(r){return r.startsWith("[")&&r.endsWith("]")}var Cn,v2,A2,On=C(()=>{l();st();Cn=X(Me());Qa();At();dn();hr();Oe();lt();so();Xa();dr();ei();eo();_t();je();oo();v2=(0,Cn.default)(r=>r.first.filter(({type:e})=>e==="class").pop().value);A2=/^[a-z_-]/});var Md,Bd=C(()=>{l();Md={}});function R2(r){try{return Md.createHash("md5").update(r,"utf-8").digest("binary")}catch(e){return""}}function Fd(r,e){let t=e.toString();if(!t.includes("@tailwind"))return!1;let i=Za.get(r),n=R2(t),a=i!==n;return Za.set(r,n),a}var Ld=C(()=>{l();Bd();lt()});function Tn(r){return(r>0n)-(r<0n)}var Nd=C(()=>{l()});function $d(r,e){let t=0n,i=0n;for(let[n,a]of e)r&n&&(t=t|n,i=i|a);return r&~t|i}var zd=C(()=>{l()});function jd(r){let e=null;for(let t of r)e=e??t,e=e>t?e:t;return e}function M2(r,e){let t=r.length,i=e.length,n=t{l();Nd();zd();po=class{constructor(){this.offsets={defaults:0n,base:0n,components:0n,utilities:0n,variants:0n,user:0n},this.layerPositions={defaults:0n,base:1n,components:2n,utilities:3n,user:4n,variants:5n},this.reservedVariantBits=0n,this.variantOffsets=new Map}create(e){return{layer:e,parentLayer:e,arbitrary:0n,variants:0n,parallelIndex:0n,index:this.offsets[e]++,propertyOffset:0n,property:"",options:[]}}arbitraryProperty(e){return{...this.create("utilities"),arbitrary:1n,property:e}}forVariant(e,t=0){let i=this.variantOffsets.get(e);if(i===void 0)throw new Error(`Cannot find offset for unknown variant ${e}`);return{...this.create("variants"),variants:i<n.startsWith("[")).sort(([n],[a])=>M2(n,a)),t=e.map(([,n])=>n).sort((n,a)=>Tn(n-a));return e.map(([,n],a)=>[n,t[a]]).filter(([n,a])=>n!==a)}remapArbitraryVariantOffsets(e){let t=this.recalculateVariantOffsets();return t.length===0?e:e.map(i=>{let[n,a]=i;return n={...n,variants:$d(n.variants,t)},[n,a]})}sortArbitraryProperties(e){let t=new Set;for(let[s]of e)s.arbitrary===1n&&t.add(s.property);if(t.size===0)return e;let i=Array.from(t).sort(),n=new Map,a=1n;for(let s of i)n.set(s,a++);return e.map(s=>{let[o,u]=s;return o={...o,propertyOffset:n.get(o.property)??0n},[o,u]})}sort(e){return e=this.remapArbitraryVariantOffsets(e),e=this.sortArbitraryProperties(e),e.sort(([t],[i])=>Tn(this.compare(t,i)))}}});function yo(r,e){let t=r.tailwindConfig.prefix;return typeof t=="function"?t(e):t+e}function Wd({type:r="any",...e}){let t=[].concat(r);return{...e,types:t.map(i=>Array.isArray(i)?{type:i[0],...i[1]}:{type:i,preferOnConflict:!1})}}function B2(r){let e=[],t="",i=0;for(let n=0;n0&&e.push(t.trim()),e=e.filter(n=>n!==""),e}function F2(r,e,{before:t=[]}={}){if(t=[].concat(t),t.length<=0){r.push(e);return}let i=r.length-1;for(let n of t){let a=r.indexOf(n);a!==-1&&(i=Math.min(i,a))}r.splice(i,0,e)}function Gd(r){return Array.isArray(r)?r.flatMap(e=>!Array.isArray(e)&&!ie(e)?e:Lt(e)):Gd([r])}function L2(r,e){return(0,ho.default)(i=>{let n=[];return e&&e(i),i.walkClasses(a=>{n.push(a.value)}),n}).transformSync(r)}function N2(r){r.walkPseudos(e=>{e.value===":not"&&e.remove()})}function $2(r,e={containsNonOnDemandable:!1},t=0){let i=[],n=[];r.type==="rule"?n.push(...r.selectors):r.type==="atrule"&&r.walkRules(a=>n.push(...a.selectors));for(let a of n){let s=L2(a,N2);s.length===0&&(e.containsNonOnDemandable=!0);for(let o of s)i.push(o)}return t===0?[e.containsNonOnDemandable||i.length===0,i]:i}function Pn(r){return Gd(r).flatMap(e=>{let t=new Map,[i,n]=$2(e);return i&&n.unshift(He),n.map(a=>(t.has(e)||t.set(e,e),[a,t.get(e)]))})}function En(r){return r.startsWith("@")||r.includes("&")}function ri(r){r=r.replace(/\n+/g,"").replace(/\s{1,}/g," ").trim();let e=B2(r).map(t=>{if(!t.startsWith("@"))return({format:a})=>a(t);let[,i,n]=/@(\S*)( .+|[({].*)?/g.exec(t);return({wrap:a})=>a(j.atRule({name:i,params:n?.trim()??""}))}).reverse();return t=>{for(let i of e)i(t)}}function z2(r,e,{variantList:t,variantMap:i,offsets:n,classList:a}){function s(p,m){return p?(0,Ud.default)(r,p,m):r}function o(p){return Nt(r.prefix,p)}function u(p,m){return p===He?He:m.respectPrefix?e.tailwindConfig.prefix+p:p}function c(p,m,b={}){let x=Ze(p),y=s(["theme",...x],m);return Ge(x[0])(y,b)}let f=0,d={postcss:j,prefix:o,e:ce,config:s,theme:c,corePlugins:p=>Array.isArray(r.corePlugins)?r.corePlugins.includes(p):s(["corePlugins",p],!0),variants:()=>[],addBase(p){for(let[m,b]of Pn(p)){let x=u(m,{}),y=n.create("base");e.candidateRuleMap.has(x)||e.candidateRuleMap.set(x,[]),e.candidateRuleMap.get(x).push([{sort:y,layer:"base"},b])}},addDefaults(p,m){let b={[`@defaults ${p}`]:m};for(let[x,y]of Pn(b)){let w=u(x,{});e.candidateRuleMap.has(w)||e.candidateRuleMap.set(w,[]),e.candidateRuleMap.get(w).push([{sort:n.create("defaults"),layer:"defaults"},y])}},addComponents(p,m){m=Object.assign({},{preserveSource:!1,respectPrefix:!0,respectImportant:!1},Array.isArray(m)?{}:m);for(let[x,y]of Pn(p)){let w=u(x,m);a.add(w),e.candidateRuleMap.has(w)||e.candidateRuleMap.set(w,[]),e.candidateRuleMap.get(w).push([{sort:n.create("components"),layer:"components",options:m},y])}},addUtilities(p,m){m=Object.assign({},{preserveSource:!1,respectPrefix:!0,respectImportant:!0},Array.isArray(m)?{}:m);for(let[x,y]of Pn(p)){let w=u(x,m);a.add(w),e.candidateRuleMap.has(w)||e.candidateRuleMap.set(w,[]),e.candidateRuleMap.get(w).push([{sort:n.create("utilities"),layer:"utilities",options:m},y])}},matchUtilities:function(p,m){m=Wd({...{respectPrefix:!0,respectImportant:!0,modifiers:!1},...m});let x=n.create("utilities");for(let y in p){let S=function(E,{isOnlyPlugin:I}){let[q,R,J]=gs(m.types,E,m,r);if(q===void 0)return[];if(!m.types.some(({type:ee})=>ee===R))if(I)F.warn([`Unnecessary typehint \`${R}\` in \`${y}-${E}\`.`,`You can safely update it to \`${y}-${E.replace(R+":","")}\`.`]);else return[];if(!zt(q))return[];let ue={get modifier(){return m.modifiers||F.warn(`modifier-used-without-options-for-${y}`,["Your plugin must set `modifiers: true` in its options to support modifiers."]),J}},de=K(r,"generalizedModifiers");return[].concat(de?k(q,ue):k(q)).filter(Boolean).map(ee=>({[hn(y,E)]:ee}))},w=u(y,m),k=p[y];a.add([w,m]);let _=[{sort:x,layer:"utilities",options:m},S];e.candidateRuleMap.has(w)||e.candidateRuleMap.set(w,[]),e.candidateRuleMap.get(w).push(_)}},matchComponents:function(p,m){m=Wd({...{respectPrefix:!0,respectImportant:!1,modifiers:!1},...m});let x=n.create("components");for(let y in p){let S=function(E,{isOnlyPlugin:I}){let[q,R,J]=gs(m.types,E,m,r);if(q===void 0)return[];if(!m.types.some(({type:ee})=>ee===R))if(I)F.warn([`Unnecessary typehint \`${R}\` in \`${y}-${E}\`.`,`You can safely update it to \`${y}-${E.replace(R+":","")}\`.`]);else return[];if(!zt(q))return[];let ue={get modifier(){return m.modifiers||F.warn(`modifier-used-without-options-for-${y}`,["Your plugin must set `modifiers: true` in its options to support modifiers."]),J}},de=K(r,"generalizedModifiers");return[].concat(de?k(q,ue):k(q)).filter(Boolean).map(ee=>({[hn(y,E)]:ee}))},w=u(y,m),k=p[y];a.add([w,m]);let _=[{sort:x,layer:"components",options:m},S];e.candidateRuleMap.has(w)||e.candidateRuleMap.set(w,[]),e.candidateRuleMap.get(w).push(_)}},addVariant(p,m,b={}){m=[].concat(m).map(x=>{if(typeof x!="string")return(y={})=>{let{args:w,modifySelectors:k,container:S,separator:_,wrap:E,format:I}=y,q=x(Object.assign({modifySelectors:k,container:S,separator:_},b.type===mo.MatchVariant&&{args:w,wrap:E,format:I}));if(typeof q=="string"&&!En(q))throw new Error(`Your custom variant \`${p}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`);return Array.isArray(q)?q.filter(R=>typeof R=="string").map(R=>ri(R)):q&&typeof q=="string"&&ri(q)(y)};if(!En(x))throw new Error(`Your custom variant \`${p}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`);return ri(x)}),F2(t,p,b),i.set(p,m),e.variantOptions.set(p,b)},matchVariant(p,m,b){let x=b?.id??++f,y=p==="@",w=K(r,"generalizedModifiers");for(let[S,_]of Object.entries(b?.values??{}))S!=="DEFAULT"&&d.addVariant(y?`${p}${S}`:`${p}-${S}`,({args:E,container:I})=>m(_,w?{modifier:E?.modifier,container:I}:{container:I}),{...b,value:_,id:x,type:mo.MatchVariant,variantInfo:go.Base});let k="DEFAULT"in(b?.values??{});d.addVariant(p,({args:S,container:_})=>S?.value===ti&&!k?null:m(S?.value===ti?b.values.DEFAULT:S?.value??(typeof S=="string"?S:""),w?{modifier:S?.modifier,container:_}:{container:_}),{...b,id:x,type:mo.MatchVariant,variantInfo:go.Dynamic})}};return d}function Dn(r){return wo.has(r)||wo.set(r,new Map),wo.get(r)}function Hd(r,e){let t=!1,i=new Map;for(let n of r){if(!n)continue;let a=Ss.parse(n),s=a.hash?a.href.replace(a.hash,""):a.href;s=a.search?s.replace(a.search,""):s;let o=te.statSync(decodeURIComponent(s),{throwIfNoEntry:!1})?.mtimeMs;!o||((!e.has(n)||o>e.get(n))&&(t=!0),i.set(n,o))}return[t,i]}function Yd(r){r.walkAtRules(e=>{["responsive","variants"].includes(e.name)&&(Yd(e),e.before(e.nodes),e.remove())})}function j2(r){let e=[];return r.each(t=>{t.type==="atrule"&&["responsive","variants"].includes(t.name)&&(t.name="layer",t.params="utilities")}),r.walkAtRules("layer",t=>{if(Yd(t),t.params==="base"){for(let i of t.nodes)e.push(function({addBase:n}){n(i,{respectPrefix:!1})});t.remove()}else if(t.params==="components"){for(let i of t.nodes)e.push(function({addComponents:n}){n(i,{respectPrefix:!1,preserveSource:!0})});t.remove()}else if(t.params==="utilities"){for(let i of t.nodes)e.push(function({addUtilities:n}){n(i,{respectPrefix:!1,preserveSource:!0})});t.remove()}}),e}function V2(r,e){let t=Object.entries({...H,...Sd}).map(([u,c])=>r.tailwindConfig.corePlugins.includes(u)?c:null).filter(Boolean),i=r.tailwindConfig.plugins.map(u=>(u.__isOptionsFunction&&(u=u()),typeof u=="function"?u:u.handler)),n=j2(e),a=[H.childVariant,H.pseudoElementVariants,H.pseudoClassVariants,H.hasVariants,H.ariaVariants,H.dataVariants],s=[H.supportsVariants,H.reducedMotionVariants,H.prefersContrastVariants,H.screenVariants,H.orientationVariants,H.directionVariants,H.darkVariants,H.forcedColorsVariants,H.printVariant];return(r.tailwindConfig.darkMode==="class"||Array.isArray(r.tailwindConfig.darkMode)&&r.tailwindConfig.darkMode[0]==="class")&&(s=[H.supportsVariants,H.reducedMotionVariants,H.prefersContrastVariants,H.darkVariants,H.screenVariants,H.orientationVariants,H.directionVariants,H.forcedColorsVariants,H.printVariant]),[...t,...a,...i,...s,...n]}function U2(r,e){let t=[],i=new Map;e.variantMap=i;let n=new po;e.offsets=n;let a=new Set,s=z2(e.tailwindConfig,e,{variantList:t,variantMap:i,offsets:n,classList:a});for(let f of r)if(Array.isArray(f))for(let d of f)d(s);else f?.(s);n.recordVariants(t,f=>i.get(f).length);for(let[f,d]of i.entries())e.variantMap.set(f,d.map((p,m)=>[n.forVariant(f,m),p]));let o=(e.tailwindConfig.safelist??[]).filter(Boolean);if(o.length>0){let f=[];for(let d of o){if(typeof d=="string"){e.changedContent.push({content:d,extension:"html"});continue}if(d instanceof RegExp){F.warn("root-regex",["Regular expressions in `safelist` work differently in Tailwind CSS v3.0.","Update your `safelist` configuration to eliminate this warning.","https://tailwindcss.com/docs/content-configuration#safelisting-classes"]);continue}f.push(d)}if(f.length>0){let d=new Map,p=e.tailwindConfig.prefix.length,m=f.some(b=>b.pattern.source.includes("!"));for(let b of a){let x=Array.isArray(b)?(()=>{let[y,w]=b,S=Object.keys(w?.values??{}).map(_=>Kr(y,_));return w?.supportsNegativeValues&&(S=[...S,...S.map(_=>"-"+_)],S=[...S,...S.map(_=>_.slice(0,p)+"-"+_.slice(p))]),w.types.some(({type:_})=>_==="color")&&(S=[...S,...S.flatMap(_=>Object.keys(e.tailwindConfig.theme.opacity).map(E=>`${_}/${E}`))]),m&&w?.respectImportant&&(S=[...S,...S.map(_=>"!"+_)]),S})():[b];for(let y of x)for(let{pattern:w,variants:k=[]}of f)if(w.lastIndex=0,d.has(w)||d.set(w,0),!!w.test(y)){d.set(w,d.get(w)+1),e.changedContent.push({content:y,extension:"html"});for(let S of k)e.changedContent.push({content:S+e.tailwindConfig.separator+y,extension:"html"})}}for(let[b,x]of d.entries())x===0&&F.warn([`The safelist pattern \`${b}\` doesn't match any Tailwind CSS classes.`,"Fix this pattern or remove it from your `safelist` configuration.","https://tailwindcss.com/docs/content-configuration#safelisting-classes"])}}let u=[].concat(e.tailwindConfig.darkMode??"media")[1]??"dark",c=[yo(e,u),yo(e,"group"),yo(e,"peer")];e.getClassOrder=function(d){let p=[...d].sort((y,w)=>y===w?0:y[y,null])),b=_n(new Set(p),e,!0);b=e.offsets.sort(b);let x=BigInt(c.length);for(let[,y]of b){let w=y.raws.tailwind.candidate;m.set(w,m.get(w)??x++)}return d.map(y=>{let w=m.get(y)??null,k=c.indexOf(y);return w===null&&k!==-1&&(w=BigInt(k)),[y,w]})},e.getClassList=function(d={}){let p=[];for(let m of a)if(Array.isArray(m)){let[b,x]=m,y=[],w=Object.keys(x?.modifiers??{});x?.types?.some(({type:_})=>_==="color")&&w.push(...Object.keys(e.tailwindConfig.theme.opacity??{}));let k={modifiers:w},S=d.includeMetadata&&w.length>0;for(let[_,E]of Object.entries(x?.values??{})){if(E==null)continue;let I=Kr(b,_);if(p.push(S?[I,k]:I),x?.supportsNegativeValues&&Ke(E)){let q=Kr(b,`-${_}`);y.push(S?[q,k]:q)}}p.push(...y)}else p.push(m);return p},e.getVariants=function(){let d=Math.random().toString(36).substring(7).toUpperCase(),p=[];for(let[m,b]of e.variantOptions.entries())b.variantInfo!==go.Base&&p.push({name:m,isArbitrary:b.type===Symbol.for("MATCH_VARIANT"),values:Object.keys(b.values??{}),hasDash:m!=="@",selectors({modifier:x,value:y}={}){let w=`TAILWINDPLACEHOLDER${d}`,k=j.rule({selector:`.${w}`}),S=j.root({nodes:[k.clone()]}),_=S.toString(),E=(e.variantMap.get(m)??[]).flatMap(([oe,he])=>he),I=[];for(let oe of E){let he=[],ui={args:{modifier:x,value:b.values?.[y]??y},separator:e.tailwindConfig.separator,modifySelectors(Ce){return S.each(ts=>{ts.type==="rule"&&(ts.selectors=ts.selectors.map(mu=>Ce({get className(){return lo(mu)},selector:mu})))}),S},format(Ce){he.push(Ce)},wrap(Ce){he.push(`@${Ce.name} ${Ce.params} { & }`)},container:S},fi=oe(ui);if(he.length>0&&I.push(he),Array.isArray(fi))for(let Ce of fi)he=[],Ce(ui),I.push(he)}let q=[],R=S.toString();_!==R&&(S.walkRules(oe=>{let he=oe.selector,ui=(0,ho.default)(fi=>{fi.walkClasses(Ce=>{Ce.value=`${m}${e.tailwindConfig.separator}${Ce.value}`})}).processSync(he);q.push(he.replace(ui,"&").replace(w,"&"))}),S.walkAtRules(oe=>{q.push(`@${oe.name} (${oe.params}) { & }`)}));let J=!(y in(b.values??{})),ue=b[Zr]??{},de=(()=>!(J||ue.respectPrefix===!1))();I=I.map(oe=>oe.map(he=>({format:he,respectPrefix:de}))),q=q.map(oe=>({format:oe,respectPrefix:de}));let De={candidate:w,context:e},ee=I.map(oe=>kn(`.${w}`,Vt(oe,De),De).replace(`.${w}`,"&").replace("{ & }","").trim());return q.length>0&&ee.push(Vt(q,De).toString().replace(`.${w}`,"&")),ee}});return p}}function Qd(r,e){!r.classCache.has(e)||(r.notClassCache.add(e),r.classCache.delete(e),r.applyClassCache.delete(e),r.candidateRuleMap.delete(e),r.candidateRuleCache.delete(e),r.stylesheetCache=null)}function W2(r,e){let t=e.raws.tailwind.candidate;if(!!t){for(let i of r.ruleCache)i[1].raws.tailwind.candidate===t&&r.ruleCache.delete(i);Qd(r,t)}}function bo(r,e=[],t=j.root()){let i={disposables:[],ruleCache:new Set,candidateRuleCache:new Map,classCache:new Map,applyClassCache:new Map,notClassCache:new Set(r.blocklist??[]),postCssNodeCache:new Map,candidateRuleMap:new Map,tailwindConfig:r,changedContent:e,variantMap:new Map,stylesheetCache:null,variantOptions:new Map,markInvalidUtilityCandidate:a=>Qd(i,a),markInvalidUtilityNode:a=>W2(i,a)},n=V2(i,t);return U2(n,i),i}function Jd(r,e,t,i,n,a){let s=e.opts.from,o=i!==null;Pe.DEBUG&&console.log("Source path:",s);let u;if(o&&Ut.has(s))u=Ut.get(s);else if(ii.has(n)){let p=ii.get(n);ut.get(p).add(s),Ut.set(s,p),u=p}let c=Fd(s,r);if(u){let[p,m]=Hd([...a],Dn(u));if(!p&&!c)return[u,!1,m]}if(Ut.has(s)){let p=Ut.get(s);if(ut.has(p)&&(ut.get(p).delete(s),ut.get(p).size===0)){ut.delete(p);for(let[m,b]of ii)b===p&&ii.delete(m);for(let m of p.disposables.splice(0))m(p)}}Pe.DEBUG&&console.log("Setting up new context...");let f=bo(t,[],r);Object.assign(f,{userConfigPath:i});let[,d]=Hd([...a],Dn(f));return ii.set(n,f),Ut.set(s,f),ut.has(f)||ut.set(f,new Set),ut.get(f).add(s),[f,!0,d]}var Ud,ho,Zr,mo,go,wo,Ut,ii,ut,ei=C(()=>{l();ze();Cs();st();Ud=X(Gs()),ho=X(Me());Jr();Qa();dn();At();$t();Xa();hr();Cd();lt();lt();gi();Oe();di();eo();On();Ld();Vd();je();so();Zr=Symbol(),mo={AddVariant:Symbol.for("ADD_VARIANT"),MatchVariant:Symbol.for("MATCH_VARIANT")},go={Base:1<<0,Dynamic:1<<1};wo=new WeakMap;Ut=Ad,ii=_d,ut=vn});function vo(r){return r.ignore?[]:r.glob?h.env.ROLLUP_WATCH==="true"?[{type:"dependency",file:r.base}]:[{type:"dir-dependency",dir:r.base,glob:r.glob}]:[{type:"dependency",file:r.base}]}var Xd=C(()=>{l()});function Kd(r,e){return{handler:r,config:e}}var Zd,eh=C(()=>{l();Kd.withOptions=function(r,e=()=>({})){let t=function(i){return{__options:i,handler:r(i),config:e(i)}};return t.__isOptionsFunction=!0,t.__pluginFunction=r,t.__configFunction=e,t};Zd=Kd});var In={};Ae(In,{default:()=>G2});var G2,qn=C(()=>{l();eh();G2=Zd});var rh=v((M6,th)=>{l();var H2=(qn(),In).default,Y2={overflow:"hidden",display:"-webkit-box","-webkit-box-orient":"vertical"},Q2=H2(function({matchUtilities:r,addUtilities:e,theme:t,variants:i}){let n=t("lineClamp");r({"line-clamp":a=>({...Y2,"-webkit-line-clamp":`${a}`})},{values:n}),e([{".line-clamp-none":{"-webkit-line-clamp":"unset"}}],i("lineClamp"))},{theme:{lineClamp:{1:"1",2:"2",3:"3",4:"4",5:"5",6:"6"}},variants:{lineClamp:["responsive"]}});th.exports=Q2});function xo(r){r.content.files.length===0&&F.warn("content-problems",["The `content` option in your Tailwind CSS configuration is missing or empty.","Configure your content sources or your generated CSS will be missing styles.","https://tailwindcss.com/docs/content-configuration"]);try{let e=rh();r.plugins.includes(e)&&(F.warn("line-clamp-in-core",["As of Tailwind CSS v3.3, the `@tailwindcss/line-clamp` plugin is now included by default.","Remove it from the `plugins` array in your configuration to eliminate this warning."]),r.plugins=r.plugins.filter(t=>t!==e))}catch{}return r}var ih=C(()=>{l();Oe()});var nh,sh=C(()=>{l();nh=()=>!1});var Rn,ah=C(()=>{l();Rn={sync:r=>[].concat(r),generateTasks:r=>[{dynamic:!1,base:".",negative:[],positive:[].concat(r),patterns:[].concat(r)}],escapePath:r=>r}});var ko,oh=C(()=>{l();ko=r=>r});var lh,uh=C(()=>{l();lh=()=>""});function fh(r){let e=r,t=lh(r);return t!=="."&&(e=r.substr(t.length),e.charAt(0)==="/"&&(e=e.substr(1))),e.substr(0,2)==="./"&&(e=e.substr(2)),e.charAt(0)==="/"&&(e=e.substr(1)),{base:t,glob:e}}var ch=C(()=>{l();uh()});function ph(r,e){let t=e.content.files;t=t.filter(o=>typeof o=="string"),t=t.map(ko);let i=Rn.generateTasks(t),n=[],a=[];for(let o of i)n.push(...o.positive.map(u=>dh(u,!1))),a.push(...o.negative.map(u=>dh(u,!0)));let s=[...n,...a];return s=X2(r,s),s=s.flatMap(K2),s=s.map(J2),s}function dh(r,e){let t={original:r,base:r,ignore:e,pattern:r,glob:null};return nh(r)&&Object.assign(t,fh(r)),t}function J2(r){let e=ko(r.base);return e=Rn.escapePath(e),r.pattern=r.glob?`${e}/${r.glob}`:e,r.pattern=r.ignore?`!${r.pattern}`:r.pattern,r}function X2(r,e){let t=[];return r.userConfigPath&&r.tailwindConfig.content.relative&&(t=[Z.dirname(r.userConfigPath)]),e.map(i=>(i.base=Z.resolve(...t,i.base),i))}function K2(r){let e=[r];try{let t=te.realpathSync(r.base);t!==r.base&&e.push({...r,base:t})}catch{}return e}function hh(r,e,t){let i=r.tailwindConfig.content.files.filter(s=>typeof s.raw=="string").map(({raw:s,extension:o="html"})=>({content:s,extension:o})),[n,a]=Z2(e,t);for(let s of n){let o=Z.extname(s).slice(1);i.push({file:s,extension:o})}return[i,a]}function Z2(r,e){let t=r.map(s=>s.pattern),i=new Map,n=new Set;Pe.DEBUG&&console.time("Finding changed files");let a=Rn.sync(t,{absolute:!0});for(let s of a){let o=e.get(s)||-1/0,u=te.statSync(s).mtimeMs;u>o&&(n.add(s),i.set(s,u))}return Pe.DEBUG&&console.timeEnd("Finding changed files"),[n,i]}var mh=C(()=>{l();ze();bt();sh();ah();oh();ch();lt()});function gh(){}var yh=C(()=>{l()});function iC(r,e){for(let t of e){let i=`${r}${t}`;if(te.existsSync(i)&&te.statSync(i).isFile())return i}for(let t of e){let i=`${r}/index${t}`;if(te.existsSync(i))return i}return null}function*wh(r,e,t,i=Z.extname(r)){let n=iC(Z.resolve(e,r),eC.includes(i)?tC:rC);if(n===null||t.has(n))return;t.add(n),yield n,e=Z.dirname(n),i=Z.extname(n);let a=te.readFileSync(n,"utf-8");for(let s of[...a.matchAll(/import[\s\S]*?['"](.{3,}?)['"]/gi),...a.matchAll(/import[\s\S]*from[\s\S]*?['"](.{3,}?)['"]/gi),...a.matchAll(/require\(['"`](.+)['"`]\)/gi)])!s[1].startsWith(".")||(yield*wh(s[1],e,t,i))}function So(r){return r===null?new Set:new Set(wh(r,Z.dirname(r),new Set))}var eC,tC,rC,bh=C(()=>{l();ze();bt();eC=[".js",".cjs",".mjs"],tC=["",".js",".cjs",".mjs",".ts",".cts",".mts",".jsx",".tsx"],rC=["",".ts",".cts",".mts",".tsx",".js",".cjs",".mjs",".jsx"]});function nC(r,e){if(Co.has(r))return Co.get(r);let t=ph(r,e);return Co.set(r,t).get(r)}function sC(r){let e=ks(r);if(e!==null){let[i,n,a,s]=xh.get(e)||[],o=So(e),u=!1,c=new Map;for(let p of o){let m=te.statSync(p).mtimeMs;c.set(p,m),(!s||!s.has(p)||m>s.get(p))&&(u=!0)}if(!u)return[i,e,n,a];for(let p of o)delete yu.cache[p];let f=xo(gr(gh(e))),d=pi(f);return xh.set(e,[f,d,o,c]),[f,e,d,o]}let t=gr(r?.config??r??{});return t=xo(t),[t,null,pi(t),[]]}function Ao(r){return({tailwindDirectives:e,registerDependency:t})=>(i,n)=>{let[a,s,o,u]=sC(r),c=new Set(u);if(e.size>0){c.add(n.opts.from);for(let b of n.messages)b.type==="dependency"&&c.add(b.file)}let[f,,d]=Jd(i,n,a,s,o,c),p=Dn(f),m=nC(f,a);if(e.size>0){for(let y of m)for(let w of vo(y))t(w);let[b,x]=hh(f,m,p);for(let y of b)f.changedContent.push(y);for(let[y,w]of x.entries())d.set(y,w)}for(let b of u)t({type:"dependency",file:b});for(let[b,x]of d.entries())p.set(b,x);return f}}var vh,xh,Co,kh=C(()=>{l();ze();vh=X(rs());ku();xs();cf();ei();Xd();ih();mh();yh();bh();xh=new vh.default({maxSize:100}),Co=new WeakMap});function _o(r){let e=new Set,t=new Set,i=new Set;if(r.walkAtRules(n=>{n.name==="apply"&&i.add(n),n.name==="import"&&(n.params==='"tailwindcss/base"'||n.params==="'tailwindcss/base'"?(n.name="tailwind",n.params="base"):n.params==='"tailwindcss/components"'||n.params==="'tailwindcss/components'"?(n.name="tailwind",n.params="components"):n.params==='"tailwindcss/utilities"'||n.params==="'tailwindcss/utilities'"?(n.name="tailwind",n.params="utilities"):(n.params==='"tailwindcss/screens"'||n.params==="'tailwindcss/screens'"||n.params==='"tailwindcss/variants"'||n.params==="'tailwindcss/variants'")&&(n.name="tailwind",n.params="variants")),n.name==="tailwind"&&(n.params==="screens"&&(n.params="variants"),e.add(n.params)),["layer","responsive","variants"].includes(n.name)&&(["responsive","variants"].includes(n.name)&&F.warn(`${n.name}-at-rule-deprecated`,[`The \`@${n.name}\` directive has been deprecated in Tailwind CSS v3.0.`,"Use `@layer utilities` or `@layer components` instead.","https://tailwindcss.com/docs/upgrade-guide#replace-variants-with-layer"]),t.add(n))}),!e.has("base")||!e.has("components")||!e.has("utilities")){for(let n of t)if(n.name==="layer"&&["base","components","utilities"].includes(n.params)){if(!e.has(n.params))throw n.error(`\`@layer ${n.params}\` is used but no matching \`@tailwind ${n.params}\` directive is present.`)}else if(n.name==="responsive"){if(!e.has("utilities"))throw n.error("`@responsive` is used but `@tailwind utilities` is missing.")}else if(n.name==="variants"&&!e.has("utilities"))throw n.error("`@variants` is used but `@tailwind utilities` is missing.")}return{tailwindDirectives:e,applyDirectives:i}}var Sh=C(()=>{l();Oe()});function St(r,e=void 0,t=void 0){return r.map(i=>{let n=i.clone();return t!==void 0&&(n.raws.tailwind={...n.raws.tailwind,...t}),e!==void 0&&Ch(n,a=>{if(a.raws.tailwind?.preserveSource===!0&&a.source)return!1;a.source=e}),n})}function Ch(r,e){e(r)!==!1&&r.each?.(t=>Ch(t,e))}var Ah=C(()=>{l()});function Oo(r){return r=Array.isArray(r)?r:[r],r=r.map(e=>e instanceof RegExp?e.source:e),r.join("")}function ye(r){return new RegExp(Oo(r),"g")}function ft(r){return`(?:${r.map(Oo).join("|")})`}function Eo(r){return`(?:${Oo(r)})?`}function Oh(r){return r&&aC.test(r)?r.replace(_h,"\\$&"):r||""}var _h,aC,Eh=C(()=>{l();_h=/[\\^$.*+?()[\]{}|]/g,aC=RegExp(_h.source)});function Th(r){let e=Array.from(oC(r));return t=>{let i=[];for(let n of e)for(let a of t.match(n)??[])i.push(fC(a));return i}}function*oC(r){let e=r.tailwindConfig.separator,t=r.tailwindConfig.prefix!==""?Eo(ye([/-?/,Oh(r.tailwindConfig.prefix)])):"",i=ft([/\[[^\s:'"`]+:[^\s\[\]]+\]/,/\[[^\s:'"`\]]+:[^\s]+?\[[^\s]+\][^\s]+?\]/,ye([ft([/-?(?:\w+)/,/@(?:\w+)/]),Eo(ft([ye([ft([/-(?:\w+-)*\['[^\s]+'\]/,/-(?:\w+-)*\["[^\s]+"\]/,/-(?:\w+-)*\[`[^\s]+`\]/,/-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s:\[\]]+\]/]),/(?![{([]])/,/(?:\/[^\s'"`\\><$]*)?/]),ye([ft([/-(?:\w+-)*\['[^\s]+'\]/,/-(?:\w+-)*\["[^\s]+"\]/,/-(?:\w+-)*\[`[^\s]+`\]/,/-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s\[\]]+\]/]),/(?![{([]])/,/(?:\/[^\s'"`\\$]*)?/]),/[-\/][^\s'"`\\$={><]*/]))])]),n=[ft([ye([/@\[[^\s"'`]+\](\/[^\s"'`]+)?/,e]),ye([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]\/[\w_-]+/,e]),ye([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/,e]),ye([/[^\s"'`\[\\]+/,e])]),ft([ye([/([^\s"'`\[\\]+-)?\[[^\s`]+\]\/[\w_-]+/,e]),ye([/([^\s"'`\[\\]+-)?\[[^\s`]+\]/,e]),ye([/[^\s`\[\\]+/,e])])];for(let a of n)yield ye(["((?=((",a,")+))\\2)?",/!?/,t,i]);yield/[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g}function fC(r){if(!r.includes("-["))return r;let e=0,t=[],i=r.matchAll(lC);i=Array.from(i).flatMap(n=>{let[,...a]=n;return a.map((s,o)=>Object.assign([],n,{index:n.index+o,0:s}))});for(let n of i){let a=n[0],s=t[t.length-1];if(a===s?t.pop():(a==="'"||a==='"'||a==="`")&&t.push(a),!s){if(a==="["){e++;continue}else if(a==="]"){e--;continue}if(e<0)return r.substring(0,n.index-1);if(e===0&&!uC.test(a))return r.substring(0,n.index)}}return r}var lC,uC,Ph=C(()=>{l();Eh();lC=/([\[\]'"`])([^\[\]'"`])?/g,uC=/[^"'`\s<>\]]+/});function cC(r,e){let t=r.tailwindConfig.content.extract;return t[e]||t.DEFAULT||Ih[e]||Ih.DEFAULT(r)}function pC(r,e){let t=r.content.transform;return t[e]||t.DEFAULT||qh[e]||qh.DEFAULT}function dC(r,e,t,i){ni.has(e)||ni.set(e,new Dh.default({maxSize:25e3}));for(let n of r.split(` -`))if(n=n.trim(),!i.has(n))if(i.add(n),ni.get(e).has(n))for(let a of ni.get(e).get(n))t.add(a);else{let a=e(n).filter(o=>o!=="!*"),s=new Set(a);for(let o of s)t.add(o);ni.get(e).set(n,s)}}function hC(r,e){let t=e.offsets.sort(r),i={base:new Set,defaults:new Set,components:new Set,utilities:new Set,variants:new Set};for(let[n,a]of t)i[n.layer].add(a);return i}function To(r){return async e=>{let t={base:null,components:null,utilities:null,variants:null};if(e.walkAtRules(y=>{y.name==="tailwind"&&Object.keys(t).includes(y.params)&&(t[y.params]=y)}),Object.values(t).every(y=>y===null))return e;let i=new Set([...r.candidates??[],He]),n=new Set;Ye.DEBUG&&console.time("Reading changed files");let a=[];for(let y of r.changedContent){let w=pC(r.tailwindConfig,y.extension),k=cC(r,y.extension);a.push([y,{transformer:w,extractor:k}])}let s=500;for(let y=0;y{S=k?await te.promises.readFile(k,"utf8"):S,dC(_(S),E,i,n)}))}Ye.DEBUG&&console.timeEnd("Reading changed files");let o=r.classCache.size;Ye.DEBUG&&console.time("Generate rules"),Ye.DEBUG&&console.time("Sorting candidates");let u=new Set([...i].sort((y,w)=>y===w?0:y{let w=y.raws.tailwind?.parentLayer;return w==="components"?t.components!==null:w==="utilities"?t.utilities!==null:!0});t.variants?(t.variants.before(St(b,t.variants.source,{layer:"variants"})),t.variants.remove()):b.length>0&&e.append(St(b,e.source,{layer:"variants"})),e.source.end=e.source.end??e.source.start;let x=b.some(y=>y.raws.tailwind?.parentLayer==="utilities");t.utilities&&p.size===0&&!x&&F.warn("content-problems",["No utility classes were detected in your source files. If this is unexpected, double-check the `content` option in your Tailwind CSS configuration.","https://tailwindcss.com/docs/content-configuration"]),Ye.DEBUG&&(console.log("Potential classes: ",i.size),console.log("Active contexts: ",vn.size)),r.changedContent=[],e.walkAtRules("layer",y=>{Object.keys(t).includes(y.params)&&y.remove()})}}var Dh,Ye,Ih,qh,ni,Rh=C(()=>{l();ze();Dh=X(rs());lt();On();Oe();Ah();Ph();Ye=Pe,Ih={DEFAULT:Th},qh={DEFAULT:r=>r,svelte:r=>r.replace(/(?:^|\s)class:/g," ")};ni=new WeakMap});function Bn(r){let e=new Map;j.root({nodes:[r.clone()]}).walkRules(a=>{(0,Mn.default)(s=>{s.walkClasses(o=>{let u=o.parent.toString(),c=e.get(u);c||e.set(u,c=new Set),c.add(o.value)})}).processSync(a.selector)});let i=Array.from(e.values(),a=>Array.from(a)),n=i.flat();return Object.assign(n,{groups:i})}function Po(r){return mC.astSync(r)}function Mh(r,e){let t=new Set;for(let i of r)t.add(i.split(e).pop());return Array.from(t)}function Bh(r,e){let t=r.tailwindConfig.prefix;return typeof t=="function"?t(e):t+e}function*Fh(r){for(yield r;r.parent;)yield r.parent,r=r.parent}function gC(r,e={}){let t=r.nodes;r.nodes=[];let i=r.clone(e);return r.nodes=t,i}function yC(r){for(let e of Fh(r))if(r!==e){if(e.type==="root")break;r=gC(e,{nodes:[r]})}return r}function wC(r,e){let t=new Map;return r.walkRules(i=>{for(let s of Fh(i))if(s.raws.tailwind?.layer!==void 0)return;let n=yC(i),a=e.offsets.create("user");for(let s of Bn(i)){let o=t.get(s)||[];t.set(s,o),o.push([{layer:"user",sort:a,important:!1},n])}}),t}function bC(r,e){for(let t of r){if(e.notClassCache.has(t)||e.applyClassCache.has(t))continue;if(e.classCache.has(t)){e.applyClassCache.set(t,e.classCache.get(t).map(([n,a])=>[n,a.clone()]));continue}let i=Array.from(fo(t,e));if(i.length===0){e.notClassCache.add(t);continue}e.applyClassCache.set(t,i)}return e.applyClassCache}function vC(r){let e=null;return{get:t=>(e=e||r(),e.get(t)),has:t=>(e=e||r(),e.has(t))}}function xC(r){return{get:e=>r.flatMap(t=>t.get(e)||[]),has:e=>r.some(t=>t.has(e))}}function Lh(r){let e=r.split(/[\s\t\n]+/g);return e[e.length-1]==="!important"?[e.slice(0,-1),!0]:[e,!1]}function Nh(r,e,t){let i=new Set,n=[];if(r.walkAtRules("apply",u=>{let[c]=Lh(u.params);for(let f of c)i.add(f);n.push(u)}),n.length===0)return;let a=xC([t,bC(i,e)]);function s(u,c,f){let d=Po(u),p=Po(c),b=Po(`.${ce(f)}`).nodes[0].nodes[0];return d.each(x=>{let y=new Set;p.each(w=>{let k=!1;w=w.clone(),w.walkClasses(S=>{S.value===b.value&&(k||(S.replaceWith(...x.nodes.map(_=>_.clone())),y.add(w),k=!0))})});for(let w of y){let k=[[]];for(let S of w.nodes)S.type==="combinator"?(k.push(S),k.push([])):k[k.length-1].push(S);w.nodes=[];for(let S of k)Array.isArray(S)&&S.sort((_,E)=>_.type==="tag"&&E.type==="class"?-1:_.type==="class"&&E.type==="tag"?1:_.type==="class"&&E.type==="pseudo"&&E.value.startsWith("::")?-1:_.type==="pseudo"&&_.value.startsWith("::")&&E.type==="class"?1:0),w.nodes=w.nodes.concat(S)}x.replaceWith(...y)}),d.toString()}let o=new Map;for(let u of n){let[c]=o.get(u.parent)||[[],u.source];o.set(u.parent,[c,u.source]);let[f,d]=Lh(u.params);if(u.parent.type==="atrule"){if(u.parent.name==="screen"){let p=u.parent.params;throw u.error(`@apply is not supported within nested at-rules like @screen. We suggest you write this as @apply ${f.map(m=>`${p}:${m}`).join(" ")} instead.`)}throw u.error(`@apply is not supported within nested at-rules like @${u.parent.name}. You can fix this by un-nesting @${u.parent.name}.`)}for(let p of f){if([Bh(e,"group"),Bh(e,"peer")].includes(p))throw u.error(`@apply should not be used with the '${p}' utility`);if(!a.has(p))throw u.error(`The \`${p}\` class does not exist. If \`${p}\` is a custom class, make sure it is defined within a \`@layer\` directive.`);let m=a.get(p);for(let[,b]of m)b.type!=="atrule"&&b.walkRules(()=>{throw u.error([`The \`${p}\` class cannot be used with \`@apply\` because \`@apply\` does not currently support nested CSS.`,"Rewrite the selector without nesting or configure the `tailwindcss/nesting` plugin:","https://tailwindcss.com/docs/using-with-preprocessors#nesting"].join(` -`))});c.push([p,d,m])}}for(let[u,[c,f]]of o){let d=[];for(let[m,b,x]of c){let y=[m,...Mh([m],e.tailwindConfig.separator)];for(let[w,k]of x){let S=Bn(u),_=Bn(k);if(_=_.groups.filter(R=>R.some(J=>y.includes(J))).flat(),_=_.concat(Mh(_,e.tailwindConfig.separator)),S.some(R=>_.includes(R)))throw k.error(`You cannot \`@apply\` the \`${m}\` utility here because it creates a circular dependency.`);let I=j.root({nodes:[k.clone()]});I.walk(R=>{R.source=f}),(k.type!=="atrule"||k.type==="atrule"&&k.name!=="keyframes")&&I.walkRules(R=>{if(!Bn(R).some(ee=>ee===m)){R.remove();return}let J=typeof e.tailwindConfig.important=="string"?e.tailwindConfig.important:null,de=u.raws.tailwind!==void 0&&J&&u.selector.indexOf(J)===0?u.selector.slice(J.length):u.selector;de===""&&(de=u.selector),R.selector=s(de,R.selector,m),J&&de!==u.selector&&(R.selector=Sn(R.selector,J)),R.walkDecls(ee=>{ee.important=w.important||b});let De=(0,Mn.default)().astSync(R.selector);De.each(ee=>jt(ee)),R.selector=De.toString()}),!!I.nodes[0]&&d.push([w.sort,I.nodes[0]])}}let p=e.offsets.sort(d).map(m=>m[1]);u.after(p)}for(let u of n)u.parent.nodes.length>1?u.remove():u.parent.remove();Nh(r,e,t)}function Do(r){return e=>{let t=vC(()=>wC(e,r));Nh(e,r,t)}}var Mn,mC,$h=C(()=>{l();st();Mn=X(Me());On();$t();oo();xn();mC=(0,Mn.default)()});var zh=v((I4,Fn)=>{l();(function(){"use strict";function r(i,n,a){if(!i)return null;r.caseSensitive||(i=i.toLowerCase());var s=r.threshold===null?null:r.threshold*i.length,o=r.thresholdAbsolute,u;s!==null&&o!==null?u=Math.min(s,o):s!==null?u=s:o!==null?u=o:u=null;var c,f,d,p,m,b=n.length;for(m=0;ma)return a+1;var u=[],c,f,d,p,m;for(c=0;c<=o;c++)u[c]=[c];for(f=0;f<=s;f++)u[0][f]=f;for(c=1;c<=o;c++){for(d=e,p=1,c>a&&(p=c-a),m=o+1,m>a+c&&(m=a+c),f=1;f<=s;f++)fm?u[c][f]=a+1:n.charAt(c-1)===i.charAt(f-1)?u[c][f]=u[c-1][f-1]:u[c][f]=Math.min(u[c-1][f-1]+1,Math.min(u[c][f-1]+1,u[c-1][f]+1)),u[c][f]a)return a+1}return u[o][s]}})()});var Vh=v((q4,jh)=>{l();var Io="(".charCodeAt(0),qo=")".charCodeAt(0),Ln="'".charCodeAt(0),Ro='"'.charCodeAt(0),Mo="\\".charCodeAt(0),Wt="/".charCodeAt(0),Bo=",".charCodeAt(0),Fo=":".charCodeAt(0),Nn="*".charCodeAt(0),kC="u".charCodeAt(0),SC="U".charCodeAt(0),CC="+".charCodeAt(0),AC=/^[a-f0-9?-]+$/i;jh.exports=function(r){for(var e=[],t=r,i,n,a,s,o,u,c,f,d=0,p=t.charCodeAt(d),m=t.length,b=[{nodes:e}],x=0,y,w="",k="",S="";d{l();Uh.exports=function r(e,t,i){var n,a,s,o;for(n=0,a=e.length;n{l();function Gh(r,e){var t=r.type,i=r.value,n,a;return e&&(a=e(r))!==void 0?a:t==="word"||t==="space"?i:t==="string"?(n=r.quote||"",n+i+(r.unclosed?"":n)):t==="comment"?"/*"+i+(r.unclosed?"":"*/"):t==="div"?(r.before||"")+i+(r.after||""):Array.isArray(r.nodes)?(n=Hh(r.nodes,e),t!=="function"?n:i+"("+(r.before||"")+n+(r.after||"")+(r.unclosed?"":")")):i}function Hh(r,e){var t,i;if(Array.isArray(r)){for(t="",i=r.length-1;~i;i-=1)t=Gh(r[i],e)+t;return t}return Gh(r,e)}Yh.exports=Hh});var Xh=v((B4,Jh)=>{l();var $n="-".charCodeAt(0),zn="+".charCodeAt(0),Lo=".".charCodeAt(0),_C="e".charCodeAt(0),OC="E".charCodeAt(0);function EC(r){var e=r.charCodeAt(0),t;if(e===zn||e===$n){if(t=r.charCodeAt(1),t>=48&&t<=57)return!0;var i=r.charCodeAt(2);return t===Lo&&i>=48&&i<=57}return e===Lo?(t=r.charCodeAt(1),t>=48&&t<=57):e>=48&&e<=57}Jh.exports=function(r){var e=0,t=r.length,i,n,a;if(t===0||!EC(r))return!1;for(i=r.charCodeAt(e),(i===zn||i===$n)&&e++;e57));)e+=1;if(i=r.charCodeAt(e),n=r.charCodeAt(e+1),i===Lo&&n>=48&&n<=57)for(e+=2;e57));)e+=1;if(i=r.charCodeAt(e),n=r.charCodeAt(e+1),a=r.charCodeAt(e+2),(i===_C||i===OC)&&(n>=48&&n<=57||(n===zn||n===$n)&&a>=48&&a<=57))for(e+=n===zn||n===$n?3:2;e57));)e+=1;return{number:r.slice(0,e),unit:r.slice(e)}}});var tm=v((F4,em)=>{l();var TC=Vh(),Kh=Wh(),Zh=Qh();function ct(r){return this instanceof ct?(this.nodes=TC(r),this):new ct(r)}ct.prototype.toString=function(){return Array.isArray(this.nodes)?Zh(this.nodes):""};ct.prototype.walk=function(r,e){return Kh(this.nodes,r,e),this};ct.unit=Xh();ct.walk=Kh;ct.stringify=Zh;em.exports=ct});function $o(r){return typeof r=="object"&&r!==null}function PC(r,e){let t=Ze(e);do if(t.pop(),(0,si.default)(r,t)!==void 0)break;while(t.length);return t.length?t:void 0}function Gt(r){return typeof r=="string"?r:r.reduce((e,t,i)=>t.includes(".")?`${e}[${t}]`:i===0?t:`${e}.${t}`,"")}function im(r){return r.map(e=>`'${e}'`).join(", ")}function nm(r){return im(Object.keys(r))}function zo(r,e,t,i={}){let n=Array.isArray(e)?Gt(e):e.replace(/^['"]+|['"]+$/g,""),a=Array.isArray(e)?e:Ze(n),s=(0,si.default)(r.theme,a,t);if(s===void 0){let u=`'${n}' does not exist in your theme config.`,c=a.slice(0,-1),f=(0,si.default)(r.theme,c);if($o(f)){let d=Object.keys(f).filter(m=>zo(r,[...c,m]).isValid),p=(0,rm.default)(a[a.length-1],d);p?u+=` Did you mean '${Gt([...c,p])}'?`:d.length>0&&(u+=` '${Gt(c)}' has the following valid keys: ${im(d)}`)}else{let d=PC(r.theme,n);if(d){let p=(0,si.default)(r.theme,d);$o(p)?u+=` '${Gt(d)}' has the following keys: ${nm(p)}`:u+=` '${Gt(d)}' is not an object.`}else u+=` Your theme has the following top-level keys: ${nm(r.theme)}`}return{isValid:!1,error:u}}if(!(typeof s=="string"||typeof s=="number"||typeof s=="function"||s instanceof String||s instanceof Number||Array.isArray(s))){let u=`'${n}' was found but does not resolve to a string.`;if($o(s)){let c=Object.keys(s).filter(f=>zo(r,[...a,f]).isValid);c.length&&(u+=` Did you mean something like '${Gt([...a,c[0]])}'?`)}return{isValid:!1,error:u}}let[o]=a;return{isValid:!0,value:Ge(o)(s,i)}}function DC(r,e,t){e=e.map(n=>sm(r,n,t));let i=[""];for(let n of e)n.type==="div"&&n.value===","?i.push(""):i[i.length-1]+=No.default.stringify(n);return i}function sm(r,e,t){if(e.type==="function"&&t[e.value]!==void 0){let i=DC(r,e.nodes,t);e.type="word",e.value=t[e.value](r,...i)}return e}function IC(r,e,t){return Object.keys(t).some(n=>e.includes(`${n}(`))?(0,No.default)(e).walk(n=>{sm(r,n,t)}).toString():e}function*RC(r){r=r.replace(/^['"]+|['"]+$/g,"");let e=r.match(/^([^\s]+)(?![^\[]*\])(?:\s*\/\s*([^\/\s]+))$/),t;yield[r,void 0],e&&(r=e[1],t=e[2],yield[r,t])}function MC(r,e,t){let i=Array.from(RC(e)).map(([n,a])=>Object.assign(zo(r,n,t,{opacityValue:a}),{resolvedPath:n,alpha:a}));return i.find(n=>n.isValid)??i[0]}function am(r){let e=r.tailwindConfig,t={theme:(i,n,...a)=>{let{isValid:s,value:o,error:u,alpha:c}=MC(e,n,a.length?a:void 0);if(!s){let p=i.parent,m=p?.raws.tailwind?.candidate;if(p&&m!==void 0){r.markInvalidUtilityNode(p),p.remove(),F.warn("invalid-theme-key-in-class",[`The utility \`${m}\` contains an invalid theme value and was not generated.`]);return}throw i.error(u)}let f=Ot(o),d=f!==void 0&&typeof f=="function";return(c!==void 0||d)&&(c===void 0&&(c=1),o=Ie(f,c,f)),o},screen:(i,n)=>{n=n.replace(/^['"]+/g,"").replace(/['"]+$/g,"");let s=ot(e.theme.screens).find(({name:o})=>o===n);if(!s)throw i.error(`The '${n}' screen does not exist in your theme.`);return at(s)}};return i=>{i.walk(n=>{let a=qC[n.type];a!==void 0&&(n[a]=IC(n,n[a],t))})}}var si,rm,No,qC,om=C(()=>{l();si=X(Gs()),rm=X(zh());Jr();No=X(tm());wn();mn();gi();fr();hr();Oe();qC={atrule:"params",decl:"value"}});function lm({tailwindConfig:{theme:r}}){return function(e){e.walkAtRules("screen",t=>{let i=t.params,a=ot(r.screens).find(({name:s})=>s===i);if(!a)throw t.error(`No \`${i}\` screen found.`);t.name="media",t.params=at(a)})}}var um=C(()=>{l();wn();mn()});function BC(r){let e=r.filter(o=>o.type!=="pseudo"||o.nodes.length>0?!0:o.value.startsWith("::")||[":before",":after",":first-line",":first-letter"].includes(o.value)).reverse(),t=new Set(["tag","class","id","attribute"]),i=e.findIndex(o=>t.has(o.type));if(i===-1)return e.reverse().join("").trim();let n=e[i],a=fm[n.type]?fm[n.type](n):n;e=e.slice(0,i);let s=e.findIndex(o=>o.type==="combinator"&&o.value===">");return s!==-1&&(e.splice(0,s),e.unshift(jn.default.universal())),[a,...e.reverse()].join("").trim()}function LC(r){return jo.has(r)||jo.set(r,FC.transformSync(r)),jo.get(r)}function Vo({tailwindConfig:r}){return e=>{let t=new Map,i=new Set;if(e.walkAtRules("defaults",n=>{if(n.nodes&&n.nodes.length>0){i.add(n);return}let a=n.params;t.has(a)||t.set(a,new Set),t.get(a).add(n.parent),n.remove()}),K(r,"optimizeUniversalDefaults"))for(let n of i){let a=new Map,s=t.get(n.params)??[];for(let o of s)for(let u of LC(o.selector)){let c=u.includes(":-")||u.includes("::-")||u.includes(":has")?u:"__DEFAULT__",f=a.get(c)??new Set;a.set(c,f),f.add(u)}if(K(r,"optimizeUniversalDefaults")){if(a.size===0){n.remove();continue}for(let[,o]of a){let u=j.rule({source:n.source});u.selectors=[...o],u.append(n.nodes.map(c=>c.clone())),n.before(u)}}n.remove()}else if(i.size){let n=j.rule({selectors:["*","::before","::after"]});for(let s of i)n.append(s.nodes),n.parent||s.before(n),n.source||(n.source=s.source),s.remove();let a=n.clone({selectors:["::backdrop"]});n.after(a)}}}var jn,fm,FC,jo,cm=C(()=>{l();st();jn=X(Me());je();fm={id(r){return jn.default.attribute({attribute:"id",operator:"=",value:r.value,quoteMark:'"'})}};FC=(0,jn.default)(r=>r.map(e=>{let t=e.split(i=>i.type==="combinator"&&i.value===" ").pop();return BC(t)})),jo=new Map});function Uo(){function r(e){let t=null;e.each(i=>{if(!NC.has(i.type)){t=null;return}if(t===null){t=i;return}let n=pm[i.type];i.type==="atrule"&&i.name==="font-face"?t=i:n.every(a=>(i[a]??"").replace(/\s+/g," ")===(t[a]??"").replace(/\s+/g," "))?(i.nodes&&t.append(i.nodes),i.remove()):t=i}),e.each(i=>{i.type==="atrule"&&r(i)})}return e=>{r(e)}}var pm,NC,dm=C(()=>{l();pm={atrule:["name","params"],rule:["selector"]},NC=new Set(Object.keys(pm))});function Wo(){return r=>{r.walkRules(e=>{let t=new Map,i=new Set([]),n=new Map;e.walkDecls(a=>{if(a.parent===e){if(t.has(a.prop)){if(t.get(a.prop).value===a.value){i.add(t.get(a.prop)),t.set(a.prop,a);return}n.has(a.prop)||n.set(a.prop,new Set),n.get(a.prop).add(t.get(a.prop)),n.get(a.prop).add(a)}t.set(a.prop,a)}});for(let a of i)a.remove();for(let a of n.values()){let s=new Map;for(let o of a){let u=zC(o.value);u!==null&&(s.has(u)||s.set(u,new Set),s.get(u).add(o))}for(let o of s.values()){let u=Array.from(o).slice(0,-1);for(let c of u)c.remove()}}})}}function zC(r){let e=/^-?\d*.?\d+([\w%]+)?$/g.exec(r);return e?e[1]??$C:null}var $C,hm=C(()=>{l();$C=Symbol("unitless-number")});function jC(r){if(!r.walkAtRules)return;let e=new Set;if(r.walkAtRules("apply",t=>{e.add(t.parent)}),e.size!==0)for(let t of e){let i=[],n=[];for(let a of t.nodes)a.type==="atrule"&&a.name==="apply"?(n.length>0&&(i.push(n),n=[]),i.push([a])):n.push(a);if(n.length>0&&i.push(n),i.length!==1){for(let a of[...i].reverse()){let s=t.clone({nodes:[]});s.append(a),t.after(s)}t.remove()}}}function Vn(){return r=>{jC(r)}}var mm=C(()=>{l()});function Un(r){return async function(e,t){let{tailwindDirectives:i,applyDirectives:n}=_o(e);Vn()(e,t);let a=r({tailwindDirectives:i,applyDirectives:n,registerDependency(s){t.messages.push({plugin:"tailwindcss",parent:t.opts.from,...s})},createContext(s,o){return bo(s,o,e)}})(e,t);if(a.tailwindConfig.separator==="-")throw new Error("The '-' character cannot be used as a custom separator in JIT mode due to parsing ambiguity. Please use another character like '_' instead.");Iu(a.tailwindConfig),await To(a)(e,t),Vn()(e,t),Do(a)(e,t),am(a)(e,t),lm(a)(e,t),Vo(a)(e,t),Uo(a)(e,t),Wo(a)(e,t)}}var gm=C(()=>{l();Sh();Rh();$h();om();um();cm();dm();hm();mm();ei();je()});function ym(r,e){let t=null,i=null;return r.walkAtRules("config",n=>{if(i=n.source?.input.file??e.opts.from??null,i===null)throw n.error("The `@config` directive cannot be used without setting `from` in your PostCSS config.");if(t)throw n.error("Only one `@config` directive is allowed per file.");let a=n.params.match(/(['"])(.*?)\1/);if(!a)throw n.error("A path is required when using the `@config` directive.");let s=a[2];if(Z.isAbsolute(s))throw n.error("The `@config` directive cannot be used with an absolute path.");if(t=Z.resolve(Z.dirname(i),s),!te.existsSync(t))throw n.error(`The config file at "${s}" does not exist. Make sure the path is correct and the file exists.`);n.remove()}),t||null}var wm=C(()=>{l();ze();bt()});var bm=v((vD,Go)=>{l();kh();gm();lt();wm();Go.exports=function(e){return{postcssPlugin:"tailwindcss",plugins:[Pe.DEBUG&&function(t){return console.log(` -`),console.time("JIT TOTAL"),t},async function(t,i){e=ym(t,i)??e;let n=Ao(e);if(t.type==="document"){let a=t.nodes.filter(s=>s.type==="root");for(let s of a)s.type==="root"&&await Un(n)(s,i);return}await Un(n)(t,i)},Pe.DEBUG&&function(t){return console.timeEnd("JIT TOTAL"),console.log(` -`),t}].filter(Boolean)}};Go.exports.postcss=!0});var xm=v((xD,vm)=>{l();vm.exports=bm()});var Ho=v((kD,km)=>{l();km.exports=()=>["and_chr 114","and_uc 15.5","chrome 114","chrome 113","chrome 109","edge 114","firefox 114","ios_saf 16.5","ios_saf 16.4","ios_saf 16.3","ios_saf 16.1","opera 99","safari 16.5","samsung 21"]});var Wn={};Ae(Wn,{agents:()=>VC,feature:()=>UC});function UC(){return{status:"cr",title:"CSS Feature Queries",stats:{ie:{"6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","5.5":"n"},edge:{"12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","79":"y","80":"y","81":"y","83":"y","84":"y","85":"y","86":"y","87":"y","88":"y","89":"y","90":"y","91":"y","92":"y","93":"y","94":"y","95":"y","96":"y","97":"y","98":"y","99":"y","100":"y","101":"y","102":"y","103":"y","104":"y","105":"y","106":"y","107":"y","108":"y","109":"y","110":"y","111":"y","112":"y","113":"y","114":"y"},firefox:{"2":"n","3":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y","40":"y","41":"y","42":"y","43":"y","44":"y","45":"y","46":"y","47":"y","48":"y","49":"y","50":"y","51":"y","52":"y","53":"y","54":"y","55":"y","56":"y","57":"y","58":"y","59":"y","60":"y","61":"y","62":"y","63":"y","64":"y","65":"y","66":"y","67":"y","68":"y","69":"y","70":"y","71":"y","72":"y","73":"y","74":"y","75":"y","76":"y","77":"y","78":"y","79":"y","80":"y","81":"y","82":"y","83":"y","84":"y","85":"y","86":"y","87":"y","88":"y","89":"y","90":"y","91":"y","92":"y","93":"y","94":"y","95":"y","96":"y","97":"y","98":"y","99":"y","100":"y","101":"y","102":"y","103":"y","104":"y","105":"y","106":"y","107":"y","108":"y","109":"y","110":"y","111":"y","112":"y","113":"y","114":"y","115":"y","116":"y","117":"y","3.5":"n","3.6":"n"},chrome:{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y","40":"y","41":"y","42":"y","43":"y","44":"y","45":"y","46":"y","47":"y","48":"y","49":"y","50":"y","51":"y","52":"y","53":"y","54":"y","55":"y","56":"y","57":"y","58":"y","59":"y","60":"y","61":"y","62":"y","63":"y","64":"y","65":"y","66":"y","67":"y","68":"y","69":"y","70":"y","71":"y","72":"y","73":"y","74":"y","75":"y","76":"y","77":"y","78":"y","79":"y","80":"y","81":"y","83":"y","84":"y","85":"y","86":"y","87":"y","88":"y","89":"y","90":"y","91":"y","92":"y","93":"y","94":"y","95":"y","96":"y","97":"y","98":"y","99":"y","100":"y","101":"y","102":"y","103":"y","104":"y","105":"y","106":"y","107":"y","108":"y","109":"y","110":"y","111":"y","112":"y","113":"y","114":"y","115":"y","116":"y","117":"y"},safari:{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","17":"y","9.1":"y","10.1":"y","11.1":"y","12.1":"y","13.1":"y","14.1":"y","15.1":"y","15.2-15.3":"y","15.4":"y","15.5":"y","15.6":"y","16.0":"y","16.1":"y","16.2":"y","16.3":"y","16.4":"y","16.5":"y","16.6":"y",TP:"y","3.1":"n","3.2":"n","5.1":"n","6.1":"n","7.1":"n"},opera:{"9":"n","11":"n","12":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y","40":"y","41":"y","42":"y","43":"y","44":"y","45":"y","46":"y","47":"y","48":"y","49":"y","50":"y","51":"y","52":"y","53":"y","54":"y","55":"y","56":"y","57":"y","58":"y","60":"y","62":"y","63":"y","64":"y","65":"y","66":"y","67":"y","68":"y","69":"y","70":"y","71":"y","72":"y","73":"y","74":"y","75":"y","76":"y","77":"y","78":"y","79":"y","80":"y","81":"y","82":"y","83":"y","84":"y","85":"y","86":"y","87":"y","88":"y","89":"y","90":"y","91":"y","92":"y","93":"y","94":"y","95":"y","96":"y","97":"y","98":"y","99":"y","100":"y","12.1":"y","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11.1":"n","11.5":"n","11.6":"n"},ios_saf:{"8":"n","17":"y","9.0-9.2":"y","9.3":"y","10.0-10.2":"y","10.3":"y","11.0-11.2":"y","11.3-11.4":"y","12.0-12.1":"y","12.2-12.5":"y","13.0-13.1":"y","13.2":"y","13.3":"y","13.4-13.7":"y","14.0-14.4":"y","14.5-14.8":"y","15.0-15.1":"y","15.2-15.3":"y","15.4":"y","15.5":"y","15.6":"y","16.0":"y","16.1":"y","16.2":"y","16.3":"y","16.4":"y","16.5":"y","16.6":"y","3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8.1-8.4":"n"},op_mini:{all:"y"},android:{"3":"n","4":"n","114":"y","4.4":"y","4.4.3-4.4.4":"y","2.1":"n","2.2":"n","2.3":"n","4.1":"n","4.2-4.3":"n"},bb:{"7":"n","10":"n"},op_mob:{"10":"n","11":"n","12":"n","73":"y","11.1":"n","11.5":"n","12.1":"n"},and_chr:{"114":"y"},and_ff:{"115":"y"},ie_mob:{"10":"n","11":"n"},and_uc:{"15.5":"y"},samsung:{"4":"y","20":"y","21":"y","5.0-5.4":"y","6.2-6.4":"y","7.2-7.4":"y","8.2":"y","9.2":"y","10.1":"y","11.1-11.2":"y","12.0":"y","13.0":"y","14.0":"y","15.0":"y","16.0":"y","17.0":"y","18.0":"y","19.0":"y"},and_qq:{"13.1":"y"},baidu:{"13.18":"y"},kaios:{"2.5":"y","3.0-3.1":"y"}}}}var VC,Gn=C(()=>{l();VC={ie:{prefix:"ms"},edge:{prefix:"webkit",prefix_exceptions:{"12":"ms","13":"ms","14":"ms","15":"ms","16":"ms","17":"ms","18":"ms"}},firefox:{prefix:"moz"},chrome:{prefix:"webkit"},safari:{prefix:"webkit"},opera:{prefix:"webkit",prefix_exceptions:{"9":"o","11":"o","12":"o","9.5-9.6":"o","10.0-10.1":"o","10.5":"o","10.6":"o","11.1":"o","11.5":"o","11.6":"o","12.1":"o"}},ios_saf:{prefix:"webkit"},op_mini:{prefix:"o"},android:{prefix:"webkit"},bb:{prefix:"webkit"},op_mob:{prefix:"o",prefix_exceptions:{"73":"webkit"}},and_chr:{prefix:"webkit"},and_ff:{prefix:"moz"},ie_mob:{prefix:"ms"},and_uc:{prefix:"webkit",prefix_exceptions:{"15.5":"webkit"}},samsung:{prefix:"webkit"},and_qq:{prefix:"webkit"},baidu:{prefix:"webkit"},kaios:{prefix:"moz"}}});var Sm=v(()=>{l()});var le=v((AD,pt)=>{l();var{list:Yo}=ge();pt.exports.error=function(r){let e=new Error(r);throw e.autoprefixer=!0,e};pt.exports.uniq=function(r){return[...new Set(r)]};pt.exports.removeNote=function(r){return r.includes(" ")?r.split(" ")[0]:r};pt.exports.escapeRegexp=function(r){return r.replace(/[$()*+-.?[\\\]^{|}]/g,"\\$&")};pt.exports.regexp=function(r,e=!0){return e&&(r=this.escapeRegexp(r)),new RegExp(`(^|[\\s,(])(${r}($|[\\s(,]))`,"gi")};pt.exports.editList=function(r,e){let t=Yo.comma(r),i=e(t,[]);if(t===i)return r;let n=r.match(/,\s*/);return n=n?n[0]:", ",i.join(n)};pt.exports.splitSelector=function(r){return Yo.comma(r).map(e=>Yo.space(e).map(t=>t.split(/(?=\.|#)/g)))}});var dt=v((_D,_m)=>{l();var WC=Ho(),Cm=(Gn(),Wn).agents,GC=le(),Am=class{static prefixes(){if(this.prefixesCache)return this.prefixesCache;this.prefixesCache=[];for(let e in Cm)this.prefixesCache.push(`-${Cm[e].prefix}-`);return this.prefixesCache=GC.uniq(this.prefixesCache).sort((e,t)=>t.length-e.length),this.prefixesCache}static withPrefix(e){return this.prefixesRegexp||(this.prefixesRegexp=new RegExp(this.prefixes().join("|"))),this.prefixesRegexp.test(e)}constructor(e,t,i,n){this.data=e,this.options=i||{},this.browserslistOpts=n||{},this.selected=this.parse(t)}parse(e){let t={};for(let i in this.browserslistOpts)t[i]=this.browserslistOpts[i];return t.path=this.options.from,WC(e,t)}prefix(e){let[t,i]=e.split(" "),n=this.data[t],a=n.prefix_exceptions&&n.prefix_exceptions[i];return a||(a=n.prefix),`-${a}-`}isSelected(e){return this.selected.includes(e)}};_m.exports=Am});var ai=v((OD,Om)=>{l();Om.exports={prefix(r){let e=r.match(/^(-\w+-)/);return e?e[0]:""},unprefixed(r){return r.replace(/^-\w+-/,"")}}});var Ht=v((ED,Tm)=>{l();var HC=dt(),Em=ai(),YC=le();function Qo(r,e){let t=new r.constructor;for(let i of Object.keys(r||{})){let n=r[i];i==="parent"&&typeof n=="object"?e&&(t[i]=e):i==="source"||i===null?t[i]=n:Array.isArray(n)?t[i]=n.map(a=>Qo(a,t)):i!=="_autoprefixerPrefix"&&i!=="_autoprefixerValues"&&i!=="proxyCache"&&(typeof n=="object"&&n!==null&&(n=Qo(n,t)),t[i]=n)}return t}var Hn=class{static hack(e){return this.hacks||(this.hacks={}),e.names.map(t=>(this.hacks[t]=e,this.hacks[t]))}static load(e,t,i){let n=this.hacks&&this.hacks[e];return n?new n(e,t,i):new this(e,t,i)}static clone(e,t){let i=Qo(e);for(let n in t)i[n]=t[n];return i}constructor(e,t,i){this.prefixes=t,this.name=e,this.all=i}parentPrefix(e){let t;return typeof e._autoprefixerPrefix!="undefined"?t=e._autoprefixerPrefix:e.type==="decl"&&e.prop[0]==="-"?t=Em.prefix(e.prop):e.type==="root"?t=!1:e.type==="rule"&&e.selector.includes(":-")&&/:(-\w+-)/.test(e.selector)?t=e.selector.match(/:(-\w+-)/)[1]:e.type==="atrule"&&e.name[0]==="-"?t=Em.prefix(e.name):t=this.parentPrefix(e.parent),HC.prefixes().includes(t)||(t=!1),e._autoprefixerPrefix=t,e._autoprefixerPrefix}process(e,t){if(!this.check(e))return;let i=this.parentPrefix(e),n=this.prefixes.filter(s=>!i||i===YC.removeNote(s)),a=[];for(let s of n)this.add(e,s,a.concat([s]),t)&&a.push(s);return a}clone(e,t){return Hn.clone(e,t)}};Tm.exports=Hn});var M=v((TD,Im)=>{l();var QC=Ht(),JC=dt(),Pm=le(),Dm=class extends QC{check(){return!0}prefixed(e,t){return t+e}normalize(e){return e}otherPrefixes(e,t){for(let i of JC.prefixes())if(i!==t&&e.includes(i))return!0;return!1}set(e,t){return e.prop=this.prefixed(e.prop,t),e}needCascade(e){return e._autoprefixerCascade||(e._autoprefixerCascade=this.all.options.cascade!==!1&&e.raw("before").includes(` -`)),e._autoprefixerCascade}maxPrefixed(e,t){if(t._autoprefixerMax)return t._autoprefixerMax;let i=0;for(let n of e)n=Pm.removeNote(n),n.length>i&&(i=n.length);return t._autoprefixerMax=i,t._autoprefixerMax}calcBefore(e,t,i=""){let a=this.maxPrefixed(e,t)-Pm.removeNote(i).length,s=t.raw("before");return a>0&&(s+=Array(a).fill(" ").join("")),s}restoreBefore(e){let t=e.raw("before").split(` -`),i=t[t.length-1];this.all.group(e).up(n=>{let a=n.raw("before").split(` -`),s=a[a.length-1];s.lengths.prop===n.prop&&s.value===n.value)))return this.needCascade(e)&&(n.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,n)}isAlready(e,t){let i=this.all.group(e).up(n=>n.prop===t);return i||(i=this.all.group(e).down(n=>n.prop===t)),i}add(e,t,i,n){let a=this.prefixed(e.prop,t);if(!(this.isAlready(e,a)||this.otherPrefixes(e.value,t)))return this.insert(e,t,i,n)}process(e,t){if(!this.needCascade(e)){super.process(e,t);return}let i=super.process(e,t);!i||!i.length||(this.restoreBefore(e),e.raws.before=this.calcBefore(i,e))}old(e,t){return[this.prefixed(e,t)]}};Im.exports=Dm});var Rm=v((PD,qm)=>{l();qm.exports=function r(e){return{mul:t=>new r(e*t),div:t=>new r(e/t),simplify:()=>new r(e),toString:()=>e.toString()}}});var Fm=v((DD,Bm)=>{l();var XC=Rm(),KC=Ht(),Jo=le(),ZC=/(min|max)-resolution\s*:\s*\d*\.?\d+(dppx|dpcm|dpi|x)/gi,eA=/(min|max)-resolution(\s*:\s*)(\d*\.?\d+)(dppx|dpcm|dpi|x)/i,Mm=class extends KC{prefixName(e,t){return e==="-moz-"?t+"--moz-device-pixel-ratio":e+t+"-device-pixel-ratio"}prefixQuery(e,t,i,n,a){return n=new XC(n),a==="dpi"?n=n.div(96):a==="dpcm"&&(n=n.mul(2.54).div(96)),n=n.simplify(),e==="-o-"&&(n=n.n+"/"+n.d),this.prefixName(e,t)+i+n}clean(e){if(!this.bad){this.bad=[];for(let t of this.prefixes)this.bad.push(this.prefixName(t,"min")),this.bad.push(this.prefixName(t,"max"))}e.params=Jo.editList(e.params,t=>t.filter(i=>this.bad.every(n=>!i.includes(n))))}process(e){let t=this.parentPrefix(e),i=t?[t]:this.prefixes;e.params=Jo.editList(e.params,(n,a)=>{for(let s of n){if(!s.includes("min-resolution")&&!s.includes("max-resolution")){a.push(s);continue}for(let o of i){let u=s.replace(ZC,c=>{let f=c.match(eA);return this.prefixQuery(o,f[1],f[2],f[3],f[4])});a.push(u)}a.push(s)}return Jo.uniq(a)})}};Bm.exports=Mm});var Nm=v((ID,Lm)=>{l();var Xo="(".charCodeAt(0),Ko=")".charCodeAt(0),Yn="'".charCodeAt(0),Zo='"'.charCodeAt(0),el="\\".charCodeAt(0),Yt="/".charCodeAt(0),tl=",".charCodeAt(0),rl=":".charCodeAt(0),Qn="*".charCodeAt(0),tA="u".charCodeAt(0),rA="U".charCodeAt(0),iA="+".charCodeAt(0),nA=/^[a-f0-9?-]+$/i;Lm.exports=function(r){for(var e=[],t=r,i,n,a,s,o,u,c,f,d=0,p=t.charCodeAt(d),m=t.length,b=[{nodes:e}],x=0,y,w="",k="",S="";d{l();$m.exports=function r(e,t,i){var n,a,s,o;for(n=0,a=e.length;n{l();function jm(r,e){var t=r.type,i=r.value,n,a;return e&&(a=e(r))!==void 0?a:t==="word"||t==="space"?i:t==="string"?(n=r.quote||"",n+i+(r.unclosed?"":n)):t==="comment"?"/*"+i+(r.unclosed?"":"*/"):t==="div"?(r.before||"")+i+(r.after||""):Array.isArray(r.nodes)?(n=Vm(r.nodes,e),t!=="function"?n:i+"("+(r.before||"")+n+(r.after||"")+(r.unclosed?"":")")):i}function Vm(r,e){var t,i;if(Array.isArray(r)){for(t="",i=r.length-1;~i;i-=1)t=jm(r[i],e)+t;return t}return jm(r,e)}Um.exports=Vm});var Hm=v((MD,Gm)=>{l();var Jn="-".charCodeAt(0),Xn="+".charCodeAt(0),il=".".charCodeAt(0),sA="e".charCodeAt(0),aA="E".charCodeAt(0);function oA(r){var e=r.charCodeAt(0),t;if(e===Xn||e===Jn){if(t=r.charCodeAt(1),t>=48&&t<=57)return!0;var i=r.charCodeAt(2);return t===il&&i>=48&&i<=57}return e===il?(t=r.charCodeAt(1),t>=48&&t<=57):e>=48&&e<=57}Gm.exports=function(r){var e=0,t=r.length,i,n,a;if(t===0||!oA(r))return!1;for(i=r.charCodeAt(e),(i===Xn||i===Jn)&&e++;e57));)e+=1;if(i=r.charCodeAt(e),n=r.charCodeAt(e+1),i===il&&n>=48&&n<=57)for(e+=2;e57));)e+=1;if(i=r.charCodeAt(e),n=r.charCodeAt(e+1),a=r.charCodeAt(e+2),(i===sA||i===aA)&&(n>=48&&n<=57||(n===Xn||n===Jn)&&a>=48&&a<=57))for(e+=n===Xn||n===Jn?3:2;e57));)e+=1;return{number:r.slice(0,e),unit:r.slice(e)}}});var Kn=v((BD,Jm)=>{l();var lA=Nm(),Ym=zm(),Qm=Wm();function ht(r){return this instanceof ht?(this.nodes=lA(r),this):new ht(r)}ht.prototype.toString=function(){return Array.isArray(this.nodes)?Qm(this.nodes):""};ht.prototype.walk=function(r,e){return Ym(this.nodes,r,e),this};ht.unit=Hm();ht.walk=Ym;ht.stringify=Qm;Jm.exports=ht});var tg=v((FD,eg)=>{l();var{list:uA}=ge(),Xm=Kn(),fA=dt(),Km=ai(),Zm=class{constructor(e){this.props=["transition","transition-property"],this.prefixes=e}add(e,t){let i,n,a=this.prefixes.add[e.prop],s=this.ruleVendorPrefixes(e),o=s||a&&a.prefixes||[],u=this.parse(e.value),c=u.map(m=>this.findProp(m)),f=[];if(c.some(m=>m[0]==="-"))return;for(let m of u){if(n=this.findProp(m),n[0]==="-")continue;let b=this.prefixes.add[n];if(!(!b||!b.prefixes))for(i of b.prefixes){if(s&&!s.some(y=>i.includes(y)))continue;let x=this.prefixes.prefixed(n,i);x!=="-ms-transform"&&!c.includes(x)&&(this.disabled(n,i)||f.push(this.clone(n,x,m)))}}u=u.concat(f);let d=this.stringify(u),p=this.stringify(this.cleanFromUnprefixed(u,"-webkit-"));if(o.includes("-webkit-")&&this.cloneBefore(e,`-webkit-${e.prop}`,p),this.cloneBefore(e,e.prop,p),o.includes("-o-")){let m=this.stringify(this.cleanFromUnprefixed(u,"-o-"));this.cloneBefore(e,`-o-${e.prop}`,m)}for(i of o)if(i!=="-webkit-"&&i!=="-o-"){let m=this.stringify(this.cleanOtherPrefixes(u,i));this.cloneBefore(e,i+e.prop,m)}d!==e.value&&!this.already(e,e.prop,d)&&(this.checkForWarning(t,e),e.cloneBefore(),e.value=d)}findProp(e){let t=e[0].value;if(/^\d/.test(t)){for(let[i,n]of e.entries())if(i!==0&&n.type==="word")return n.value}return t}already(e,t,i){return e.parent.some(n=>n.prop===t&&n.value===i)}cloneBefore(e,t,i){this.already(e,t,i)||e.cloneBefore({prop:t,value:i})}checkForWarning(e,t){if(t.prop!=="transition-property")return;let i=!1,n=!1;t.parent.each(a=>{if(a.type!=="decl"||a.prop.indexOf("transition-")!==0)return;let s=uA.comma(a.value);if(a.prop==="transition-property"){s.forEach(o=>{let u=this.prefixes.add[o];u&&u.prefixes&&u.prefixes.length>0&&(i=!0)});return}return n=n||s.length>1,!1}),i&&n&&t.warn(e,"Replace transition-property to transition, because Autoprefixer could not support any cases of transition-property and other transition-*")}remove(e){let t=this.parse(e.value);t=t.filter(s=>{let o=this.prefixes.remove[this.findProp(s)];return!o||!o.remove});let i=this.stringify(t);if(e.value===i)return;if(t.length===0){e.remove();return}let n=e.parent.some(s=>s.prop===e.prop&&s.value===i),a=e.parent.some(s=>s!==e&&s.prop===e.prop&&s.value.length>i.length);if(n||a){e.remove();return}e.value=i}parse(e){let t=Xm(e),i=[],n=[];for(let a of t.nodes)n.push(a),a.type==="div"&&a.value===","&&(i.push(n),n=[]);return i.push(n),i.filter(a=>a.length>0)}stringify(e){if(e.length===0)return"";let t=[];for(let i of e)i[i.length-1].type!=="div"&&i.push(this.div(e)),t=t.concat(i);return t[0].type==="div"&&(t=t.slice(1)),t[t.length-1].type==="div"&&(t=t.slice(0,-2+1||void 0)),Xm.stringify({nodes:t})}clone(e,t,i){let n=[],a=!1;for(let s of i)!a&&s.type==="word"&&s.value===e?(n.push({type:"word",value:t}),a=!0):n.push(s);return n}div(e){for(let t of e)for(let i of t)if(i.type==="div"&&i.value===",")return i;return{type:"div",value:",",after:" "}}cleanOtherPrefixes(e,t){return e.filter(i=>{let n=Km.prefix(this.findProp(i));return n===""||n===t})}cleanFromUnprefixed(e,t){let i=e.map(a=>this.findProp(a)).filter(a=>a.slice(0,t.length)===t).map(a=>this.prefixes.unprefixed(a)),n=[];for(let a of e){let s=this.findProp(a),o=Km.prefix(s);!i.includes(s)&&(o===t||o==="")&&n.push(a)}return n}disabled(e,t){let i=["order","justify-content","align-self","align-content"];if(e.includes("flex")||i.includes(e)){if(this.prefixes.options.flexbox===!1)return!0;if(this.prefixes.options.flexbox==="no-2009")return t.includes("2009")}}ruleVendorPrefixes(e){let{parent:t}=e;if(t.type!=="rule")return!1;if(!t.selector.includes(":-"))return!1;let i=fA.prefixes().filter(n=>t.selector.includes(":"+n));return i.length>0?i:!1}};eg.exports=Zm});var Qt=v((LD,ig)=>{l();var cA=le(),rg=class{constructor(e,t,i,n){this.unprefixed=e,this.prefixed=t,this.string=i||t,this.regexp=n||cA.regexp(t)}check(e){return e.includes(this.string)?!!e.match(this.regexp):!1}};ig.exports=rg});var ke=v((ND,sg)=>{l();var pA=Ht(),dA=Qt(),hA=ai(),mA=le(),ng=class extends pA{static save(e,t){let i=t.prop,n=[];for(let a in t._autoprefixerValues){let s=t._autoprefixerValues[a];if(s===t.value)continue;let o,u=hA.prefix(i);if(u==="-pie-")continue;if(u===a){o=t.value=s,n.push(o);continue}let c=e.prefixed(i,a),f=t.parent;if(!f.every(b=>b.prop!==c)){n.push(o);continue}let d=s.replace(/\s+/," ");if(f.some(b=>b.prop===t.prop&&b.value.replace(/\s+/," ")===d)){n.push(o);continue}let m=this.clone(t,{value:s});o=t.parent.insertBefore(t,m),n.push(o)}return n}check(e){let t=e.value;return t.includes(this.name)?!!t.match(this.regexp()):!1}regexp(){return this.regexpCache||(this.regexpCache=mA.regexp(this.name))}replace(e,t){return e.replace(this.regexp(),`$1${t}$2`)}value(e){return e.raws.value&&e.raws.value.value===e.value?e.raws.value.raw:e.value}add(e,t){e._autoprefixerValues||(e._autoprefixerValues={});let i=e._autoprefixerValues[t]||this.value(e),n;do if(n=i,i=this.replace(i,t),i===!1)return;while(i!==n);e._autoprefixerValues[t]=i}old(e){return new dA(this.name,e+this.name)}};sg.exports=ng});var mt=v(($D,ag)=>{l();ag.exports={}});var sl=v((zD,ug)=>{l();var og=Kn(),gA=ke(),yA=mt().insertAreas,wA=/(^|[^-])linear-gradient\(\s*(top|left|right|bottom)/i,bA=/(^|[^-])radial-gradient\(\s*\d+(\w*|%)\s+\d+(\w*|%)\s*,/i,vA=/(!\s*)?autoprefixer:\s*ignore\s+next/i,xA=/(!\s*)?autoprefixer\s*grid:\s*(on|off|(no-)?autoplace)/i,kA=["width","height","min-width","max-width","min-height","max-height","inline-size","min-inline-size","max-inline-size","block-size","min-block-size","max-block-size"];function nl(r){return r.parent.some(e=>e.prop==="grid-template"||e.prop==="grid-template-areas")}function SA(r){let e=r.parent.some(i=>i.prop==="grid-template-rows"),t=r.parent.some(i=>i.prop==="grid-template-columns");return e&&t}var lg=class{constructor(e){this.prefixes=e}add(e,t){let i=this.prefixes.add["@resolution"],n=this.prefixes.add["@keyframes"],a=this.prefixes.add["@viewport"],s=this.prefixes.add["@supports"];e.walkAtRules(f=>{if(f.name==="keyframes"){if(!this.disabled(f,t))return n&&n.process(f)}else if(f.name==="viewport"){if(!this.disabled(f,t))return a&&a.process(f)}else if(f.name==="supports"){if(this.prefixes.options.supports!==!1&&!this.disabled(f,t))return s.process(f)}else if(f.name==="media"&&f.params.includes("-resolution")&&!this.disabled(f,t))return i&&i.process(f)}),e.walkRules(f=>{if(!this.disabled(f,t))return this.prefixes.add.selectors.map(d=>d.process(f,t))});function o(f){return f.parent.nodes.some(d=>{if(d.type!=="decl")return!1;let p=d.prop==="display"&&/(inline-)?grid/.test(d.value),m=d.prop.startsWith("grid-template"),b=/^grid-([A-z]+-)?gap/.test(d.prop);return p||m||b})}function u(f){return f.parent.some(d=>d.prop==="display"&&/(inline-)?flex/.test(d.value))}let c=this.gridStatus(e,t)&&this.prefixes.add["grid-area"]&&this.prefixes.add["grid-area"].prefixes;return e.walkDecls(f=>{if(this.disabledDecl(f,t))return;let d=f.parent,p=f.prop,m=f.value;if(p==="grid-row-span"){t.warn("grid-row-span is not part of final Grid Layout. Use grid-row.",{node:f});return}else if(p==="grid-column-span"){t.warn("grid-column-span is not part of final Grid Layout. Use grid-column.",{node:f});return}else if(p==="display"&&m==="box"){t.warn("You should write display: flex by final spec instead of display: box",{node:f});return}else if(p==="text-emphasis-position")(m==="under"||m==="over")&&t.warn("You should use 2 values for text-emphasis-position For example, `under left` instead of just `under`.",{node:f});else if(/^(align|justify|place)-(items|content)$/.test(p)&&u(f))(m==="start"||m==="end")&&t.warn(`${m} value has mixed support, consider using flex-${m} instead`,{node:f});else if(p==="text-decoration-skip"&&m==="ink")t.warn("Replace text-decoration-skip: ink to text-decoration-skip-ink: auto, because spec had been changed",{node:f});else{if(c&&this.gridStatus(f,t))if(f.value==="subgrid"&&t.warn("IE does not support subgrid",{node:f}),/^(align|justify|place)-items$/.test(p)&&o(f)){let x=p.replace("-items","-self");t.warn(`IE does not support ${p} on grid containers. Try using ${x} on child elements instead: ${f.parent.selector} > * { ${x}: ${f.value} }`,{node:f})}else if(/^(align|justify|place)-content$/.test(p)&&o(f))t.warn(`IE does not support ${f.prop} on grid containers`,{node:f});else if(p==="display"&&f.value==="contents"){t.warn("Please do not use display: contents; if you have grid setting enabled",{node:f});return}else if(f.prop==="grid-gap"){let x=this.gridStatus(f,t);x==="autoplace"&&!SA(f)&&!nl(f)?t.warn("grid-gap only works if grid-template(-areas) is being used or both rows and columns have been declared and cells have not been manually placed inside the explicit grid",{node:f}):(x===!0||x==="no-autoplace")&&!nl(f)&&t.warn("grid-gap only works if grid-template(-areas) is being used",{node:f})}else if(p==="grid-auto-columns"){t.warn("grid-auto-columns is not supported by IE",{node:f});return}else if(p==="grid-auto-rows"){t.warn("grid-auto-rows is not supported by IE",{node:f});return}else if(p==="grid-auto-flow"){let x=d.some(w=>w.prop==="grid-template-rows"),y=d.some(w=>w.prop==="grid-template-columns");nl(f)?t.warn("grid-auto-flow is not supported by IE",{node:f}):m.includes("dense")?t.warn("grid-auto-flow: dense is not supported by IE",{node:f}):!x&&!y&&t.warn("grid-auto-flow works only if grid-template-rows and grid-template-columns are present in the same rule",{node:f});return}else if(m.includes("auto-fit")){t.warn("auto-fit value is not supported by IE",{node:f,word:"auto-fit"});return}else if(m.includes("auto-fill")){t.warn("auto-fill value is not supported by IE",{node:f,word:"auto-fill"});return}else p.startsWith("grid-template")&&m.includes("[")&&t.warn("Autoprefixer currently does not support line names. Try using grid-template-areas instead.",{node:f,word:"["});if(m.includes("radial-gradient"))if(bA.test(f.value))t.warn("Gradient has outdated direction syntax. New syntax is like `closest-side at 0 0` instead of `0 0, closest-side`.",{node:f});else{let x=og(m);for(let y of x.nodes)if(y.type==="function"&&y.value==="radial-gradient")for(let w of y.nodes)w.type==="word"&&(w.value==="cover"?t.warn("Gradient has outdated direction syntax. Replace `cover` to `farthest-corner`.",{node:f}):w.value==="contain"&&t.warn("Gradient has outdated direction syntax. Replace `contain` to `closest-side`.",{node:f}))}m.includes("linear-gradient")&&wA.test(m)&&t.warn("Gradient has outdated direction syntax. New syntax is like `to left` instead of `right`.",{node:f})}kA.includes(f.prop)&&(f.value.includes("-fill-available")||(f.value.includes("fill-available")?t.warn("Replace fill-available to stretch, because spec had been changed",{node:f}):f.value.includes("fill")&&og(m).nodes.some(y=>y.type==="word"&&y.value==="fill")&&t.warn("Replace fill to stretch, because spec had been changed",{node:f})));let b;if(f.prop==="transition"||f.prop==="transition-property")return this.prefixes.transition.add(f,t);if(f.prop==="align-self"){if(this.displayType(f)!=="grid"&&this.prefixes.options.flexbox!==!1&&(b=this.prefixes.add["align-self"],b&&b.prefixes&&b.process(f)),this.gridStatus(f,t)!==!1&&(b=this.prefixes.add["grid-row-align"],b&&b.prefixes))return b.process(f,t)}else if(f.prop==="justify-self"){if(this.gridStatus(f,t)!==!1&&(b=this.prefixes.add["grid-column-align"],b&&b.prefixes))return b.process(f,t)}else if(f.prop==="place-self"){if(b=this.prefixes.add["place-self"],b&&b.prefixes&&this.gridStatus(f,t)!==!1)return b.process(f,t)}else if(b=this.prefixes.add[f.prop],b&&b.prefixes)return b.process(f,t)}),this.gridStatus(e,t)&&yA(e,this.disabled),e.walkDecls(f=>{if(this.disabledValue(f,t))return;let d=this.prefixes.unprefixed(f.prop),p=this.prefixes.values("add",d);if(Array.isArray(p))for(let m of p)m.process&&m.process(f,t);gA.save(this.prefixes,f)})}remove(e,t){let i=this.prefixes.remove["@resolution"];e.walkAtRules((n,a)=>{this.prefixes.remove[`@${n.name}`]?this.disabled(n,t)||n.parent.removeChild(a):n.name==="media"&&n.params.includes("-resolution")&&i&&i.clean(n)});for(let n of this.prefixes.remove.selectors)e.walkRules((a,s)=>{n.check(a)&&(this.disabled(a,t)||a.parent.removeChild(s))});return e.walkDecls((n,a)=>{if(this.disabled(n,t))return;let s=n.parent,o=this.prefixes.unprefixed(n.prop);if((n.prop==="transition"||n.prop==="transition-property")&&this.prefixes.transition.remove(n),this.prefixes.remove[n.prop]&&this.prefixes.remove[n.prop].remove){let u=this.prefixes.group(n).down(c=>this.prefixes.normalize(c.prop)===o);if(o==="flex-flow"&&(u=!0),n.prop==="-webkit-box-orient"){let c={"flex-direction":!0,"flex-flow":!0};if(!n.parent.some(f=>c[f.prop]))return}if(u&&!this.withHackValue(n)){n.raw("before").includes(` -`)&&this.reduceSpaces(n),s.removeChild(a);return}}for(let u of this.prefixes.values("remove",o)){if(!u.check||!u.check(n.value))continue;if(o=u.unprefixed,this.prefixes.group(n).down(f=>f.value.includes(o))){s.removeChild(a);return}}})}withHackValue(e){return e.prop==="-webkit-background-clip"&&e.value==="text"}disabledValue(e,t){return this.gridStatus(e,t)===!1&&e.type==="decl"&&e.prop==="display"&&e.value.includes("grid")||this.prefixes.options.flexbox===!1&&e.type==="decl"&&e.prop==="display"&&e.value.includes("flex")||e.type==="decl"&&e.prop==="content"?!0:this.disabled(e,t)}disabledDecl(e,t){if(this.gridStatus(e,t)===!1&&e.type==="decl"&&(e.prop.includes("grid")||e.prop==="justify-items"))return!0;if(this.prefixes.options.flexbox===!1&&e.type==="decl"){let i=["order","justify-content","align-items","align-content"];if(e.prop.includes("flex")||i.includes(e.prop))return!0}return this.disabled(e,t)}disabled(e,t){if(!e)return!1;if(e._autoprefixerDisabled!==void 0)return e._autoprefixerDisabled;if(e.parent){let n=e.prev();if(n&&n.type==="comment"&&vA.test(n.text))return e._autoprefixerDisabled=!0,e._autoprefixerSelfDisabled=!0,!0}let i=null;if(e.nodes){let n;e.each(a=>{a.type==="comment"&&/(!\s*)?autoprefixer:\s*(off|on)/i.test(a.text)&&(typeof n!="undefined"?t.warn("Second Autoprefixer control comment was ignored. Autoprefixer applies control comment to whole block, not to next rules.",{node:a}):n=/on/i.test(a.text))}),n!==void 0&&(i=!n)}if(!e.nodes||i===null)if(e.parent){let n=this.disabled(e.parent,t);e.parent._autoprefixerSelfDisabled===!0?i=!1:i=n}else i=!1;return e._autoprefixerDisabled=i,i}reduceSpaces(e){let t=!1;if(this.prefixes.group(e).up(()=>(t=!0,!0)),t)return;let i=e.raw("before").split(` -`),n=i[i.length-1].length,a=!1;this.prefixes.group(e).down(s=>{i=s.raw("before").split(` -`);let o=i.length-1;i[o].length>n&&(a===!1&&(a=i[o].length-n),i[o]=i[o].slice(0,-a),s.raws.before=i.join(` -`))})}displayType(e){for(let t of e.parent.nodes)if(t.prop==="display"){if(t.value.includes("flex"))return"flex";if(t.value.includes("grid"))return"grid"}return!1}gridStatus(e,t){if(!e)return!1;if(e._autoprefixerGridStatus!==void 0)return e._autoprefixerGridStatus;let i=null;if(e.nodes){let n;e.each(a=>{if(a.type==="comment"&&xA.test(a.text)){let s=/:\s*autoplace/i.test(a.text),o=/no-autoplace/i.test(a.text);typeof n!="undefined"?t.warn("Second Autoprefixer grid control comment was ignored. Autoprefixer applies control comments to the whole block, not to the next rules.",{node:a}):s?n="autoplace":o?n=!0:n=/on/i.test(a.text)}}),n!==void 0&&(i=n)}if(e.type==="atrule"&&e.name==="supports"){let n=e.params;n.includes("grid")&&n.includes("auto")&&(i=!1)}if(!e.nodes||i===null)if(e.parent){let n=this.gridStatus(e.parent,t);e.parent._autoprefixerSelfDisabled===!0?i=!1:i=n}else typeof this.prefixes.options.grid!="undefined"?i=this.prefixes.options.grid:typeof h.env.AUTOPREFIXER_GRID!="undefined"?h.env.AUTOPREFIXER_GRID==="autoplace"?i="autoplace":i=!0:i=!1;return e._autoprefixerGridStatus=i,i}};ug.exports=lg});var cg=v((jD,fg)=>{l();fg.exports={A:{A:{"2":"K E F G A B JC"},B:{"1":"C L M H N D O P Q R S T U V W X Y Z a b c d e f g h i j n o p q r s t u v w x y z I"},C:{"1":"2 3 4 5 6 7 8 9 AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB PB QB RB SB TB UB VB WB XB YB ZB aB bB cB 0B dB 1B eB fB gB hB iB jB kB lB mB nB oB m pB qB rB sB tB P Q R 2B S T U V W X Y Z a b c d e f g h i j n o p q r s t u v w x y z I uB 3B 4B","2":"0 1 KC zB J K E F G A B C L M H N D O k l LC MC"},D:{"1":"8 9 AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB PB QB RB SB TB UB VB WB XB YB ZB aB bB cB 0B dB 1B eB fB gB hB iB jB kB lB mB nB oB m pB qB rB sB tB P Q R S T U V W X Y Z a b c d e f g h i j n o p q r s t u v w x y z I uB 3B 4B","2":"0 1 2 3 4 5 6 7 J K E F G A B C L M H N D O k l"},E:{"1":"G A B C L M H D RC 6B vB wB 7B SC TC 8B 9B xB AC yB BC CC DC EC FC GC UC","2":"0 J K E F NC 5B OC PC QC"},F:{"1":"1 2 3 4 5 6 7 8 9 H N D O k l AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB PB QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB m pB qB rB sB tB P Q R 2B S T U V W X Y Z a b c d e f g h i j wB","2":"G B C VC WC XC YC vB HC ZC"},G:{"1":"D fC gC hC iC jC kC lC mC nC oC pC qC rC sC tC 8B 9B xB AC yB BC CC DC EC FC GC","2":"F 5B aC IC bC cC dC eC"},H:{"1":"uC"},I:{"1":"I zC 0C","2":"zB J vC wC xC yC IC"},J:{"2":"E A"},K:{"1":"m","2":"A B C vB HC wB"},L:{"1":"I"},M:{"1":"uB"},N:{"2":"A B"},O:{"1":"xB"},P:{"1":"J k l 1C 2C 3C 4C 5C 6B 6C 7C 8C 9C AD yB BD CD DD"},Q:{"1":"7B"},R:{"1":"ED"},S:{"1":"FD GD"}},B:4,C:"CSS Feature Queries"}});var mg=v((VD,hg)=>{l();function pg(r){return r[r.length-1]}var dg={parse(r){let e=[""],t=[e];for(let i of r){if(i==="("){e=[""],pg(t).push(e),t.push(e);continue}if(i===")"){t.pop(),e=pg(t),e.push("");continue}e[e.length-1]+=i}return t[0]},stringify(r){let e="";for(let t of r){if(typeof t=="object"){e+=`(${dg.stringify(t)})`;continue}e+=t}return e}};hg.exports=dg});var vg=v((UD,bg)=>{l();var CA=cg(),{feature:AA}=(Gn(),Wn),{parse:_A}=ge(),OA=dt(),al=mg(),EA=ke(),TA=le(),gg=AA(CA),yg=[];for(let r in gg.stats){let e=gg.stats[r];for(let t in e){let i=e[t];/y/.test(i)&&yg.push(r+" "+t)}}var wg=class{constructor(e,t){this.Prefixes=e,this.all=t}prefixer(){if(this.prefixerCache)return this.prefixerCache;let e=this.all.browsers.selected.filter(i=>yg.includes(i)),t=new OA(this.all.browsers.data,e,this.all.options);return this.prefixerCache=new this.Prefixes(this.all.data,t,this.all.options),this.prefixerCache}parse(e){let t=e.split(":"),i=t[0],n=t[1];return n||(n=""),[i.trim(),n.trim()]}virtual(e){let[t,i]=this.parse(e),n=_A("a{}").first;return n.append({prop:t,value:i,raws:{before:""}}),n}prefixed(e){let t=this.virtual(e);if(this.disabled(t.first))return t.nodes;let i={warn:()=>null},n=this.prefixer().add[t.first.prop];n&&n.process&&n.process(t.first,i);for(let a of t.nodes){for(let s of this.prefixer().values("add",t.first.prop))s.process(a);EA.save(this.all,a)}return t.nodes}isNot(e){return typeof e=="string"&&/not\s*/i.test(e)}isOr(e){return typeof e=="string"&&/\s*or\s*/i.test(e)}isProp(e){return typeof e=="object"&&e.length===1&&typeof e[0]=="string"}isHack(e,t){return!new RegExp(`(\\(|\\s)${TA.escapeRegexp(t)}:`).test(e)}toRemove(e,t){let[i,n]=this.parse(e),a=this.all.unprefixed(i),s=this.all.cleaner();if(s.remove[i]&&s.remove[i].remove&&!this.isHack(t,a))return!0;for(let o of s.values("remove",a))if(o.check(n))return!0;return!1}remove(e,t){let i=0;for(;itypeof t!="object"?t:t.length===1&&typeof t[0]=="object"?this.cleanBrackets(t[0]):this.cleanBrackets(t))}convert(e){let t=[""];for(let i of e)t.push([`${i.prop}: ${i.value}`]),t.push(" or ");return t[t.length-1]="",t}normalize(e){if(typeof e!="object")return e;if(e=e.filter(t=>t!==""),typeof e[0]=="string"){let t=e[0].trim();if(t.includes(":")||t==="selector"||t==="not selector")return[al.stringify(e)]}return e.map(t=>this.normalize(t))}add(e,t){return e.map(i=>{if(this.isProp(i)){let n=this.prefixed(i[0]);return n.length>1?this.convert(n):i}return typeof i=="object"?this.add(i,t):i})}process(e){let t=al.parse(e.params);t=this.normalize(t),t=this.remove(t,e.params),t=this.add(t,e.params),t=this.cleanBrackets(t),e.params=al.stringify(t)}disabled(e){if(!this.all.options.grid&&(e.prop==="display"&&e.value.includes("grid")||e.prop.includes("grid")||e.prop==="justify-items"))return!0;if(this.all.options.flexbox===!1){if(e.prop==="display"&&e.value.includes("flex"))return!0;let t=["order","justify-content","align-items","align-content"];if(e.prop.includes("flex")||t.includes(e.prop))return!0}return!1}};bg.exports=wg});var Sg=v((WD,kg)=>{l();var xg=class{constructor(e,t){this.prefix=t,this.prefixed=e.prefixed(this.prefix),this.regexp=e.regexp(this.prefix),this.prefixeds=e.possible().map(i=>[e.prefixed(i),e.regexp(i)]),this.unprefixed=e.name,this.nameRegexp=e.regexp()}isHack(e){let t=e.parent.index(e)+1,i=e.parent.nodes;for(;t{l();var{list:PA}=ge(),DA=Sg(),IA=Ht(),qA=dt(),RA=le(),Cg=class extends IA{constructor(e,t,i){super(e,t,i);this.regexpCache=new Map}check(e){return e.selector.includes(this.name)?!!e.selector.match(this.regexp()):!1}prefixed(e){return this.name.replace(/^(\W*)/,`$1${e}`)}regexp(e){if(!this.regexpCache.has(e)){let t=e?this.prefixed(e):this.name;this.regexpCache.set(e,new RegExp(`(^|[^:"'=])${RA.escapeRegexp(t)}`,"gi"))}return this.regexpCache.get(e)}possible(){return qA.prefixes()}prefixeds(e){if(e._autoprefixerPrefixeds){if(e._autoprefixerPrefixeds[this.name])return e._autoprefixerPrefixeds}else e._autoprefixerPrefixeds={};let t={};if(e.selector.includes(",")){let n=PA.comma(e.selector).filter(a=>a.includes(this.name));for(let a of this.possible())t[a]=n.map(s=>this.replace(s,a)).join(", ")}else for(let i of this.possible())t[i]=this.replace(e.selector,i);return e._autoprefixerPrefixeds[this.name]=t,e._autoprefixerPrefixeds}already(e,t,i){let n=e.parent.index(e)-1;for(;n>=0;){let a=e.parent.nodes[n];if(a.type!=="rule")return!1;let s=!1;for(let o in t[this.name]){let u=t[this.name][o];if(a.selector===u){if(i===o)return!0;s=!0;break}}if(!s)return!1;n-=1}return!1}replace(e,t){return e.replace(this.regexp(),`$1${this.prefixed(t)}`)}add(e,t){let i=this.prefixeds(e);if(this.already(e,i,t))return;let n=this.clone(e,{selector:i[this.name][t]});e.parent.insertBefore(e,n)}old(e){return new DA(this,e)}};Ag.exports=Cg});var Eg=v((HD,Og)=>{l();var MA=Ht(),_g=class extends MA{add(e,t){let i=t+e.name;if(e.parent.some(s=>s.name===i&&s.params===e.params))return;let a=this.clone(e,{name:i});return e.parent.insertBefore(e,a)}process(e){let t=this.parentPrefix(e);for(let i of this.prefixes)(!t||t===i)&&this.add(e,i)}};Og.exports=_g});var Pg=v((YD,Tg)=>{l();var BA=Jt(),ol=class extends BA{prefixed(e){return e==="-webkit-"?":-webkit-full-screen":e==="-moz-"?":-moz-full-screen":`:${e}fullscreen`}};ol.names=[":fullscreen"];Tg.exports=ol});var Ig=v((QD,Dg)=>{l();var FA=Jt(),ll=class extends FA{possible(){return super.possible().concat(["-moz- old","-ms- old"])}prefixed(e){return e==="-webkit-"?"::-webkit-input-placeholder":e==="-ms-"?"::-ms-input-placeholder":e==="-ms- old"?":-ms-input-placeholder":e==="-moz- old"?":-moz-placeholder":`::${e}placeholder`}};ll.names=["::placeholder"];Dg.exports=ll});var Rg=v((JD,qg)=>{l();var LA=Jt(),ul=class extends LA{prefixed(e){return e==="-ms-"?":-ms-input-placeholder":`:${e}placeholder-shown`}};ul.names=[":placeholder-shown"];qg.exports=ul});var Bg=v((XD,Mg)=>{l();var NA=Jt(),$A=le(),fl=class extends NA{constructor(e,t,i){super(e,t,i);this.prefixes&&(this.prefixes=$A.uniq(this.prefixes.map(n=>"-webkit-")))}prefixed(e){return e==="-webkit-"?"::-webkit-file-upload-button":`::${e}file-selector-button`}};fl.names=["::file-selector-button"];Mg.exports=fl});var pe=v((KD,Fg)=>{l();Fg.exports=function(r){let e;return r==="-webkit- 2009"||r==="-moz-"?e=2009:r==="-ms-"?e=2012:r==="-webkit-"&&(e="final"),r==="-webkit- 2009"&&(r="-webkit-"),[e,r]}});var zg=v((ZD,$g)=>{l();var Lg=ge().list,Ng=pe(),zA=M(),Xt=class extends zA{prefixed(e,t){let i;return[i,t]=Ng(t),i===2009?t+"box-flex":super.prefixed(e,t)}normalize(){return"flex"}set(e,t){let i=Ng(t)[0];if(i===2009)return e.value=Lg.space(e.value)[0],e.value=Xt.oldValues[e.value]||e.value,super.set(e,t);if(i===2012){let n=Lg.space(e.value);n.length===3&&n[2]==="0"&&(e.value=n.slice(0,2).concat("0px").join(" "))}return super.set(e,t)}};Xt.names=["flex","box-flex"];Xt.oldValues={auto:"1",none:"0"};$g.exports=Xt});var Ug=v((eI,Vg)=>{l();var jg=pe(),jA=M(),cl=class extends jA{prefixed(e,t){let i;return[i,t]=jg(t),i===2009?t+"box-ordinal-group":i===2012?t+"flex-order":super.prefixed(e,t)}normalize(){return"order"}set(e,t){return jg(t)[0]===2009&&/\d/.test(e.value)?(e.value=(parseInt(e.value)+1).toString(),super.set(e,t)):super.set(e,t)}};cl.names=["order","flex-order","box-ordinal-group"];Vg.exports=cl});var Gg=v((tI,Wg)=>{l();var VA=M(),pl=class extends VA{check(e){let t=e.value;return!t.toLowerCase().includes("alpha(")&&!t.includes("DXImageTransform.Microsoft")&&!t.includes("data:image/svg+xml")}};pl.names=["filter"];Wg.exports=pl});var Yg=v((rI,Hg)=>{l();var UA=M(),dl=class extends UA{insert(e,t,i,n){if(t!=="-ms-")return super.insert(e,t,i);let a=this.clone(e),s=e.prop.replace(/end$/,"start"),o=t+e.prop.replace(/end$/,"span");if(!e.parent.some(u=>u.prop===o)){if(a.prop=o,e.value.includes("span"))a.value=e.value.replace(/span\s/i,"");else{let u;if(e.parent.walkDecls(s,c=>{u=c}),u){let c=Number(e.value)-Number(u.value)+"";a.value=c}else e.warn(n,`Can not prefix ${e.prop} (${s} is not found)`)}e.cloneBefore(a)}}};dl.names=["grid-row-end","grid-column-end"];Hg.exports=dl});var Jg=v((iI,Qg)=>{l();var WA=M(),hl=class extends WA{check(e){return!e.value.split(/\s+/).some(t=>{let i=t.toLowerCase();return i==="reverse"||i==="alternate-reverse"})}};hl.names=["animation","animation-direction"];Qg.exports=hl});var Kg=v((nI,Xg)=>{l();var GA=pe(),HA=M(),ml=class extends HA{insert(e,t,i){let n;if([n,t]=GA(t),n!==2009)return super.insert(e,t,i);let a=e.value.split(/\s+/).filter(d=>d!=="wrap"&&d!=="nowrap"&&"wrap-reverse");if(a.length===0||e.parent.some(d=>d.prop===t+"box-orient"||d.prop===t+"box-direction"))return;let o=a[0],u=o.includes("row")?"horizontal":"vertical",c=o.includes("reverse")?"reverse":"normal",f=this.clone(e);return f.prop=t+"box-orient",f.value=u,this.needCascade(e)&&(f.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,f),f=this.clone(e),f.prop=t+"box-direction",f.value=c,this.needCascade(e)&&(f.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,f)}};ml.names=["flex-flow","box-direction","box-orient"];Xg.exports=ml});var ey=v((sI,Zg)=>{l();var YA=pe(),QA=M(),gl=class extends QA{normalize(){return"flex"}prefixed(e,t){let i;return[i,t]=YA(t),i===2009?t+"box-flex":i===2012?t+"flex-positive":super.prefixed(e,t)}};gl.names=["flex-grow","flex-positive"];Zg.exports=gl});var ry=v((aI,ty)=>{l();var JA=pe(),XA=M(),yl=class extends XA{set(e,t){if(JA(t)[0]!==2009)return super.set(e,t)}};yl.names=["flex-wrap"];ty.exports=yl});var ny=v((oI,iy)=>{l();var KA=M(),Kt=mt(),wl=class extends KA{insert(e,t,i,n){if(t!=="-ms-")return super.insert(e,t,i);let a=Kt.parse(e),[s,o]=Kt.translate(a,0,2),[u,c]=Kt.translate(a,1,3);[["grid-row",s],["grid-row-span",o],["grid-column",u],["grid-column-span",c]].forEach(([f,d])=>{Kt.insertDecl(e,f,d)}),Kt.warnTemplateSelectorNotFound(e,n),Kt.warnIfGridRowColumnExists(e,n)}};wl.names=["grid-area"];iy.exports=wl});var ay=v((lI,sy)=>{l();var ZA=M(),oi=mt(),bl=class extends ZA{insert(e,t,i){if(t!=="-ms-")return super.insert(e,t,i);if(e.parent.some(s=>s.prop==="-ms-grid-row-align"))return;let[[n,a]]=oi.parse(e);a?(oi.insertDecl(e,"grid-row-align",n),oi.insertDecl(e,"grid-column-align",a)):(oi.insertDecl(e,"grid-row-align",n),oi.insertDecl(e,"grid-column-align",n))}};bl.names=["place-self"];sy.exports=bl});var ly=v((uI,oy)=>{l();var e5=M(),vl=class extends e5{check(e){let t=e.value;return!t.includes("/")||t.includes("span")}normalize(e){return e.replace("-start","")}prefixed(e,t){let i=super.prefixed(e,t);return t==="-ms-"&&(i=i.replace("-start","")),i}};vl.names=["grid-row-start","grid-column-start"];oy.exports=vl});var cy=v((fI,fy)=>{l();var uy=pe(),t5=M(),Zt=class extends t5{check(e){return e.parent&&!e.parent.some(t=>t.prop&&t.prop.startsWith("grid-"))}prefixed(e,t){let i;return[i,t]=uy(t),i===2012?t+"flex-item-align":super.prefixed(e,t)}normalize(){return"align-self"}set(e,t){let i=uy(t)[0];if(i===2012)return e.value=Zt.oldValues[e.value]||e.value,super.set(e,t);if(i==="final")return super.set(e,t)}};Zt.names=["align-self","flex-item-align"];Zt.oldValues={"flex-end":"end","flex-start":"start"};fy.exports=Zt});var dy=v((cI,py)=>{l();var r5=M(),i5=le(),xl=class extends r5{constructor(e,t,i){super(e,t,i);this.prefixes&&(this.prefixes=i5.uniq(this.prefixes.map(n=>n==="-ms-"?"-webkit-":n)))}};xl.names=["appearance"];py.exports=xl});var gy=v((pI,my)=>{l();var hy=pe(),n5=M(),kl=class extends n5{normalize(){return"flex-basis"}prefixed(e,t){let i;return[i,t]=hy(t),i===2012?t+"flex-preferred-size":super.prefixed(e,t)}set(e,t){let i;if([i,t]=hy(t),i===2012||i==="final")return super.set(e,t)}};kl.names=["flex-basis","flex-preferred-size"];my.exports=kl});var wy=v((dI,yy)=>{l();var s5=M(),Sl=class extends s5{normalize(){return this.name.replace("box-image","border")}prefixed(e,t){let i=super.prefixed(e,t);return t==="-webkit-"&&(i=i.replace("border","box-image")),i}};Sl.names=["mask-border","mask-border-source","mask-border-slice","mask-border-width","mask-border-outset","mask-border-repeat","mask-box-image","mask-box-image-source","mask-box-image-slice","mask-box-image-width","mask-box-image-outset","mask-box-image-repeat"];yy.exports=Sl});var vy=v((hI,by)=>{l();var a5=M(),Ne=class extends a5{insert(e,t,i){let n=e.prop==="mask-composite",a;n?a=e.value.split(","):a=e.value.match(Ne.regexp)||[],a=a.map(c=>c.trim()).filter(c=>c);let s=a.length,o;if(s&&(o=this.clone(e),o.value=a.map(c=>Ne.oldValues[c]||c).join(", "),a.includes("intersect")&&(o.value+=", xor"),o.prop=t+"mask-composite"),n)return s?(this.needCascade(e)&&(o.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,o)):void 0;let u=this.clone(e);return u.prop=t+u.prop,s&&(u.value=u.value.replace(Ne.regexp,"")),this.needCascade(e)&&(u.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,u),s?(this.needCascade(e)&&(o.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,o)):e}};Ne.names=["mask","mask-composite"];Ne.oldValues={add:"source-over",subtract:"source-out",intersect:"source-in",exclude:"xor"};Ne.regexp=new RegExp(`\\s+(${Object.keys(Ne.oldValues).join("|")})\\b(?!\\))\\s*(?=[,])`,"ig");by.exports=Ne});var Sy=v((mI,ky)=>{l();var xy=pe(),o5=M(),er=class extends o5{prefixed(e,t){let i;return[i,t]=xy(t),i===2009?t+"box-align":i===2012?t+"flex-align":super.prefixed(e,t)}normalize(){return"align-items"}set(e,t){let i=xy(t)[0];return(i===2009||i===2012)&&(e.value=er.oldValues[e.value]||e.value),super.set(e,t)}};er.names=["align-items","flex-align","box-align"];er.oldValues={"flex-end":"end","flex-start":"start"};ky.exports=er});var Ay=v((gI,Cy)=>{l();var l5=M(),Cl=class extends l5{set(e,t){return t==="-ms-"&&e.value==="contain"&&(e.value="element"),super.set(e,t)}insert(e,t,i){if(!(e.value==="all"&&t==="-ms-"))return super.insert(e,t,i)}};Cl.names=["user-select"];Cy.exports=Cl});var Ey=v((yI,Oy)=>{l();var _y=pe(),u5=M(),Al=class extends u5{normalize(){return"flex-shrink"}prefixed(e,t){let i;return[i,t]=_y(t),i===2012?t+"flex-negative":super.prefixed(e,t)}set(e,t){let i;if([i,t]=_y(t),i===2012||i==="final")return super.set(e,t)}};Al.names=["flex-shrink","flex-negative"];Oy.exports=Al});var Py=v((wI,Ty)=>{l();var f5=M(),_l=class extends f5{prefixed(e,t){return`${t}column-${e}`}normalize(e){return e.includes("inside")?"break-inside":e.includes("before")?"break-before":"break-after"}set(e,t){return(e.prop==="break-inside"&&e.value==="avoid-column"||e.value==="avoid-page")&&(e.value="avoid"),super.set(e,t)}insert(e,t,i){if(e.prop!=="break-inside")return super.insert(e,t,i);if(!(/region/i.test(e.value)||/page/i.test(e.value)))return super.insert(e,t,i)}};_l.names=["break-inside","page-break-inside","column-break-inside","break-before","page-break-before","column-break-before","break-after","page-break-after","column-break-after"];Ty.exports=_l});var Iy=v((bI,Dy)=>{l();var c5=M(),Ol=class extends c5{prefixed(e,t){return t+"print-color-adjust"}normalize(){return"color-adjust"}};Ol.names=["color-adjust","print-color-adjust"];Dy.exports=Ol});var Ry=v((vI,qy)=>{l();var p5=M(),tr=class extends p5{insert(e,t,i){if(t==="-ms-"){let n=this.set(this.clone(e),t);this.needCascade(e)&&(n.raws.before=this.calcBefore(i,e,t));let a="ltr";return e.parent.nodes.forEach(s=>{s.prop==="direction"&&(s.value==="rtl"||s.value==="ltr")&&(a=s.value)}),n.value=tr.msValues[a][e.value]||e.value,e.parent.insertBefore(e,n)}return super.insert(e,t,i)}};tr.names=["writing-mode"];tr.msValues={ltr:{"horizontal-tb":"lr-tb","vertical-rl":"tb-rl","vertical-lr":"tb-lr"},rtl:{"horizontal-tb":"rl-tb","vertical-rl":"bt-rl","vertical-lr":"bt-lr"}};qy.exports=tr});var By=v((xI,My)=>{l();var d5=M(),El=class extends d5{set(e,t){return e.value=e.value.replace(/\s+fill(\s)/,"$1"),super.set(e,t)}};El.names=["border-image"];My.exports=El});var Ny=v((kI,Ly)=>{l();var Fy=pe(),h5=M(),rr=class extends h5{prefixed(e,t){let i;return[i,t]=Fy(t),i===2012?t+"flex-line-pack":super.prefixed(e,t)}normalize(){return"align-content"}set(e,t){let i=Fy(t)[0];if(i===2012)return e.value=rr.oldValues[e.value]||e.value,super.set(e,t);if(i==="final")return super.set(e,t)}};rr.names=["align-content","flex-line-pack"];rr.oldValues={"flex-end":"end","flex-start":"start","space-between":"justify","space-around":"distribute"};Ly.exports=rr});var zy=v((SI,$y)=>{l();var m5=M(),Se=class extends m5{prefixed(e,t){return t==="-moz-"?t+(Se.toMozilla[e]||e):super.prefixed(e,t)}normalize(e){return Se.toNormal[e]||e}};Se.names=["border-radius"];Se.toMozilla={};Se.toNormal={};for(let r of["top","bottom"])for(let e of["left","right"]){let t=`border-${r}-${e}-radius`,i=`border-radius-${r}${e}`;Se.names.push(t),Se.names.push(i),Se.toMozilla[t]=i,Se.toNormal[i]=t}$y.exports=Se});var Vy=v((CI,jy)=>{l();var g5=M(),Tl=class extends g5{prefixed(e,t){return e.includes("-start")?t+e.replace("-block-start","-before"):t+e.replace("-block-end","-after")}normalize(e){return e.includes("-before")?e.replace("-before","-block-start"):e.replace("-after","-block-end")}};Tl.names=["border-block-start","border-block-end","margin-block-start","margin-block-end","padding-block-start","padding-block-end","border-before","border-after","margin-before","margin-after","padding-before","padding-after"];jy.exports=Tl});var Wy=v((AI,Uy)=>{l();var y5=M(),{parseTemplate:w5,warnMissedAreas:b5,getGridGap:v5,warnGridGap:x5,inheritGridGap:k5}=mt(),Pl=class extends y5{insert(e,t,i,n){if(t!=="-ms-")return super.insert(e,t,i);if(e.parent.some(m=>m.prop==="-ms-grid-rows"))return;let a=v5(e),s=k5(e,a),{rows:o,columns:u,areas:c}=w5({decl:e,gap:s||a}),f=Object.keys(c).length>0,d=Boolean(o),p=Boolean(u);return x5({gap:a,hasColumns:p,decl:e,result:n}),b5(c,e,n),(d&&p||f)&&e.cloneBefore({prop:"-ms-grid-rows",value:o,raws:{}}),p&&e.cloneBefore({prop:"-ms-grid-columns",value:u,raws:{}}),e}};Pl.names=["grid-template"];Uy.exports=Pl});var Hy=v((_I,Gy)=>{l();var S5=M(),Dl=class extends S5{prefixed(e,t){return t+e.replace("-inline","")}normalize(e){return e.replace(/(margin|padding|border)-(start|end)/,"$1-inline-$2")}};Dl.names=["border-inline-start","border-inline-end","margin-inline-start","margin-inline-end","padding-inline-start","padding-inline-end","border-start","border-end","margin-start","margin-end","padding-start","padding-end"];Gy.exports=Dl});var Qy=v((OI,Yy)=>{l();var C5=M(),Il=class extends C5{check(e){return!e.value.includes("flex-")&&e.value!=="baseline"}prefixed(e,t){return t+"grid-row-align"}normalize(){return"align-self"}};Il.names=["grid-row-align"];Yy.exports=Il});var Xy=v((EI,Jy)=>{l();var A5=M(),ir=class extends A5{keyframeParents(e){let{parent:t}=e;for(;t;){if(t.type==="atrule"&&t.name==="keyframes")return!0;({parent:t}=t)}return!1}contain3d(e){if(e.prop==="transform-origin")return!1;for(let t of ir.functions3d)if(e.value.includes(`${t}(`))return!0;return!1}set(e,t){return e=super.set(e,t),t==="-ms-"&&(e.value=e.value.replace(/rotatez/gi,"rotate")),e}insert(e,t,i){if(t==="-ms-"){if(!this.contain3d(e)&&!this.keyframeParents(e))return super.insert(e,t,i)}else if(t==="-o-"){if(!this.contain3d(e))return super.insert(e,t,i)}else return super.insert(e,t,i)}};ir.names=["transform","transform-origin"];ir.functions3d=["matrix3d","translate3d","translateZ","scale3d","scaleZ","rotate3d","rotateX","rotateY","perspective"];Jy.exports=ir});var ew=v((TI,Zy)=>{l();var Ky=pe(),_5=M(),ql=class extends _5{normalize(){return"flex-direction"}insert(e,t,i){let n;if([n,t]=Ky(t),n!==2009)return super.insert(e,t,i);if(e.parent.some(f=>f.prop===t+"box-orient"||f.prop===t+"box-direction"))return;let s=e.value,o,u;s==="inherit"||s==="initial"||s==="unset"?(o=s,u=s):(o=s.includes("row")?"horizontal":"vertical",u=s.includes("reverse")?"reverse":"normal");let c=this.clone(e);return c.prop=t+"box-orient",c.value=o,this.needCascade(e)&&(c.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,c),c=this.clone(e),c.prop=t+"box-direction",c.value=u,this.needCascade(e)&&(c.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,c)}old(e,t){let i;return[i,t]=Ky(t),i===2009?[t+"box-orient",t+"box-direction"]:super.old(e,t)}};ql.names=["flex-direction","box-direction","box-orient"];Zy.exports=ql});var rw=v((PI,tw)=>{l();var O5=M(),Rl=class extends O5{check(e){return e.value==="pixelated"}prefixed(e,t){return t==="-ms-"?"-ms-interpolation-mode":super.prefixed(e,t)}set(e,t){return t!=="-ms-"?super.set(e,t):(e.prop="-ms-interpolation-mode",e.value="nearest-neighbor",e)}normalize(){return"image-rendering"}process(e,t){return super.process(e,t)}};Rl.names=["image-rendering","interpolation-mode"];tw.exports=Rl});var nw=v((DI,iw)=>{l();var E5=M(),T5=le(),Ml=class extends E5{constructor(e,t,i){super(e,t,i);this.prefixes&&(this.prefixes=T5.uniq(this.prefixes.map(n=>n==="-ms-"?"-webkit-":n)))}};Ml.names=["backdrop-filter"];iw.exports=Ml});var aw=v((II,sw)=>{l();var P5=M(),D5=le(),Bl=class extends P5{constructor(e,t,i){super(e,t,i);this.prefixes&&(this.prefixes=D5.uniq(this.prefixes.map(n=>n==="-ms-"?"-webkit-":n)))}check(e){return e.value.toLowerCase()==="text"}};Bl.names=["background-clip"];sw.exports=Bl});var lw=v((qI,ow)=>{l();var I5=M(),q5=["none","underline","overline","line-through","blink","inherit","initial","unset"],Fl=class extends I5{check(e){return e.value.split(/\s+/).some(t=>!q5.includes(t))}};Fl.names=["text-decoration"];ow.exports=Fl});var cw=v((RI,fw)=>{l();var uw=pe(),R5=M(),nr=class extends R5{prefixed(e,t){let i;return[i,t]=uw(t),i===2009?t+"box-pack":i===2012?t+"flex-pack":super.prefixed(e,t)}normalize(){return"justify-content"}set(e,t){let i=uw(t)[0];if(i===2009||i===2012){let n=nr.oldValues[e.value]||e.value;if(e.value=n,i!==2009||n!=="distribute")return super.set(e,t)}else if(i==="final")return super.set(e,t)}};nr.names=["justify-content","flex-pack","box-pack"];nr.oldValues={"flex-end":"end","flex-start":"start","space-between":"justify","space-around":"distribute"};fw.exports=nr});var dw=v((MI,pw)=>{l();var M5=M(),Ll=class extends M5{set(e,t){let i=e.value.toLowerCase();return t==="-webkit-"&&!i.includes(" ")&&i!=="contain"&&i!=="cover"&&(e.value=e.value+" "+e.value),super.set(e,t)}};Ll.names=["background-size"];pw.exports=Ll});var mw=v((BI,hw)=>{l();var B5=M(),Nl=mt(),$l=class extends B5{insert(e,t,i){if(t!=="-ms-")return super.insert(e,t,i);let n=Nl.parse(e),[a,s]=Nl.translate(n,0,1);n[0]&&n[0].includes("span")&&(s=n[0].join("").replace(/\D/g,"")),[[e.prop,a],[`${e.prop}-span`,s]].forEach(([u,c])=>{Nl.insertDecl(e,u,c)})}};$l.names=["grid-row","grid-column"];hw.exports=$l});var ww=v((FI,yw)=>{l();var F5=M(),{prefixTrackProp:gw,prefixTrackValue:L5,autoplaceGridItems:N5,getGridGap:$5,inheritGridGap:z5}=mt(),j5=sl(),zl=class extends F5{prefixed(e,t){return t==="-ms-"?gw({prop:e,prefix:t}):super.prefixed(e,t)}normalize(e){return e.replace(/^grid-(rows|columns)/,"grid-template-$1")}insert(e,t,i,n){if(t!=="-ms-")return super.insert(e,t,i);let{parent:a,prop:s,value:o}=e,u=s.includes("rows"),c=s.includes("columns"),f=a.some(k=>k.prop==="grid-template"||k.prop==="grid-template-areas");if(f&&u)return!1;let d=new j5({options:{}}),p=d.gridStatus(a,n),m=$5(e);m=z5(e,m)||m;let b=u?m.row:m.column;(p==="no-autoplace"||p===!0)&&!f&&(b=null);let x=L5({value:o,gap:b});e.cloneBefore({prop:gw({prop:s,prefix:t}),value:x});let y=a.nodes.find(k=>k.prop==="grid-auto-flow"),w="row";if(y&&!d.disabled(y,n)&&(w=y.value.trim()),p==="autoplace"){let k=a.nodes.find(_=>_.prop==="grid-template-rows");if(!k&&f)return;if(!k&&!f){e.warn(n,"Autoplacement does not work without grid-template-rows property");return}!a.nodes.find(_=>_.prop==="grid-template-columns")&&!f&&e.warn(n,"Autoplacement does not work without grid-template-columns property"),c&&!f&&N5(e,n,m,w)}}};zl.names=["grid-template-rows","grid-template-columns","grid-rows","grid-columns"];yw.exports=zl});var vw=v((LI,bw)=>{l();var V5=M(),jl=class extends V5{check(e){return!e.value.includes("flex-")&&e.value!=="baseline"}prefixed(e,t){return t+"grid-column-align"}normalize(){return"justify-self"}};jl.names=["grid-column-align"];bw.exports=jl});var kw=v((NI,xw)=>{l();var U5=M(),Vl=class extends U5{prefixed(e,t){return t+"scroll-chaining"}normalize(){return"overscroll-behavior"}set(e,t){return e.value==="auto"?e.value="chained":(e.value==="none"||e.value==="contain")&&(e.value="none"),super.set(e,t)}};Vl.names=["overscroll-behavior","scroll-chaining"];xw.exports=Vl});var Aw=v(($I,Cw)=>{l();var W5=M(),{parseGridAreas:G5,warnMissedAreas:H5,prefixTrackProp:Y5,prefixTrackValue:Sw,getGridGap:Q5,warnGridGap:J5,inheritGridGap:X5}=mt();function K5(r){return r.trim().slice(1,-1).split(/["']\s*["']?/g)}var Ul=class extends W5{insert(e,t,i,n){if(t!=="-ms-")return super.insert(e,t,i);let a=!1,s=!1,o=e.parent,u=Q5(e);u=X5(e,u)||u,o.walkDecls(/-ms-grid-rows/,d=>d.remove()),o.walkDecls(/grid-template-(rows|columns)/,d=>{if(d.prop==="grid-template-rows"){s=!0;let{prop:p,value:m}=d;d.cloneBefore({prop:Y5({prop:p,prefix:t}),value:Sw({value:m,gap:u.row})})}else a=!0});let c=K5(e.value);a&&!s&&u.row&&c.length>1&&e.cloneBefore({prop:"-ms-grid-rows",value:Sw({value:`repeat(${c.length}, auto)`,gap:u.row}),raws:{}}),J5({gap:u,hasColumns:a,decl:e,result:n});let f=G5({rows:c,gap:u});return H5(f,e,n),e}};Ul.names=["grid-template-areas"];Cw.exports=Ul});var Ow=v((zI,_w)=>{l();var Z5=M(),Wl=class extends Z5{set(e,t){return t==="-webkit-"&&(e.value=e.value.replace(/\s*(right|left)\s*/i,"")),super.set(e,t)}};Wl.names=["text-emphasis-position"];_w.exports=Wl});var Tw=v((jI,Ew)=>{l();var e_=M(),Gl=class extends e_{set(e,t){return e.prop==="text-decoration-skip-ink"&&e.value==="auto"?(e.prop=t+"text-decoration-skip",e.value="ink",e):super.set(e,t)}};Gl.names=["text-decoration-skip-ink","text-decoration-skip"];Ew.exports=Gl});var Mw=v((VI,Rw)=>{l();"use strict";Rw.exports={wrap:Pw,limit:Dw,validate:Iw,test:Hl,curry:t_,name:qw};function Pw(r,e,t){var i=e-r;return((t-r)%i+i)%i+r}function Dw(r,e,t){return Math.max(r,Math.min(e,t))}function Iw(r,e,t,i,n){if(!Hl(r,e,t,i,n))throw new Error(t+" is outside of range ["+r+","+e+")");return t}function Hl(r,e,t,i,n){return!(te||n&&t===e||i&&t===r)}function qw(r,e,t,i){return(t?"(":"[")+r+","+e+(i?")":"]")}function t_(r,e,t,i){var n=qw.bind(null,r,e,t,i);return{wrap:Pw.bind(null,r,e),limit:Dw.bind(null,r,e),validate:function(a){return Iw(r,e,a,t,i)},test:function(a){return Hl(r,e,a,t,i)},toString:n,name:n}}});var Lw=v((UI,Fw)=>{l();var Yl=Kn(),r_=Mw(),i_=Qt(),n_=ke(),s_=le(),Bw=/top|left|right|bottom/gi,Qe=class extends n_{replace(e,t){let i=Yl(e);for(let n of i.nodes)if(n.type==="function"&&n.value===this.name)if(n.nodes=this.newDirection(n.nodes),n.nodes=this.normalize(n.nodes),t==="-webkit- old"){if(!this.oldWebkit(n))return!1}else n.nodes=this.convertDirection(n.nodes),n.value=t+n.value;return i.toString()}replaceFirst(e,...t){return t.map(n=>n===" "?{type:"space",value:n}:{type:"word",value:n}).concat(e.slice(1))}normalizeUnit(e,t){return`${parseFloat(e)/t*360}deg`}normalize(e){if(!e[0])return e;if(/-?\d+(.\d+)?grad/.test(e[0].value))e[0].value=this.normalizeUnit(e[0].value,400);else if(/-?\d+(.\d+)?rad/.test(e[0].value))e[0].value=this.normalizeUnit(e[0].value,2*Math.PI);else if(/-?\d+(.\d+)?turn/.test(e[0].value))e[0].value=this.normalizeUnit(e[0].value,1);else if(e[0].value.includes("deg")){let t=parseFloat(e[0].value);t=r_.wrap(0,360,t),e[0].value=`${t}deg`}return e[0].value==="0deg"?e=this.replaceFirst(e,"to"," ","top"):e[0].value==="90deg"?e=this.replaceFirst(e,"to"," ","right"):e[0].value==="180deg"?e=this.replaceFirst(e,"to"," ","bottom"):e[0].value==="270deg"&&(e=this.replaceFirst(e,"to"," ","left")),e}newDirection(e){if(e[0].value==="to"||(Bw.lastIndex=0,!Bw.test(e[0].value)))return e;e.unshift({type:"word",value:"to"},{type:"space",value:" "});for(let t=2;t0&&(e[0].value==="to"?this.fixDirection(e):e[0].value.includes("deg")?this.fixAngle(e):this.isRadial(e)&&this.fixRadial(e)),e}fixDirection(e){e.splice(0,2);for(let t of e){if(t.type==="div")break;t.type==="word"&&(t.value=this.revertDirection(t.value))}}fixAngle(e){let t=e[0].value;t=parseFloat(t),t=Math.abs(450-t)%360,t=this.roundFloat(t,3),e[0].value=`${t}deg`}fixRadial(e){let t=[],i=[],n,a,s,o,u;for(o=0;o{l();var a_=Qt(),o_=ke();function Nw(r){return new RegExp(`(^|[\\s,(])(${r}($|[\\s),]))`,"gi")}var Ql=class extends o_{regexp(){return this.regexpCache||(this.regexpCache=Nw(this.name)),this.regexpCache}isStretch(){return this.name==="stretch"||this.name==="fill"||this.name==="fill-available"}replace(e,t){return t==="-moz-"&&this.isStretch()?e.replace(this.regexp(),"$1-moz-available$3"):t==="-webkit-"&&this.isStretch()?e.replace(this.regexp(),"$1-webkit-fill-available$3"):super.replace(e,t)}old(e){let t=e+this.name;return this.isStretch()&&(e==="-moz-"?t="-moz-available":e==="-webkit-"&&(t="-webkit-fill-available")),new a_(this.name,t,t,Nw(t))}add(e,t){if(!(e.prop.includes("grid")&&t!=="-webkit-"))return super.add(e,t)}};Ql.names=["max-content","min-content","fit-content","fill","fill-available","stretch"];$w.exports=Ql});var Uw=v((GI,Vw)=>{l();var jw=Qt(),l_=ke(),Jl=class extends l_{replace(e,t){return t==="-webkit-"?e.replace(this.regexp(),"$1-webkit-optimize-contrast"):t==="-moz-"?e.replace(this.regexp(),"$1-moz-crisp-edges"):super.replace(e,t)}old(e){return e==="-webkit-"?new jw(this.name,"-webkit-optimize-contrast"):e==="-moz-"?new jw(this.name,"-moz-crisp-edges"):super.old(e)}};Jl.names=["pixelated"];Vw.exports=Jl});var Gw=v((HI,Ww)=>{l();var u_=ke(),Xl=class extends u_{replace(e,t){let i=super.replace(e,t);return t==="-webkit-"&&(i=i.replace(/("[^"]+"|'[^']+')(\s+\d+\w)/gi,"url($1)$2")),i}};Xl.names=["image-set"];Ww.exports=Xl});var Yw=v((YI,Hw)=>{l();var f_=ge().list,c_=ke(),Kl=class extends c_{replace(e,t){return f_.space(e).map(i=>{if(i.slice(0,+this.name.length+1)!==this.name+"(")return i;let n=i.lastIndexOf(")"),a=i.slice(n+1),s=i.slice(this.name.length+1,n);if(t==="-webkit-"){let o=s.match(/\d*.?\d+%?/);o?(s=s.slice(o[0].length).trim(),s+=`, ${o[0]}`):s+=", 0.5"}return t+this.name+"("+s+")"+a}).join(" ")}};Kl.names=["cross-fade"];Hw.exports=Kl});var Jw=v((QI,Qw)=>{l();var p_=pe(),d_=Qt(),h_=ke(),Zl=class extends h_{constructor(e,t){super(e,t);e==="display-flex"&&(this.name="flex")}check(e){return e.prop==="display"&&e.value===this.name}prefixed(e){let t,i;return[t,e]=p_(e),t===2009?this.name==="flex"?i="box":i="inline-box":t===2012?this.name==="flex"?i="flexbox":i="inline-flexbox":t==="final"&&(i=this.name),e+i}replace(e,t){return this.prefixed(t)}old(e){let t=this.prefixed(e);if(!!t)return new d_(this.name,t)}};Zl.names=["display-flex","inline-flex"];Qw.exports=Zl});var Kw=v((JI,Xw)=>{l();var m_=ke(),eu=class extends m_{constructor(e,t){super(e,t);e==="display-grid"&&(this.name="grid")}check(e){return e.prop==="display"&&e.value===this.name}};eu.names=["display-grid","inline-grid"];Xw.exports=eu});var eb=v((XI,Zw)=>{l();var g_=ke(),tu=class extends g_{constructor(e,t){super(e,t);e==="filter-function"&&(this.name="filter")}};tu.names=["filter","filter-function"];Zw.exports=tu});var nb=v((KI,ib)=>{l();var tb=ai(),B=M(),rb=Fm(),y_=tg(),w_=sl(),b_=vg(),ru=dt(),sr=Jt(),v_=Eg(),$e=ke(),ar=le(),x_=Pg(),k_=Ig(),S_=Rg(),C_=Bg(),A_=zg(),__=Ug(),O_=Gg(),E_=Yg(),T_=Jg(),P_=Kg(),D_=ey(),I_=ry(),q_=ny(),R_=ay(),M_=ly(),B_=cy(),F_=dy(),L_=gy(),N_=wy(),$_=vy(),z_=Sy(),j_=Ay(),V_=Ey(),U_=Py(),W_=Iy(),G_=Ry(),H_=By(),Y_=Ny(),Q_=zy(),J_=Vy(),X_=Wy(),K_=Hy(),Z_=Qy(),eO=Xy(),tO=ew(),rO=rw(),iO=nw(),nO=aw(),sO=lw(),aO=cw(),oO=dw(),lO=mw(),uO=ww(),fO=vw(),cO=kw(),pO=Aw(),dO=Ow(),hO=Tw(),mO=Lw(),gO=zw(),yO=Uw(),wO=Gw(),bO=Yw(),vO=Jw(),xO=Kw(),kO=eb();sr.hack(x_);sr.hack(k_);sr.hack(S_);sr.hack(C_);B.hack(A_);B.hack(__);B.hack(O_);B.hack(E_);B.hack(T_);B.hack(P_);B.hack(D_);B.hack(I_);B.hack(q_);B.hack(R_);B.hack(M_);B.hack(B_);B.hack(F_);B.hack(L_);B.hack(N_);B.hack($_);B.hack(z_);B.hack(j_);B.hack(V_);B.hack(U_);B.hack(W_);B.hack(G_);B.hack(H_);B.hack(Y_);B.hack(Q_);B.hack(J_);B.hack(X_);B.hack(K_);B.hack(Z_);B.hack(eO);B.hack(tO);B.hack(rO);B.hack(iO);B.hack(nO);B.hack(sO);B.hack(aO);B.hack(oO);B.hack(lO);B.hack(uO);B.hack(fO);B.hack(cO);B.hack(pO);B.hack(dO);B.hack(hO);$e.hack(mO);$e.hack(gO);$e.hack(yO);$e.hack(wO);$e.hack(bO);$e.hack(vO);$e.hack(xO);$e.hack(kO);var iu=new Map,li=class{constructor(e,t,i={}){this.data=e,this.browsers=t,this.options=i,[this.add,this.remove]=this.preprocess(this.select(this.data)),this.transition=new y_(this),this.processor=new w_(this)}cleaner(){if(this.cleanerCache)return this.cleanerCache;if(this.browsers.selected.length){let e=new ru(this.browsers.data,[]);this.cleanerCache=new li(this.data,e,this.options)}else return this;return this.cleanerCache}select(e){let t={add:{},remove:{}};for(let i in e){let n=e[i],a=n.browsers.map(u=>{let c=u.split(" ");return{browser:`${c[0]} ${c[1]}`,note:c[2]}}),s=a.filter(u=>u.note).map(u=>`${this.browsers.prefix(u.browser)} ${u.note}`);s=ar.uniq(s),a=a.filter(u=>this.browsers.isSelected(u.browser)).map(u=>{let c=this.browsers.prefix(u.browser);return u.note?`${c} ${u.note}`:c}),a=this.sort(ar.uniq(a)),this.options.flexbox==="no-2009"&&(a=a.filter(u=>!u.includes("2009")));let o=n.browsers.map(u=>this.browsers.prefix(u));n.mistakes&&(o=o.concat(n.mistakes)),o=o.concat(s),o=ar.uniq(o),a.length?(t.add[i]=a,a.length!a.includes(u)))):t.remove[i]=o}return t}sort(e){return e.sort((t,i)=>{let n=ar.removeNote(t).length,a=ar.removeNote(i).length;return n===a?i.length-t.length:a-n})}preprocess(e){let t={selectors:[],"@supports":new b_(li,this)};for(let n in e.add){let a=e.add[n];if(n==="@keyframes"||n==="@viewport")t[n]=new v_(n,a,this);else if(n==="@resolution")t[n]=new rb(n,a,this);else if(this.data[n].selector)t.selectors.push(sr.load(n,a,this));else{let s=this.data[n].props;if(s){let o=$e.load(n,a,this);for(let u of s)t[u]||(t[u]={values:[]}),t[u].values.push(o)}else{let o=t[n]&&t[n].values||[];t[n]=B.load(n,a,this),t[n].values=o}}}let i={selectors:[]};for(let n in e.remove){let a=e.remove[n];if(this.data[n].selector){let s=sr.load(n,a);for(let o of a)i.selectors.push(s.old(o))}else if(n==="@keyframes"||n==="@viewport")for(let s of a){let o=`@${s}${n.slice(1)}`;i[o]={remove:!0}}else if(n==="@resolution")i[n]=new rb(n,a,this);else{let s=this.data[n].props;if(s){let o=$e.load(n,[],this);for(let u of a){let c=o.old(u);if(c)for(let f of s)i[f]||(i[f]={}),i[f].values||(i[f].values=[]),i[f].values.push(c)}}else for(let o of a){let u=this.decl(n).old(n,o);if(n==="align-self"){let c=t[n]&&t[n].prefixes;if(c){if(o==="-webkit- 2009"&&c.includes("-webkit-"))continue;if(o==="-webkit-"&&c.includes("-webkit- 2009"))continue}}for(let c of u)i[c]||(i[c]={}),i[c].remove=!0}}}return[t,i]}decl(e){return iu.has(e)||iu.set(e,B.load(e)),iu.get(e)}unprefixed(e){let t=this.normalize(tb.unprefixed(e));return t==="flex-direction"&&(t="flex-flow"),t}normalize(e){return this.decl(e).normalize(e)}prefixed(e,t){return e=tb.unprefixed(e),this.decl(e).prefixed(e,t)}values(e,t){let i=this[e],n=i["*"]&&i["*"].values,a=i[t]&&i[t].values;return n&&a?ar.uniq(n.concat(a)):n||a||[]}group(e){let t=e.parent,i=t.index(e),{length:n}=t.nodes,a=this.unprefixed(e.prop),s=(o,u)=>{for(i+=o;i>=0&&i{l();sb.exports={"backdrop-filter":{feature:"css-backdrop-filter",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5","safari 16.5"]},element:{props:["background","background-image","border-image","mask","list-style","list-style-image","content","mask-image"],feature:"css-element-function",browsers:["firefox 114"]},"user-select":{mistakes:["-khtml-"],feature:"user-select-none",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5","safari 16.5"]},"background-clip":{feature:"background-clip-text",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},hyphens:{feature:"css-hyphens",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5","safari 16.5"]},fill:{props:["width","min-width","max-width","height","min-height","max-height","inline-size","min-inline-size","max-inline-size","block-size","min-block-size","max-block-size","grid","grid-template","grid-template-rows","grid-template-columns","grid-auto-columns","grid-auto-rows"],feature:"intrinsic-width",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"fill-available":{props:["width","min-width","max-width","height","min-height","max-height","inline-size","min-inline-size","max-inline-size","block-size","min-block-size","max-block-size","grid","grid-template","grid-template-rows","grid-template-columns","grid-auto-columns","grid-auto-rows"],feature:"intrinsic-width",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},stretch:{props:["width","min-width","max-width","height","min-height","max-height","inline-size","min-inline-size","max-inline-size","block-size","min-block-size","max-block-size","grid","grid-template","grid-template-rows","grid-template-columns","grid-auto-columns","grid-auto-rows"],feature:"intrinsic-width",browsers:["firefox 114"]},"fit-content":{props:["width","min-width","max-width","height","min-height","max-height","inline-size","min-inline-size","max-inline-size","block-size","min-block-size","max-block-size","grid","grid-template","grid-template-rows","grid-template-columns","grid-auto-columns","grid-auto-rows"],feature:"intrinsic-width",browsers:["firefox 114"]},"text-decoration-style":{feature:"text-decoration",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5"]},"text-decoration-color":{feature:"text-decoration",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5"]},"text-decoration-line":{feature:"text-decoration",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5"]},"text-decoration":{feature:"text-decoration",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5"]},"text-decoration-skip":{feature:"text-decoration",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5"]},"text-decoration-skip-ink":{feature:"text-decoration",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5"]},"text-size-adjust":{feature:"text-size-adjust",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5"]},"mask-clip":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-composite":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-image":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-origin":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-repeat":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-border-repeat":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-border-source":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},mask:{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-position":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-size":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-border":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-border-outset":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-border-width":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-border-slice":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"clip-path":{feature:"css-clip-path",browsers:["samsung 21"]},"box-decoration-break":{feature:"css-boxdecorationbreak",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5","opera 99","safari 16.5","samsung 21"]},appearance:{feature:"css-appearance",browsers:["samsung 21"]},"image-set":{props:["background","background-image","border-image","cursor","mask","mask-image","list-style","list-style-image","content"],feature:"css-image-set",browsers:["and_uc 15.5","chrome 109","samsung 21"]},"cross-fade":{props:["background","background-image","border-image","mask","list-style","list-style-image","content","mask-image"],feature:"css-cross-fade",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},isolate:{props:["unicode-bidi"],feature:"css-unicode-bidi",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5","safari 16.5"]},"color-adjust":{feature:"css-color-adjust",browsers:["chrome 109","chrome 113","chrome 114","edge 114","opera 99"]}}});var lb=v((eq,ob)=>{l();ob.exports={}});var pb=v((tq,cb)=>{l();var SO=Ho(),{agents:CO}=(Gn(),Wn),nu=Sm(),AO=dt(),_O=nb(),OO=ab(),EO=lb(),ub={browsers:CO,prefixes:OO},fb=` +`); + w.push(` Use \`${r.replace("[", `[${_}:`)}\` for \`${E.trim()}\``); + break; + } + F.warn([ + `The class \`${r}\` is ambiguous and matches multiple utilities.`, + ...w, + `If this is content and not a class, replace it with \`${r.replace("[", "[").replace("]", "]")}\` to silence this warning.`, + ]); + continue; + } + } + o = o.map((p) => p.filter((m) => qd(m[1]))); + } + ((o = o.flat()), (o = Array.from(D2(o, i))), (o = k2(o, e)), a && (o = S2(o, i))); + for (let p of n) o = C2(p, o, e); + for (let p of o) + ((p[1].raws.tailwind = { ...p[1].raws.tailwind, candidate: r }), + (p = I2(p, { context: e, candidate: r })), + p !== null && (yield p)); + } + } + function I2(r, { context: e, candidate: t }) { + if (!r[0].collectedFormats) return r; + let i = !0, + n; + try { + n = Vt(r[0].collectedFormats, { context: e, candidate: t }); + } catch { + return null; + } + let a = j.root({ nodes: [r[1].clone()] }); + return ( + a.walkRules((s) => { + if (!An(s)) + try { + let o = kn(s.selector, n, { candidate: t, context: e }); + if (o === null) { + s.remove(); + return; + } + s.selector = o; + } catch { + return ((i = !1), !1); + } + }), + !i || a.nodes.length === 0 ? null : ((r[1] = a.nodes[0]), r) + ); + } + function An(r) { + return r.parent && r.parent.type === "atrule" && r.parent.name === "keyframes"; + } + function q2(r) { + if (r === !0) + return (e) => { + An(e) || + e.walkDecls((t) => { + t.parent.type === "rule" && !An(t.parent) && (t.important = !0); + }); + }; + if (typeof r == "string") + return (e) => { + An(e) || (e.selectors = e.selectors.map((t) => Sn(t, r))); + }; + } + function _n(r, e, t = !1) { + let i = [], + n = q2(e.tailwindConfig.important); + for (let a of r) { + if (e.notClassCache.has(a)) continue; + if (e.candidateRuleCache.has(a)) { + i = i.concat(Array.from(e.candidateRuleCache.get(a))); + continue; + } + let s = Array.from(fo(a, e)); + if (s.length === 0) { + e.notClassCache.add(a); + continue; + } + e.classCache.set(a, s); + let o = e.candidateRuleCache.get(a) ?? new Set(); + e.candidateRuleCache.set(a, o); + for (let u of s) { + let [{ sort: c, options: f }, d] = u; + if (f.respectImportant && n) { + let m = j.root({ nodes: [d.clone()] }); + (m.walkRules(n), (d = m.nodes[0])); + } + let p = [c, t ? d.clone() : d]; + (o.add(p), e.ruleCache.add(p), i.push(p)); + } + } + return i; + } + function co(r) { + return r.startsWith("[") && r.endsWith("]"); + } + var Cn, + v2, + A2, + On = C(() => { + l(); + st(); + Cn = X(Me()); + Qa(); + At(); + dn(); + hr(); + Oe(); + lt(); + so(); + Xa(); + dr(); + ei(); + eo(); + _t(); + je(); + oo(); + v2 = (0, Cn.default)((r) => r.first.filter(({ type: e }) => e === "class").pop().value); + A2 = /^[a-z_-]/; + }); + var Md, + Bd = C(() => { + l(); + Md = {}; + }); + function R2(r) { + try { + return Md.createHash("md5").update(r, "utf-8").digest("binary"); + } catch (e) { + return ""; + } + } + function Fd(r, e) { + let t = e.toString(); + if (!t.includes("@tailwind")) return !1; + let i = Za.get(r), + n = R2(t), + a = i !== n; + return (Za.set(r, n), a); + } + var Ld = C(() => { + l(); + Bd(); + lt(); + }); + function Tn(r) { + return (r > 0n) - (r < 0n); + } + var Nd = C(() => { + l(); + }); + function $d(r, e) { + let t = 0n, + i = 0n; + for (let [n, a] of e) r & n && ((t = t | n), (i = i | a)); + return (r & ~t) | i; + } + var zd = C(() => { + l(); + }); + function jd(r) { + let e = null; + for (let t of r) ((e = e ?? t), (e = e > t ? e : t)); + return e; + } + function M2(r, e) { + let t = r.length, + i = e.length, + n = t < i ? t : i; + for (let a = 0; a < n; a++) { + let s = r.charCodeAt(a) - e.charCodeAt(a); + if (s !== 0) return s; + } + return t - i; + } + var po, + Vd = C(() => { + l(); + Nd(); + zd(); + po = class { + constructor() { + ((this.offsets = { defaults: 0n, base: 0n, components: 0n, utilities: 0n, variants: 0n, user: 0n }), + (this.layerPositions = { + defaults: 0n, + base: 1n, + components: 2n, + utilities: 3n, + user: 4n, + variants: 5n, + }), + (this.reservedVariantBits = 0n), + (this.variantOffsets = new Map())); + } + create(e) { + return { + layer: e, + parentLayer: e, + arbitrary: 0n, + variants: 0n, + parallelIndex: 0n, + index: this.offsets[e]++, + propertyOffset: 0n, + property: "", + options: [], + }; + } + arbitraryProperty(e) { + return { ...this.create("utilities"), arbitrary: 1n, property: e }; + } + forVariant(e, t = 0) { + let i = this.variantOffsets.get(e); + if (i === void 0) throw new Error(`Cannot find offset for unknown variant ${e}`); + return { ...this.create("variants"), variants: i << BigInt(t) }; + } + applyVariantOffset(e, t, i) { + return ( + (i.variant = t.variants), + { + ...e, + layer: "variants", + parentLayer: e.layer === "variants" ? e.parentLayer : e.layer, + variants: e.variants | t.variants, + options: i.sort ? [].concat(i, e.options) : e.options, + parallelIndex: jd([e.parallelIndex, t.parallelIndex]), + } + ); + } + applyParallelOffset(e, t) { + return { ...e, parallelIndex: BigInt(t) }; + } + recordVariants(e, t) { + for (let i of e) this.recordVariant(i, t(i)); + } + recordVariant(e, t = 1) { + return ( + this.variantOffsets.set(e, 1n << this.reservedVariantBits), + (this.reservedVariantBits += BigInt(t)), + { ...this.create("variants"), variants: this.variantOffsets.get(e) } + ); + } + compare(e, t) { + if (e.layer !== t.layer) return this.layerPositions[e.layer] - this.layerPositions[t.layer]; + if (e.parentLayer !== t.parentLayer) + return this.layerPositions[e.parentLayer] - this.layerPositions[t.parentLayer]; + for (let i of e.options) + for (let n of t.options) { + if (i.id !== n.id || !i.sort || !n.sort) continue; + let a = jd([i.variant, n.variant]) ?? 0n, + s = ~(a | (a - 1n)), + o = e.variants & s, + u = t.variants & s; + if (o !== u) continue; + let c = i.sort( + { value: i.value, modifier: i.modifier }, + { value: n.value, modifier: n.modifier } + ); + if (c !== 0) return c; + } + return e.variants !== t.variants + ? e.variants - t.variants + : e.parallelIndex !== t.parallelIndex + ? e.parallelIndex - t.parallelIndex + : e.arbitrary !== t.arbitrary + ? e.arbitrary - t.arbitrary + : e.propertyOffset !== t.propertyOffset + ? e.propertyOffset - t.propertyOffset + : e.index - t.index; + } + recalculateVariantOffsets() { + let e = Array.from(this.variantOffsets.entries()) + .filter(([n]) => n.startsWith("[")) + .sort(([n], [a]) => M2(n, a)), + t = e.map(([, n]) => n).sort((n, a) => Tn(n - a)); + return e.map(([, n], a) => [n, t[a]]).filter(([n, a]) => n !== a); + } + remapArbitraryVariantOffsets(e) { + let t = this.recalculateVariantOffsets(); + return t.length === 0 + ? e + : e.map((i) => { + let [n, a] = i; + return ((n = { ...n, variants: $d(n.variants, t) }), [n, a]); + }); + } + sortArbitraryProperties(e) { + let t = new Set(); + for (let [s] of e) s.arbitrary === 1n && t.add(s.property); + if (t.size === 0) return e; + let i = Array.from(t).sort(), + n = new Map(), + a = 1n; + for (let s of i) n.set(s, a++); + return e.map((s) => { + let [o, u] = s; + return ((o = { ...o, propertyOffset: n.get(o.property) ?? 0n }), [o, u]); + }); + } + sort(e) { + return ( + (e = this.remapArbitraryVariantOffsets(e)), + (e = this.sortArbitraryProperties(e)), + e.sort(([t], [i]) => Tn(this.compare(t, i))) + ); + } + }; + }); + function yo(r, e) { + let t = r.tailwindConfig.prefix; + return typeof t == "function" ? t(e) : t + e; + } + function Wd({ type: r = "any", ...e }) { + let t = [].concat(r); + return { + ...e, + types: t.map((i) => (Array.isArray(i) ? { type: i[0], ...i[1] } : { type: i, preferOnConflict: !1 })), + }; + } + function B2(r) { + let e = [], + t = "", + i = 0; + for (let n = 0; n < r.length; n++) { + let a = r[n]; + if (a === "\\") t += "\\" + r[++n]; + else if (a === "{") (++i, e.push(t.trim()), (t = "")); + else if (a === "}") { + if (--i < 0) throw new Error("Your { and } are unbalanced."); + (e.push(t.trim()), (t = "")); + } else t += a; + } + return (t.length > 0 && e.push(t.trim()), (e = e.filter((n) => n !== "")), e); + } + function F2(r, e, { before: t = [] } = {}) { + if (((t = [].concat(t)), t.length <= 0)) { + r.push(e); + return; + } + let i = r.length - 1; + for (let n of t) { + let a = r.indexOf(n); + a !== -1 && (i = Math.min(i, a)); + } + r.splice(i, 0, e); + } + function Gd(r) { + return Array.isArray(r) ? r.flatMap((e) => (!Array.isArray(e) && !ie(e) ? e : Lt(e))) : Gd([r]); + } + function L2(r, e) { + return (0, ho.default)((i) => { + let n = []; + return ( + e && e(i), + i.walkClasses((a) => { + n.push(a.value); + }), + n + ); + }).transformSync(r); + } + function N2(r) { + r.walkPseudos((e) => { + e.value === ":not" && e.remove(); + }); + } + function $2(r, e = { containsNonOnDemandable: !1 }, t = 0) { + let i = [], + n = []; + r.type === "rule" ? n.push(...r.selectors) : r.type === "atrule" && r.walkRules((a) => n.push(...a.selectors)); + for (let a of n) { + let s = L2(a, N2); + s.length === 0 && (e.containsNonOnDemandable = !0); + for (let o of s) i.push(o); + } + return t === 0 ? [e.containsNonOnDemandable || i.length === 0, i] : i; + } + function Pn(r) { + return Gd(r).flatMap((e) => { + let t = new Map(), + [i, n] = $2(e); + return (i && n.unshift(He), n.map((a) => (t.has(e) || t.set(e, e), [a, t.get(e)]))); + }); + } + function En(r) { + return r.startsWith("@") || r.includes("&"); + } + function ri(r) { + r = r + .replace(/\n+/g, "") + .replace(/\s{1,}/g, " ") + .trim(); + let e = B2(r) + .map((t) => { + if (!t.startsWith("@")) return ({ format: a }) => a(t); + let [, i, n] = /@(\S*)( .+|[({].*)?/g.exec(t); + return ({ wrap: a }) => a(j.atRule({ name: i, params: n?.trim() ?? "" })); + }) + .reverse(); + return (t) => { + for (let i of e) i(t); + }; + } + function z2(r, e, { variantList: t, variantMap: i, offsets: n, classList: a }) { + function s(p, m) { + return p ? (0, Ud.default)(r, p, m) : r; + } + function o(p) { + return Nt(r.prefix, p); + } + function u(p, m) { + return p === He ? He : m.respectPrefix ? e.tailwindConfig.prefix + p : p; + } + function c(p, m, b = {}) { + let x = Ze(p), + y = s(["theme", ...x], m); + return Ge(x[0])(y, b); + } + let f = 0, + d = { + postcss: j, + prefix: o, + e: ce, + config: s, + theme: c, + corePlugins: (p) => + Array.isArray(r.corePlugins) ? r.corePlugins.includes(p) : s(["corePlugins", p], !0), + variants: () => [], + addBase(p) { + for (let [m, b] of Pn(p)) { + let x = u(m, {}), + y = n.create("base"); + (e.candidateRuleMap.has(x) || e.candidateRuleMap.set(x, []), + e.candidateRuleMap.get(x).push([{ sort: y, layer: "base" }, b])); + } + }, + addDefaults(p, m) { + let b = { [`@defaults ${p}`]: m }; + for (let [x, y] of Pn(b)) { + let w = u(x, {}); + (e.candidateRuleMap.has(w) || e.candidateRuleMap.set(w, []), + e.candidateRuleMap.get(w).push([{ sort: n.create("defaults"), layer: "defaults" }, y])); + } + }, + addComponents(p, m) { + m = Object.assign( + {}, + { preserveSource: !1, respectPrefix: !0, respectImportant: !1 }, + Array.isArray(m) ? {} : m + ); + for (let [x, y] of Pn(p)) { + let w = u(x, m); + (a.add(w), + e.candidateRuleMap.has(w) || e.candidateRuleMap.set(w, []), + e.candidateRuleMap + .get(w) + .push([{ sort: n.create("components"), layer: "components", options: m }, y])); + } + }, + addUtilities(p, m) { + m = Object.assign( + {}, + { preserveSource: !1, respectPrefix: !0, respectImportant: !0 }, + Array.isArray(m) ? {} : m + ); + for (let [x, y] of Pn(p)) { + let w = u(x, m); + (a.add(w), + e.candidateRuleMap.has(w) || e.candidateRuleMap.set(w, []), + e.candidateRuleMap + .get(w) + .push([{ sort: n.create("utilities"), layer: "utilities", options: m }, y])); + } + }, + matchUtilities: function (p, m) { + m = Wd({ ...{ respectPrefix: !0, respectImportant: !0, modifiers: !1 }, ...m }); + let x = n.create("utilities"); + for (let y in p) { + let S = function (E, { isOnlyPlugin: I }) { + let [q, R, J] = gs(m.types, E, m, r); + if (q === void 0) return []; + if (!m.types.some(({ type: ee }) => ee === R)) + if (I) + F.warn([ + `Unnecessary typehint \`${R}\` in \`${y}-${E}\`.`, + `You can safely update it to \`${y}-${E.replace(R + ":", "")}\`.`, + ]); + else return []; + if (!zt(q)) return []; + let ue = { + get modifier() { + return ( + m.modifiers || + F.warn(`modifier-used-without-options-for-${y}`, [ + "Your plugin must set `modifiers: true` in its options to support modifiers.", + ]), + J + ); + }, + }, + de = K(r, "generalizedModifiers"); + return [] + .concat(de ? k(q, ue) : k(q)) + .filter(Boolean) + .map((ee) => ({ [hn(y, E)]: ee })); + }, + w = u(y, m), + k = p[y]; + a.add([w, m]); + let _ = [{ sort: x, layer: "utilities", options: m }, S]; + (e.candidateRuleMap.has(w) || e.candidateRuleMap.set(w, []), e.candidateRuleMap.get(w).push(_)); + } + }, + matchComponents: function (p, m) { + m = Wd({ ...{ respectPrefix: !0, respectImportant: !1, modifiers: !1 }, ...m }); + let x = n.create("components"); + for (let y in p) { + let S = function (E, { isOnlyPlugin: I }) { + let [q, R, J] = gs(m.types, E, m, r); + if (q === void 0) return []; + if (!m.types.some(({ type: ee }) => ee === R)) + if (I) + F.warn([ + `Unnecessary typehint \`${R}\` in \`${y}-${E}\`.`, + `You can safely update it to \`${y}-${E.replace(R + ":", "")}\`.`, + ]); + else return []; + if (!zt(q)) return []; + let ue = { + get modifier() { + return ( + m.modifiers || + F.warn(`modifier-used-without-options-for-${y}`, [ + "Your plugin must set `modifiers: true` in its options to support modifiers.", + ]), + J + ); + }, + }, + de = K(r, "generalizedModifiers"); + return [] + .concat(de ? k(q, ue) : k(q)) + .filter(Boolean) + .map((ee) => ({ [hn(y, E)]: ee })); + }, + w = u(y, m), + k = p[y]; + a.add([w, m]); + let _ = [{ sort: x, layer: "components", options: m }, S]; + (e.candidateRuleMap.has(w) || e.candidateRuleMap.set(w, []), e.candidateRuleMap.get(w).push(_)); + } + }, + addVariant(p, m, b = {}) { + ((m = [].concat(m).map((x) => { + if (typeof x != "string") + return (y = {}) => { + let { args: w, modifySelectors: k, container: S, separator: _, wrap: E, format: I } = y, + q = x( + Object.assign( + { modifySelectors: k, container: S, separator: _ }, + b.type === mo.MatchVariant && { args: w, wrap: E, format: I } + ) + ); + if (typeof q == "string" && !En(q)) + throw new Error( + `Your custom variant \`${p}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.` + ); + return Array.isArray(q) + ? q.filter((R) => typeof R == "string").map((R) => ri(R)) + : q && typeof q == "string" && ri(q)(y); + }; + if (!En(x)) + throw new Error( + `Your custom variant \`${p}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.` + ); + return ri(x); + })), + F2(t, p, b), + i.set(p, m), + e.variantOptions.set(p, b)); + }, + matchVariant(p, m, b) { + let x = b?.id ?? ++f, + y = p === "@", + w = K(r, "generalizedModifiers"); + for (let [S, _] of Object.entries(b?.values ?? {})) + S !== "DEFAULT" && + d.addVariant( + y ? `${p}${S}` : `${p}-${S}`, + ({ args: E, container: I }) => + m(_, w ? { modifier: E?.modifier, container: I } : { container: I }), + { ...b, value: _, id: x, type: mo.MatchVariant, variantInfo: go.Base } + ); + let k = "DEFAULT" in (b?.values ?? {}); + d.addVariant( + p, + ({ args: S, container: _ }) => + S?.value === ti && !k + ? null + : m( + S?.value === ti + ? b.values.DEFAULT + : (S?.value ?? (typeof S == "string" ? S : "")), + w ? { modifier: S?.modifier, container: _ } : { container: _ } + ), + { ...b, id: x, type: mo.MatchVariant, variantInfo: go.Dynamic } + ); + }, + }; + return d; + } + function Dn(r) { + return (wo.has(r) || wo.set(r, new Map()), wo.get(r)); + } + function Hd(r, e) { + let t = !1, + i = new Map(); + for (let n of r) { + if (!n) continue; + let a = Ss.parse(n), + s = a.hash ? a.href.replace(a.hash, "") : a.href; + s = a.search ? s.replace(a.search, "") : s; + let o = te.statSync(decodeURIComponent(s), { throwIfNoEntry: !1 })?.mtimeMs; + !o || ((!e.has(n) || o > e.get(n)) && (t = !0), i.set(n, o)); + } + return [t, i]; + } + function Yd(r) { + r.walkAtRules((e) => { + ["responsive", "variants"].includes(e.name) && (Yd(e), e.before(e.nodes), e.remove()); + }); + } + function j2(r) { + let e = []; + return ( + r.each((t) => { + t.type === "atrule" && + ["responsive", "variants"].includes(t.name) && + ((t.name = "layer"), (t.params = "utilities")); + }), + r.walkAtRules("layer", (t) => { + if ((Yd(t), t.params === "base")) { + for (let i of t.nodes) + e.push(function ({ addBase: n }) { + n(i, { respectPrefix: !1 }); + }); + t.remove(); + } else if (t.params === "components") { + for (let i of t.nodes) + e.push(function ({ addComponents: n }) { + n(i, { respectPrefix: !1, preserveSource: !0 }); + }); + t.remove(); + } else if (t.params === "utilities") { + for (let i of t.nodes) + e.push(function ({ addUtilities: n }) { + n(i, { respectPrefix: !1, preserveSource: !0 }); + }); + t.remove(); + } + }), + e + ); + } + function V2(r, e) { + let t = Object.entries({ ...H, ...Sd }) + .map(([u, c]) => (r.tailwindConfig.corePlugins.includes(u) ? c : null)) + .filter(Boolean), + i = r.tailwindConfig.plugins.map( + (u) => (u.__isOptionsFunction && (u = u()), typeof u == "function" ? u : u.handler) + ), + n = j2(e), + a = [ + H.childVariant, + H.pseudoElementVariants, + H.pseudoClassVariants, + H.hasVariants, + H.ariaVariants, + H.dataVariants, + ], + s = [ + H.supportsVariants, + H.reducedMotionVariants, + H.prefersContrastVariants, + H.screenVariants, + H.orientationVariants, + H.directionVariants, + H.darkVariants, + H.forcedColorsVariants, + H.printVariant, + ]; + return ( + (r.tailwindConfig.darkMode === "class" || + (Array.isArray(r.tailwindConfig.darkMode) && r.tailwindConfig.darkMode[0] === "class")) && + (s = [ + H.supportsVariants, + H.reducedMotionVariants, + H.prefersContrastVariants, + H.darkVariants, + H.screenVariants, + H.orientationVariants, + H.directionVariants, + H.forcedColorsVariants, + H.printVariant, + ]), + [...t, ...a, ...i, ...s, ...n] + ); + } + function U2(r, e) { + let t = [], + i = new Map(); + e.variantMap = i; + let n = new po(); + e.offsets = n; + let a = new Set(), + s = z2(e.tailwindConfig, e, { variantList: t, variantMap: i, offsets: n, classList: a }); + for (let f of r) + if (Array.isArray(f)) for (let d of f) d(s); + else f?.(s); + n.recordVariants(t, (f) => i.get(f).length); + for (let [f, d] of i.entries()) + e.variantMap.set( + f, + d.map((p, m) => [n.forVariant(f, m), p]) + ); + let o = (e.tailwindConfig.safelist ?? []).filter(Boolean); + if (o.length > 0) { + let f = []; + for (let d of o) { + if (typeof d == "string") { + e.changedContent.push({ content: d, extension: "html" }); + continue; + } + if (d instanceof RegExp) { + F.warn("root-regex", [ + "Regular expressions in `safelist` work differently in Tailwind CSS v3.0.", + "Update your `safelist` configuration to eliminate this warning.", + "https://tailwindcss.com/docs/content-configuration#safelisting-classes", + ]); + continue; + } + f.push(d); + } + if (f.length > 0) { + let d = new Map(), + p = e.tailwindConfig.prefix.length, + m = f.some((b) => b.pattern.source.includes("!")); + for (let b of a) { + let x = Array.isArray(b) + ? (() => { + let [y, w] = b, + S = Object.keys(w?.values ?? {}).map((_) => Kr(y, _)); + return ( + w?.supportsNegativeValues && + ((S = [...S, ...S.map((_) => "-" + _)]), + (S = [...S, ...S.map((_) => _.slice(0, p) + "-" + _.slice(p))])), + w.types.some(({ type: _ }) => _ === "color") && + (S = [ + ...S, + ...S.flatMap((_) => + Object.keys(e.tailwindConfig.theme.opacity).map((E) => `${_}/${E}`) + ), + ]), + m && w?.respectImportant && (S = [...S, ...S.map((_) => "!" + _)]), + S + ); + })() + : [b]; + for (let y of x) + for (let { pattern: w, variants: k = [] } of f) + if (((w.lastIndex = 0), d.has(w) || d.set(w, 0), !!w.test(y))) { + (d.set(w, d.get(w) + 1), e.changedContent.push({ content: y, extension: "html" })); + for (let S of k) + e.changedContent.push({ + content: S + e.tailwindConfig.separator + y, + extension: "html", + }); + } + } + for (let [b, x] of d.entries()) + x === 0 && + F.warn([ + `The safelist pattern \`${b}\` doesn't match any Tailwind CSS classes.`, + "Fix this pattern or remove it from your `safelist` configuration.", + "https://tailwindcss.com/docs/content-configuration#safelisting-classes", + ]); + } + } + let u = [].concat(e.tailwindConfig.darkMode ?? "media")[1] ?? "dark", + c = [yo(e, u), yo(e, "group"), yo(e, "peer")]; + ((e.getClassOrder = function (d) { + let p = [...d].sort((y, w) => (y === w ? 0 : y < w ? -1 : 1)), + m = new Map(p.map((y) => [y, null])), + b = _n(new Set(p), e, !0); + b = e.offsets.sort(b); + let x = BigInt(c.length); + for (let [, y] of b) { + let w = y.raws.tailwind.candidate; + m.set(w, m.get(w) ?? x++); + } + return d.map((y) => { + let w = m.get(y) ?? null, + k = c.indexOf(y); + return (w === null && k !== -1 && (w = BigInt(k)), [y, w]); + }); + }), + (e.getClassList = function (d = {}) { + let p = []; + for (let m of a) + if (Array.isArray(m)) { + let [b, x] = m, + y = [], + w = Object.keys(x?.modifiers ?? {}); + x?.types?.some(({ type: _ }) => _ === "color") && + w.push(...Object.keys(e.tailwindConfig.theme.opacity ?? {})); + let k = { modifiers: w }, + S = d.includeMetadata && w.length > 0; + for (let [_, E] of Object.entries(x?.values ?? {})) { + if (E == null) continue; + let I = Kr(b, _); + if ((p.push(S ? [I, k] : I), x?.supportsNegativeValues && Ke(E))) { + let q = Kr(b, `-${_}`); + y.push(S ? [q, k] : q); + } + } + p.push(...y); + } else p.push(m); + return p; + }), + (e.getVariants = function () { + let d = Math.random().toString(36).substring(7).toUpperCase(), + p = []; + for (let [m, b] of e.variantOptions.entries()) + b.variantInfo !== go.Base && + p.push({ + name: m, + isArbitrary: b.type === Symbol.for("MATCH_VARIANT"), + values: Object.keys(b.values ?? {}), + hasDash: m !== "@", + selectors({ modifier: x, value: y } = {}) { + let w = `TAILWINDPLACEHOLDER${d}`, + k = j.rule({ selector: `.${w}` }), + S = j.root({ nodes: [k.clone()] }), + _ = S.toString(), + E = (e.variantMap.get(m) ?? []).flatMap(([oe, he]) => he), + I = []; + for (let oe of E) { + let he = [], + ui = { + args: { modifier: x, value: b.values?.[y] ?? y }, + separator: e.tailwindConfig.separator, + modifySelectors(Ce) { + return ( + S.each((ts) => { + ts.type === "rule" && + (ts.selectors = ts.selectors.map((mu) => + Ce({ + get className() { + return lo(mu); + }, + selector: mu, + }) + )); + }), + S + ); + }, + format(Ce) { + he.push(Ce); + }, + wrap(Ce) { + he.push(`@${Ce.name} ${Ce.params} { & }`); + }, + container: S, + }, + fi = oe(ui); + if ((he.length > 0 && I.push(he), Array.isArray(fi))) + for (let Ce of fi) ((he = []), Ce(ui), I.push(he)); + } + let q = [], + R = S.toString(); + _ !== R && + (S.walkRules((oe) => { + let he = oe.selector, + ui = (0, ho.default)((fi) => { + fi.walkClasses((Ce) => { + Ce.value = `${m}${e.tailwindConfig.separator}${Ce.value}`; + }); + }).processSync(he); + q.push(he.replace(ui, "&").replace(w, "&")); + }), + S.walkAtRules((oe) => { + q.push(`@${oe.name} (${oe.params}) { & }`); + })); + let J = !(y in (b.values ?? {})), + ue = b[Zr] ?? {}, + de = (() => !(J || ue.respectPrefix === !1))(); + ((I = I.map((oe) => oe.map((he) => ({ format: he, respectPrefix: de })))), + (q = q.map((oe) => ({ format: oe, respectPrefix: de })))); + let De = { candidate: w, context: e }, + ee = I.map((oe) => + kn(`.${w}`, Vt(oe, De), De).replace(`.${w}`, "&").replace("{ & }", "").trim() + ); + return (q.length > 0 && ee.push(Vt(q, De).toString().replace(`.${w}`, "&")), ee); + }, + }); + return p; + })); + } + function Qd(r, e) { + !r.classCache.has(e) || + (r.notClassCache.add(e), + r.classCache.delete(e), + r.applyClassCache.delete(e), + r.candidateRuleMap.delete(e), + r.candidateRuleCache.delete(e), + (r.stylesheetCache = null)); + } + function W2(r, e) { + let t = e.raws.tailwind.candidate; + if (!!t) { + for (let i of r.ruleCache) i[1].raws.tailwind.candidate === t && r.ruleCache.delete(i); + Qd(r, t); + } + } + function bo(r, e = [], t = j.root()) { + let i = { + disposables: [], + ruleCache: new Set(), + candidateRuleCache: new Map(), + classCache: new Map(), + applyClassCache: new Map(), + notClassCache: new Set(r.blocklist ?? []), + postCssNodeCache: new Map(), + candidateRuleMap: new Map(), + tailwindConfig: r, + changedContent: e, + variantMap: new Map(), + stylesheetCache: null, + variantOptions: new Map(), + markInvalidUtilityCandidate: (a) => Qd(i, a), + markInvalidUtilityNode: (a) => W2(i, a), + }, + n = V2(i, t); + return (U2(n, i), i); + } + function Jd(r, e, t, i, n, a) { + let s = e.opts.from, + o = i !== null; + Pe.DEBUG && console.log("Source path:", s); + let u; + if (o && Ut.has(s)) u = Ut.get(s); + else if (ii.has(n)) { + let p = ii.get(n); + (ut.get(p).add(s), Ut.set(s, p), (u = p)); + } + let c = Fd(s, r); + if (u) { + let [p, m] = Hd([...a], Dn(u)); + if (!p && !c) return [u, !1, m]; + } + if (Ut.has(s)) { + let p = Ut.get(s); + if (ut.has(p) && (ut.get(p).delete(s), ut.get(p).size === 0)) { + ut.delete(p); + for (let [m, b] of ii) b === p && ii.delete(m); + for (let m of p.disposables.splice(0)) m(p); + } + } + Pe.DEBUG && console.log("Setting up new context..."); + let f = bo(t, [], r); + Object.assign(f, { userConfigPath: i }); + let [, d] = Hd([...a], Dn(f)); + return (ii.set(n, f), Ut.set(s, f), ut.has(f) || ut.set(f, new Set()), ut.get(f).add(s), [f, !0, d]); + } + var Ud, + ho, + Zr, + mo, + go, + wo, + Ut, + ii, + ut, + ei = C(() => { + l(); + ze(); + Cs(); + st(); + ((Ud = X(Gs())), (ho = X(Me()))); + Jr(); + Qa(); + dn(); + At(); + $t(); + Xa(); + hr(); + Cd(); + lt(); + lt(); + gi(); + Oe(); + di(); + eo(); + On(); + Ld(); + Vd(); + je(); + so(); + ((Zr = Symbol()), + (mo = { AddVariant: Symbol.for("ADD_VARIANT"), MatchVariant: Symbol.for("MATCH_VARIANT") }), + (go = { Base: 1 << 0, Dynamic: 1 << 1 })); + wo = new WeakMap(); + ((Ut = Ad), (ii = _d), (ut = vn)); + }); + function vo(r) { + return r.ignore + ? [] + : r.glob + ? h.env.ROLLUP_WATCH === "true" + ? [{ type: "dependency", file: r.base }] + : [{ type: "dir-dependency", dir: r.base, glob: r.glob }] + : [{ type: "dependency", file: r.base }]; + } + var Xd = C(() => { + l(); + }); + function Kd(r, e) { + return { handler: r, config: e }; + } + var Zd, + eh = C(() => { + l(); + Kd.withOptions = function (r, e = () => ({})) { + let t = function (i) { + return { __options: i, handler: r(i), config: e(i) }; + }; + return ((t.__isOptionsFunction = !0), (t.__pluginFunction = r), (t.__configFunction = e), t); + }; + Zd = Kd; + }); + var In = {}; + Ae(In, { default: () => G2 }); + var G2, + qn = C(() => { + l(); + eh(); + G2 = Zd; + }); + var rh = v((M6, th) => { + l(); + var H2 = (qn(), In).default, + Y2 = { overflow: "hidden", display: "-webkit-box", "-webkit-box-orient": "vertical" }, + Q2 = H2( + function ({ matchUtilities: r, addUtilities: e, theme: t, variants: i }) { + let n = t("lineClamp"); + (r({ "line-clamp": (a) => ({ ...Y2, "-webkit-line-clamp": `${a}` }) }, { values: n }), + e([{ ".line-clamp-none": { "-webkit-line-clamp": "unset" } }], i("lineClamp"))); + }, + { + theme: { lineClamp: { 1: "1", 2: "2", 3: "3", 4: "4", 5: "5", 6: "6" } }, + variants: { lineClamp: ["responsive"] }, + } + ); + th.exports = Q2; + }); + function xo(r) { + r.content.files.length === 0 && + F.warn("content-problems", [ + "The `content` option in your Tailwind CSS configuration is missing or empty.", + "Configure your content sources or your generated CSS will be missing styles.", + "https://tailwindcss.com/docs/content-configuration", + ]); + try { + let e = rh(); + r.plugins.includes(e) && + (F.warn("line-clamp-in-core", [ + "As of Tailwind CSS v3.3, the `@tailwindcss/line-clamp` plugin is now included by default.", + "Remove it from the `plugins` array in your configuration to eliminate this warning.", + ]), + (r.plugins = r.plugins.filter((t) => t !== e))); + } catch {} + return r; + } + var ih = C(() => { + l(); + Oe(); + }); + var nh, + sh = C(() => { + l(); + nh = () => !1; + }); + var Rn, + ah = C(() => { + l(); + Rn = { + sync: (r) => [].concat(r), + generateTasks: (r) => [ + { dynamic: !1, base: ".", negative: [], positive: [].concat(r), patterns: [].concat(r) }, + ], + escapePath: (r) => r, + }; + }); + var ko, + oh = C(() => { + l(); + ko = (r) => r; + }); + var lh, + uh = C(() => { + l(); + lh = () => ""; + }); + function fh(r) { + let e = r, + t = lh(r); + return ( + t !== "." && ((e = r.substr(t.length)), e.charAt(0) === "/" && (e = e.substr(1))), + e.substr(0, 2) === "./" && (e = e.substr(2)), + e.charAt(0) === "/" && (e = e.substr(1)), + { base: t, glob: e } + ); + } + var ch = C(() => { + l(); + uh(); + }); + function ph(r, e) { + let t = e.content.files; + ((t = t.filter((o) => typeof o == "string")), (t = t.map(ko))); + let i = Rn.generateTasks(t), + n = [], + a = []; + for (let o of i) (n.push(...o.positive.map((u) => dh(u, !1))), a.push(...o.negative.map((u) => dh(u, !0)))); + let s = [...n, ...a]; + return ((s = X2(r, s)), (s = s.flatMap(K2)), (s = s.map(J2)), s); + } + function dh(r, e) { + let t = { original: r, base: r, ignore: e, pattern: r, glob: null }; + return (nh(r) && Object.assign(t, fh(r)), t); + } + function J2(r) { + let e = ko(r.base); + return ( + (e = Rn.escapePath(e)), + (r.pattern = r.glob ? `${e}/${r.glob}` : e), + (r.pattern = r.ignore ? `!${r.pattern}` : r.pattern), + r + ); + } + function X2(r, e) { + let t = []; + return ( + r.userConfigPath && r.tailwindConfig.content.relative && (t = [Z.dirname(r.userConfigPath)]), + e.map((i) => ((i.base = Z.resolve(...t, i.base)), i)) + ); + } + function K2(r) { + let e = [r]; + try { + let t = te.realpathSync(r.base); + t !== r.base && e.push({ ...r, base: t }); + } catch {} + return e; + } + function hh(r, e, t) { + let i = r.tailwindConfig.content.files + .filter((s) => typeof s.raw == "string") + .map(({ raw: s, extension: o = "html" }) => ({ content: s, extension: o })), + [n, a] = Z2(e, t); + for (let s of n) { + let o = Z.extname(s).slice(1); + i.push({ file: s, extension: o }); + } + return [i, a]; + } + function Z2(r, e) { + let t = r.map((s) => s.pattern), + i = new Map(), + n = new Set(); + Pe.DEBUG && console.time("Finding changed files"); + let a = Rn.sync(t, { absolute: !0 }); + for (let s of a) { + let o = e.get(s) || -1 / 0, + u = te.statSync(s).mtimeMs; + u > o && (n.add(s), i.set(s, u)); + } + return (Pe.DEBUG && console.timeEnd("Finding changed files"), [n, i]); + } + var mh = C(() => { + l(); + ze(); + bt(); + sh(); + ah(); + oh(); + ch(); + lt(); + }); + function gh() {} + var yh = C(() => { + l(); + }); + function iC(r, e) { + for (let t of e) { + let i = `${r}${t}`; + if (te.existsSync(i) && te.statSync(i).isFile()) return i; + } + for (let t of e) { + let i = `${r}/index${t}`; + if (te.existsSync(i)) return i; + } + return null; + } + function* wh(r, e, t, i = Z.extname(r)) { + let n = iC(Z.resolve(e, r), eC.includes(i) ? tC : rC); + if (n === null || t.has(n)) return; + (t.add(n), yield n, (e = Z.dirname(n)), (i = Z.extname(n))); + let a = te.readFileSync(n, "utf-8"); + for (let s of [ + ...a.matchAll(/import[\s\S]*?['"](.{3,}?)['"]/gi), + ...a.matchAll(/import[\s\S]*from[\s\S]*?['"](.{3,}?)['"]/gi), + ...a.matchAll(/require\(['"`](.+)['"`]\)/gi), + ]) + !s[1].startsWith(".") || (yield* wh(s[1], e, t, i)); + } + function So(r) { + return r === null ? new Set() : new Set(wh(r, Z.dirname(r), new Set())); + } + var eC, + tC, + rC, + bh = C(() => { + l(); + ze(); + bt(); + ((eC = [".js", ".cjs", ".mjs"]), + (tC = ["", ".js", ".cjs", ".mjs", ".ts", ".cts", ".mts", ".jsx", ".tsx"]), + (rC = ["", ".ts", ".cts", ".mts", ".tsx", ".js", ".cjs", ".mjs", ".jsx"])); + }); + function nC(r, e) { + if (Co.has(r)) return Co.get(r); + let t = ph(r, e); + return Co.set(r, t).get(r); + } + function sC(r) { + let e = ks(r); + if (e !== null) { + let [i, n, a, s] = xh.get(e) || [], + o = So(e), + u = !1, + c = new Map(); + for (let p of o) { + let m = te.statSync(p).mtimeMs; + (c.set(p, m), (!s || !s.has(p) || m > s.get(p)) && (u = !0)); + } + if (!u) return [i, e, n, a]; + for (let p of o) delete yu.cache[p]; + let f = xo(gr(gh(e))), + d = pi(f); + return (xh.set(e, [f, d, o, c]), [f, e, d, o]); + } + let t = gr(r?.config ?? r ?? {}); + return ((t = xo(t)), [t, null, pi(t), []]); + } + function Ao(r) { + return ({ tailwindDirectives: e, registerDependency: t }) => + (i, n) => { + let [a, s, o, u] = sC(r), + c = new Set(u); + if (e.size > 0) { + c.add(n.opts.from); + for (let b of n.messages) b.type === "dependency" && c.add(b.file); + } + let [f, , d] = Jd(i, n, a, s, o, c), + p = Dn(f), + m = nC(f, a); + if (e.size > 0) { + for (let y of m) for (let w of vo(y)) t(w); + let [b, x] = hh(f, m, p); + for (let y of b) f.changedContent.push(y); + for (let [y, w] of x.entries()) d.set(y, w); + } + for (let b of u) t({ type: "dependency", file: b }); + for (let [b, x] of d.entries()) p.set(b, x); + return f; + }; + } + var vh, + xh, + Co, + kh = C(() => { + l(); + ze(); + vh = X(rs()); + ku(); + xs(); + cf(); + ei(); + Xd(); + ih(); + mh(); + yh(); + bh(); + ((xh = new vh.default({ maxSize: 100 })), (Co = new WeakMap())); + }); + function _o(r) { + let e = new Set(), + t = new Set(), + i = new Set(); + if ( + (r.walkAtRules((n) => { + (n.name === "apply" && i.add(n), + n.name === "import" && + (n.params === '"tailwindcss/base"' || n.params === "'tailwindcss/base'" + ? ((n.name = "tailwind"), (n.params = "base")) + : n.params === '"tailwindcss/components"' || n.params === "'tailwindcss/components'" + ? ((n.name = "tailwind"), (n.params = "components")) + : n.params === '"tailwindcss/utilities"' || n.params === "'tailwindcss/utilities'" + ? ((n.name = "tailwind"), (n.params = "utilities")) + : (n.params === '"tailwindcss/screens"' || + n.params === "'tailwindcss/screens'" || + n.params === '"tailwindcss/variants"' || + n.params === "'tailwindcss/variants'") && + ((n.name = "tailwind"), (n.params = "variants"))), + n.name === "tailwind" && (n.params === "screens" && (n.params = "variants"), e.add(n.params)), + ["layer", "responsive", "variants"].includes(n.name) && + (["responsive", "variants"].includes(n.name) && + F.warn(`${n.name}-at-rule-deprecated`, [ + `The \`@${n.name}\` directive has been deprecated in Tailwind CSS v3.0.`, + "Use `@layer utilities` or `@layer components` instead.", + "https://tailwindcss.com/docs/upgrade-guide#replace-variants-with-layer", + ]), + t.add(n))); + }), + !e.has("base") || !e.has("components") || !e.has("utilities")) + ) { + for (let n of t) + if (n.name === "layer" && ["base", "components", "utilities"].includes(n.params)) { + if (!e.has(n.params)) + throw n.error( + `\`@layer ${n.params}\` is used but no matching \`@tailwind ${n.params}\` directive is present.` + ); + } else if (n.name === "responsive") { + if (!e.has("utilities")) + throw n.error("`@responsive` is used but `@tailwind utilities` is missing."); + } else if (n.name === "variants" && !e.has("utilities")) + throw n.error("`@variants` is used but `@tailwind utilities` is missing."); + } + return { tailwindDirectives: e, applyDirectives: i }; + } + var Sh = C(() => { + l(); + Oe(); + }); + function St(r, e = void 0, t = void 0) { + return r.map((i) => { + let n = i.clone(); + return ( + t !== void 0 && (n.raws.tailwind = { ...n.raws.tailwind, ...t }), + e !== void 0 && + Ch(n, (a) => { + if (a.raws.tailwind?.preserveSource === !0 && a.source) return !1; + a.source = e; + }), + n + ); + }); + } + function Ch(r, e) { + e(r) !== !1 && r.each?.((t) => Ch(t, e)); + } + var Ah = C(() => { + l(); + }); + function Oo(r) { + return ((r = Array.isArray(r) ? r : [r]), (r = r.map((e) => (e instanceof RegExp ? e.source : e))), r.join("")); + } + function ye(r) { + return new RegExp(Oo(r), "g"); + } + function ft(r) { + return `(?:${r.map(Oo).join("|")})`; + } + function Eo(r) { + return `(?:${Oo(r)})?`; + } + function Oh(r) { + return r && aC.test(r) ? r.replace(_h, "\\$&") : r || ""; + } + var _h, + aC, + Eh = C(() => { + l(); + ((_h = /[\\^$.*+?()[\]{}|]/g), (aC = RegExp(_h.source))); + }); + function Th(r) { + let e = Array.from(oC(r)); + return (t) => { + let i = []; + for (let n of e) for (let a of t.match(n) ?? []) i.push(fC(a)); + return i; + }; + } + function* oC(r) { + let e = r.tailwindConfig.separator, + t = r.tailwindConfig.prefix !== "" ? Eo(ye([/-?/, Oh(r.tailwindConfig.prefix)])) : "", + i = ft([ + /\[[^\s:'"`]+:[^\s\[\]]+\]/, + /\[[^\s:'"`\]]+:[^\s]+?\[[^\s]+\][^\s]+?\]/, + ye([ + ft([/-?(?:\w+)/, /@(?:\w+)/]), + Eo( + ft([ + ye([ + ft([ + /-(?:\w+-)*\['[^\s]+'\]/, + /-(?:\w+-)*\["[^\s]+"\]/, + /-(?:\w+-)*\[`[^\s]+`\]/, + /-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s:\[\]]+\]/, + ]), + /(?![{([]])/, + /(?:\/[^\s'"`\\><$]*)?/, + ]), + ye([ + ft([ + /-(?:\w+-)*\['[^\s]+'\]/, + /-(?:\w+-)*\["[^\s]+"\]/, + /-(?:\w+-)*\[`[^\s]+`\]/, + /-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s\[\]]+\]/, + ]), + /(?![{([]])/, + /(?:\/[^\s'"`\\$]*)?/, + ]), + /[-\/][^\s'"`\\$={><]*/, + ]) + ), + ]), + ]), + n = [ + ft([ + ye([/@\[[^\s"'`]+\](\/[^\s"'`]+)?/, e]), + ye([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]\/[\w_-]+/, e]), + ye([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, e]), + ye([/[^\s"'`\[\\]+/, e]), + ]), + ft([ + ye([/([^\s"'`\[\\]+-)?\[[^\s`]+\]\/[\w_-]+/, e]), + ye([/([^\s"'`\[\\]+-)?\[[^\s`]+\]/, e]), + ye([/[^\s`\[\\]+/, e]), + ]), + ]; + for (let a of n) yield ye(["((?=((", a, ")+))\\2)?", /!?/, t, i]); + yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g; + } + function fC(r) { + if (!r.includes("-[")) return r; + let e = 0, + t = [], + i = r.matchAll(lC); + i = Array.from(i).flatMap((n) => { + let [, ...a] = n; + return a.map((s, o) => Object.assign([], n, { index: n.index + o, 0: s })); + }); + for (let n of i) { + let a = n[0], + s = t[t.length - 1]; + if ((a === s ? t.pop() : (a === "'" || a === '"' || a === "`") && t.push(a), !s)) { + if (a === "[") { + e++; + continue; + } else if (a === "]") { + e--; + continue; + } + if (e < 0) return r.substring(0, n.index - 1); + if (e === 0 && !uC.test(a)) return r.substring(0, n.index); + } + } + return r; + } + var lC, + uC, + Ph = C(() => { + l(); + Eh(); + ((lC = /([\[\]'"`])([^\[\]'"`])?/g), (uC = /[^"'`\s<>\]]+/)); + }); + function cC(r, e) { + let t = r.tailwindConfig.content.extract; + return t[e] || t.DEFAULT || Ih[e] || Ih.DEFAULT(r); + } + function pC(r, e) { + let t = r.content.transform; + return t[e] || t.DEFAULT || qh[e] || qh.DEFAULT; + } + function dC(r, e, t, i) { + ni.has(e) || ni.set(e, new Dh.default({ maxSize: 25e3 })); + for (let n of r.split(` +`)) + if (((n = n.trim()), !i.has(n))) + if ((i.add(n), ni.get(e).has(n))) for (let a of ni.get(e).get(n)) t.add(a); + else { + let a = e(n).filter((o) => o !== "!*"), + s = new Set(a); + for (let o of s) t.add(o); + ni.get(e).set(n, s); + } + } + function hC(r, e) { + let t = e.offsets.sort(r), + i = { + base: new Set(), + defaults: new Set(), + components: new Set(), + utilities: new Set(), + variants: new Set(), + }; + for (let [n, a] of t) i[n.layer].add(a); + return i; + } + function To(r) { + return async (e) => { + let t = { base: null, components: null, utilities: null, variants: null }; + if ( + (e.walkAtRules((y) => { + y.name === "tailwind" && Object.keys(t).includes(y.params) && (t[y.params] = y); + }), + Object.values(t).every((y) => y === null)) + ) + return e; + let i = new Set([...(r.candidates ?? []), He]), + n = new Set(); + Ye.DEBUG && console.time("Reading changed files"); + let a = []; + for (let y of r.changedContent) { + let w = pC(r.tailwindConfig, y.extension), + k = cC(r, y.extension); + a.push([y, { transformer: w, extractor: k }]); + } + let s = 500; + for (let y = 0; y < a.length; y += s) { + let w = a.slice(y, y + s); + await Promise.all( + w.map(async ([{ file: k, content: S }, { transformer: _, extractor: E }]) => { + ((S = k ? await te.promises.readFile(k, "utf8") : S), dC(_(S), E, i, n)); + }) + ); + } + Ye.DEBUG && console.timeEnd("Reading changed files"); + let o = r.classCache.size; + (Ye.DEBUG && console.time("Generate rules"), Ye.DEBUG && console.time("Sorting candidates")); + let u = new Set([...i].sort((y, w) => (y === w ? 0 : y < w ? -1 : 1))); + (Ye.DEBUG && console.timeEnd("Sorting candidates"), + _n(u, r), + Ye.DEBUG && console.timeEnd("Generate rules"), + Ye.DEBUG && console.time("Build stylesheet"), + (r.stylesheetCache === null || r.classCache.size !== o) && + (r.stylesheetCache = hC([...r.ruleCache], r)), + Ye.DEBUG && console.timeEnd("Build stylesheet")); + let { defaults: c, base: f, components: d, utilities: p, variants: m } = r.stylesheetCache; + (t.base && (t.base.before(St([...f, ...c], t.base.source, { layer: "base" })), t.base.remove()), + t.components && + (t.components.before(St([...d], t.components.source, { layer: "components" })), + t.components.remove()), + t.utilities && + (t.utilities.before(St([...p], t.utilities.source, { layer: "utilities" })), t.utilities.remove())); + let b = Array.from(m).filter((y) => { + let w = y.raws.tailwind?.parentLayer; + return w === "components" ? t.components !== null : w === "utilities" ? t.utilities !== null : !0; + }); + (t.variants + ? (t.variants.before(St(b, t.variants.source, { layer: "variants" })), t.variants.remove()) + : b.length > 0 && e.append(St(b, e.source, { layer: "variants" })), + (e.source.end = e.source.end ?? e.source.start)); + let x = b.some((y) => y.raws.tailwind?.parentLayer === "utilities"); + (t.utilities && + p.size === 0 && + !x && + F.warn("content-problems", [ + "No utility classes were detected in your source files. If this is unexpected, double-check the `content` option in your Tailwind CSS configuration.", + "https://tailwindcss.com/docs/content-configuration", + ]), + Ye.DEBUG && (console.log("Potential classes: ", i.size), console.log("Active contexts: ", vn.size)), + (r.changedContent = []), + e.walkAtRules("layer", (y) => { + Object.keys(t).includes(y.params) && y.remove(); + })); + }; + } + var Dh, + Ye, + Ih, + qh, + ni, + Rh = C(() => { + l(); + ze(); + Dh = X(rs()); + lt(); + On(); + Oe(); + Ah(); + Ph(); + ((Ye = Pe), + (Ih = { DEFAULT: Th }), + (qh = { DEFAULT: (r) => r, svelte: (r) => r.replace(/(?:^|\s)class:/g, " ") })); + ni = new WeakMap(); + }); + function Bn(r) { + let e = new Map(); + j.root({ nodes: [r.clone()] }).walkRules((a) => { + (0, Mn.default)((s) => { + s.walkClasses((o) => { + let u = o.parent.toString(), + c = e.get(u); + (c || e.set(u, (c = new Set())), c.add(o.value)); + }); + }).processSync(a.selector); + }); + let i = Array.from(e.values(), (a) => Array.from(a)), + n = i.flat(); + return Object.assign(n, { groups: i }); + } + function Po(r) { + return mC.astSync(r); + } + function Mh(r, e) { + let t = new Set(); + for (let i of r) t.add(i.split(e).pop()); + return Array.from(t); + } + function Bh(r, e) { + let t = r.tailwindConfig.prefix; + return typeof t == "function" ? t(e) : t + e; + } + function* Fh(r) { + for (yield r; r.parent; ) (yield r.parent, (r = r.parent)); + } + function gC(r, e = {}) { + let t = r.nodes; + r.nodes = []; + let i = r.clone(e); + return ((r.nodes = t), i); + } + function yC(r) { + for (let e of Fh(r)) + if (r !== e) { + if (e.type === "root") break; + r = gC(e, { nodes: [r] }); + } + return r; + } + function wC(r, e) { + let t = new Map(); + return ( + r.walkRules((i) => { + for (let s of Fh(i)) if (s.raws.tailwind?.layer !== void 0) return; + let n = yC(i), + a = e.offsets.create("user"); + for (let s of Bn(i)) { + let o = t.get(s) || []; + (t.set(s, o), o.push([{ layer: "user", sort: a, important: !1 }, n])); + } + }), + t + ); + } + function bC(r, e) { + for (let t of r) { + if (e.notClassCache.has(t) || e.applyClassCache.has(t)) continue; + if (e.classCache.has(t)) { + e.applyClassCache.set( + t, + e.classCache.get(t).map(([n, a]) => [n, a.clone()]) + ); + continue; + } + let i = Array.from(fo(t, e)); + if (i.length === 0) { + e.notClassCache.add(t); + continue; + } + e.applyClassCache.set(t, i); + } + return e.applyClassCache; + } + function vC(r) { + let e = null; + return { get: (t) => ((e = e || r()), e.get(t)), has: (t) => ((e = e || r()), e.has(t)) }; + } + function xC(r) { + return { get: (e) => r.flatMap((t) => t.get(e) || []), has: (e) => r.some((t) => t.has(e)) }; + } + function Lh(r) { + let e = r.split(/[\s\t\n]+/g); + return e[e.length - 1] === "!important" ? [e.slice(0, -1), !0] : [e, !1]; + } + function Nh(r, e, t) { + let i = new Set(), + n = []; + if ( + (r.walkAtRules("apply", (u) => { + let [c] = Lh(u.params); + for (let f of c) i.add(f); + n.push(u); + }), + n.length === 0) + ) + return; + let a = xC([t, bC(i, e)]); + function s(u, c, f) { + let d = Po(u), + p = Po(c), + b = Po(`.${ce(f)}`).nodes[0].nodes[0]; + return ( + d.each((x) => { + let y = new Set(); + p.each((w) => { + let k = !1; + ((w = w.clone()), + w.walkClasses((S) => { + S.value === b.value && + (k || (S.replaceWith(...x.nodes.map((_) => _.clone())), y.add(w), (k = !0))); + })); + }); + for (let w of y) { + let k = [[]]; + for (let S of w.nodes) + S.type === "combinator" ? (k.push(S), k.push([])) : k[k.length - 1].push(S); + w.nodes = []; + for (let S of k) + (Array.isArray(S) && + S.sort((_, E) => + _.type === "tag" && E.type === "class" + ? -1 + : _.type === "class" && E.type === "tag" + ? 1 + : _.type === "class" && E.type === "pseudo" && E.value.startsWith("::") + ? -1 + : _.type === "pseudo" && _.value.startsWith("::") && E.type === "class" + ? 1 + : 0 + ), + (w.nodes = w.nodes.concat(S))); + } + x.replaceWith(...y); + }), + d.toString() + ); + } + let o = new Map(); + for (let u of n) { + let [c] = o.get(u.parent) || [[], u.source]; + o.set(u.parent, [c, u.source]); + let [f, d] = Lh(u.params); + if (u.parent.type === "atrule") { + if (u.parent.name === "screen") { + let p = u.parent.params; + throw u.error( + `@apply is not supported within nested at-rules like @screen. We suggest you write this as @apply ${f.map((m) => `${p}:${m}`).join(" ")} instead.` + ); + } + throw u.error( + `@apply is not supported within nested at-rules like @${u.parent.name}. You can fix this by un-nesting @${u.parent.name}.` + ); + } + for (let p of f) { + if ([Bh(e, "group"), Bh(e, "peer")].includes(p)) + throw u.error(`@apply should not be used with the '${p}' utility`); + if (!a.has(p)) + throw u.error( + `The \`${p}\` class does not exist. If \`${p}\` is a custom class, make sure it is defined within a \`@layer\` directive.` + ); + let m = a.get(p); + for (let [, b] of m) + b.type !== "atrule" && + b.walkRules(() => { + throw u.error( + [ + `The \`${p}\` class cannot be used with \`@apply\` because \`@apply\` does not currently support nested CSS.`, + "Rewrite the selector without nesting or configure the `tailwindcss/nesting` plugin:", + "https://tailwindcss.com/docs/using-with-preprocessors#nesting", + ].join(` +`) + ); + }); + c.push([p, d, m]); + } + } + for (let [u, [c, f]] of o) { + let d = []; + for (let [m, b, x] of c) { + let y = [m, ...Mh([m], e.tailwindConfig.separator)]; + for (let [w, k] of x) { + let S = Bn(u), + _ = Bn(k); + if ( + ((_ = _.groups.filter((R) => R.some((J) => y.includes(J))).flat()), + (_ = _.concat(Mh(_, e.tailwindConfig.separator))), + S.some((R) => _.includes(R))) + ) + throw k.error( + `You cannot \`@apply\` the \`${m}\` utility here because it creates a circular dependency.` + ); + let I = j.root({ nodes: [k.clone()] }); + (I.walk((R) => { + R.source = f; + }), + (k.type !== "atrule" || (k.type === "atrule" && k.name !== "keyframes")) && + I.walkRules((R) => { + if (!Bn(R).some((ee) => ee === m)) { + R.remove(); + return; + } + let J = + typeof e.tailwindConfig.important == "string" + ? e.tailwindConfig.important + : null, + de = + u.raws.tailwind !== void 0 && J && u.selector.indexOf(J) === 0 + ? u.selector.slice(J.length) + : u.selector; + (de === "" && (de = u.selector), + (R.selector = s(de, R.selector, m)), + J && de !== u.selector && (R.selector = Sn(R.selector, J)), + R.walkDecls((ee) => { + ee.important = w.important || b; + })); + let De = (0, Mn.default)().astSync(R.selector); + (De.each((ee) => jt(ee)), (R.selector = De.toString())); + }), + !!I.nodes[0] && d.push([w.sort, I.nodes[0]])); + } + } + let p = e.offsets.sort(d).map((m) => m[1]); + u.after(p); + } + for (let u of n) u.parent.nodes.length > 1 ? u.remove() : u.parent.remove(); + Nh(r, e, t); + } + function Do(r) { + return (e) => { + let t = vC(() => wC(e, r)); + Nh(e, r, t); + }; + } + var Mn, + mC, + $h = C(() => { + l(); + st(); + Mn = X(Me()); + On(); + $t(); + oo(); + xn(); + mC = (0, Mn.default)(); + }); + var zh = v((I4, Fn) => { + l(); + (function () { + "use strict"; + function r(i, n, a) { + if (!i) return null; + r.caseSensitive || (i = i.toLowerCase()); + var s = r.threshold === null ? null : r.threshold * i.length, + o = r.thresholdAbsolute, + u; + s !== null && o !== null + ? (u = Math.min(s, o)) + : s !== null + ? (u = s) + : o !== null + ? (u = o) + : (u = null); + var c, + f, + d, + p, + m, + b = n.length; + for (m = 0; m < b; m++) + if ( + ((f = n[m]), + a && (f = f[a]), + !!f && + (r.caseSensitive ? (d = f) : (d = f.toLowerCase()), + (p = t(i, d, u)), + (u === null || p < u) && + ((u = p), a && r.returnWinningObject ? (c = n[m]) : (c = f), r.returnFirstMatch))) + ) + return c; + return c || r.nullResultValue; + } + ((r.threshold = 0.4), + (r.thresholdAbsolute = 20), + (r.caseSensitive = !1), + (r.nullResultValue = null), + (r.returnWinningObject = null), + (r.returnFirstMatch = !1), + typeof Fn != "undefined" && Fn.exports ? (Fn.exports = r) : (window.didYouMean = r)); + var e = Math.pow(2, 32) - 1; + function t(i, n, a) { + a = a || a === 0 ? a : e; + var s = i.length, + o = n.length; + if (s === 0) return Math.min(a + 1, o); + if (o === 0) return Math.min(a + 1, s); + if (Math.abs(s - o) > a) return a + 1; + var u = [], + c, + f, + d, + p, + m; + for (c = 0; c <= o; c++) u[c] = [c]; + for (f = 0; f <= s; f++) u[0][f] = f; + for (c = 1; c <= o; c++) { + for (d = e, p = 1, c > a && (p = c - a), m = o + 1, m > a + c && (m = a + c), f = 1; f <= s; f++) + (f < p || f > m + ? (u[c][f] = a + 1) + : n.charAt(c - 1) === i.charAt(f - 1) + ? (u[c][f] = u[c - 1][f - 1]) + : (u[c][f] = Math.min(u[c - 1][f - 1] + 1, Math.min(u[c][f - 1] + 1, u[c - 1][f] + 1))), + u[c][f] < d && (d = u[c][f])); + if (d > a) return a + 1; + } + return u[o][s]; + } + })(); + }); + var Vh = v((q4, jh) => { + l(); + var Io = "(".charCodeAt(0), + qo = ")".charCodeAt(0), + Ln = "'".charCodeAt(0), + Ro = '"'.charCodeAt(0), + Mo = "\\".charCodeAt(0), + Wt = "/".charCodeAt(0), + Bo = ",".charCodeAt(0), + Fo = ":".charCodeAt(0), + Nn = "*".charCodeAt(0), + kC = "u".charCodeAt(0), + SC = "U".charCodeAt(0), + CC = "+".charCodeAt(0), + AC = /^[a-f0-9?-]+$/i; + jh.exports = function (r) { + for ( + var e = [], + t = r, + i, + n, + a, + s, + o, + u, + c, + f, + d = 0, + p = t.charCodeAt(d), + m = t.length, + b = [{ nodes: e }], + x = 0, + y, + w = "", + k = "", + S = ""; + d < m; + ) + if (p <= 32) { + i = d; + do ((i += 1), (p = t.charCodeAt(i))); + while (p <= 32); + ((s = t.slice(d, i)), + (a = e[e.length - 1]), + p === qo && x + ? (S = s) + : a && a.type === "div" + ? ((a.after = s), (a.sourceEndIndex += s.length)) + : p === Bo || + p === Fo || + (p === Wt && t.charCodeAt(i + 1) !== Nn && (!y || (y && y.type === "function" && !1))) + ? (k = s) + : e.push({ type: "space", sourceIndex: d, sourceEndIndex: i, value: s }), + (d = i)); + } else if (p === Ln || p === Ro) { + ((i = d), (n = p === Ln ? "'" : '"'), (s = { type: "string", sourceIndex: d, quote: n })); + do + if (((o = !1), (i = t.indexOf(n, i + 1)), ~i)) + for (u = i; t.charCodeAt(u - 1) === Mo; ) ((u -= 1), (o = !o)); + else ((t += n), (i = t.length - 1), (s.unclosed = !0)); + while (o); + ((s.value = t.slice(d + 1, i)), + (s.sourceEndIndex = s.unclosed ? i : i + 1), + e.push(s), + (d = i + 1), + (p = t.charCodeAt(d))); + } else if (p === Wt && t.charCodeAt(d + 1) === Nn) + ((i = t.indexOf("*/", d)), + (s = { type: "comment", sourceIndex: d, sourceEndIndex: i + 2 }), + i === -1 && ((s.unclosed = !0), (i = t.length), (s.sourceEndIndex = i)), + (s.value = t.slice(d + 2, i)), + e.push(s), + (d = i + 2), + (p = t.charCodeAt(d))); + else if ((p === Wt || p === Nn) && y && y.type === "function") + ((s = t[d]), + e.push({ type: "word", sourceIndex: d - k.length, sourceEndIndex: d + s.length, value: s }), + (d += 1), + (p = t.charCodeAt(d))); + else if (p === Wt || p === Bo || p === Fo) + ((s = t[d]), + e.push({ + type: "div", + sourceIndex: d - k.length, + sourceEndIndex: d + s.length, + value: s, + before: k, + after: "", + }), + (k = ""), + (d += 1), + (p = t.charCodeAt(d))); + else if (Io === p) { + i = d; + do ((i += 1), (p = t.charCodeAt(i))); + while (p <= 32); + if ( + ((f = d), + (s = { type: "function", sourceIndex: d - w.length, value: w, before: t.slice(f + 1, i) }), + (d = i), + w === "url" && p !== Ln && p !== Ro) + ) { + i -= 1; + do + if (((o = !1), (i = t.indexOf(")", i + 1)), ~i)) + for (u = i; t.charCodeAt(u - 1) === Mo; ) ((u -= 1), (o = !o)); + else ((t += ")"), (i = t.length - 1), (s.unclosed = !0)); + while (o); + c = i; + do ((c -= 1), (p = t.charCodeAt(c))); + while (p <= 32); + (f < c + ? (d !== c + 1 + ? (s.nodes = [ + { + type: "word", + sourceIndex: d, + sourceEndIndex: c + 1, + value: t.slice(d, c + 1), + }, + ]) + : (s.nodes = []), + s.unclosed && c + 1 !== i + ? ((s.after = ""), + s.nodes.push({ + type: "space", + sourceIndex: c + 1, + sourceEndIndex: i, + value: t.slice(c + 1, i), + })) + : ((s.after = t.slice(c + 1, i)), (s.sourceEndIndex = i))) + : ((s.after = ""), (s.nodes = [])), + (d = i + 1), + (s.sourceEndIndex = s.unclosed ? i : d), + (p = t.charCodeAt(d)), + e.push(s)); + } else + ((x += 1), + (s.after = ""), + (s.sourceEndIndex = d + 1), + e.push(s), + b.push(s), + (e = s.nodes = []), + (y = s)); + w = ""; + } else if (qo === p && x) + ((d += 1), + (p = t.charCodeAt(d)), + (y.after = S), + (y.sourceEndIndex += S.length), + (S = ""), + (x -= 1), + (b[b.length - 1].sourceEndIndex = d), + b.pop(), + (y = b[x]), + (e = y.nodes)); + else { + i = d; + do (p === Mo && (i += 1), (i += 1), (p = t.charCodeAt(i))); + while ( + i < m && + !( + p <= 32 || + p === Ln || + p === Ro || + p === Bo || + p === Fo || + p === Wt || + p === Io || + (p === Nn && y && y.type === "function" && !0) || + (p === Wt && y.type === "function" && !0) || + (p === qo && x) + ) + ); + ((s = t.slice(d, i)), + Io === p + ? (w = s) + : (kC === s.charCodeAt(0) || SC === s.charCodeAt(0)) && + CC === s.charCodeAt(1) && + AC.test(s.slice(2)) + ? e.push({ type: "unicode-range", sourceIndex: d, sourceEndIndex: i, value: s }) + : e.push({ type: "word", sourceIndex: d, sourceEndIndex: i, value: s }), + (d = i)); + } + for (d = b.length - 1; d; d -= 1) ((b[d].unclosed = !0), (b[d].sourceEndIndex = t.length)); + return b[0].nodes; + }; + }); + var Wh = v((R4, Uh) => { + l(); + Uh.exports = function r(e, t, i) { + var n, a, s, o; + for (n = 0, a = e.length; n < a; n += 1) + ((s = e[n]), + i || (o = t(s, n, e)), + o !== !1 && s.type === "function" && Array.isArray(s.nodes) && r(s.nodes, t, i), + i && t(s, n, e)); + }; + }); + var Qh = v((M4, Yh) => { + l(); + function Gh(r, e) { + var t = r.type, + i = r.value, + n, + a; + return e && (a = e(r)) !== void 0 + ? a + : t === "word" || t === "space" + ? i + : t === "string" + ? ((n = r.quote || ""), n + i + (r.unclosed ? "" : n)) + : t === "comment" + ? "/*" + i + (r.unclosed ? "" : "*/") + : t === "div" + ? (r.before || "") + i + (r.after || "") + : Array.isArray(r.nodes) + ? ((n = Hh(r.nodes, e)), + t !== "function" + ? n + : i + "(" + (r.before || "") + n + (r.after || "") + (r.unclosed ? "" : ")")) + : i; + } + function Hh(r, e) { + var t, i; + if (Array.isArray(r)) { + for (t = "", i = r.length - 1; ~i; i -= 1) t = Gh(r[i], e) + t; + return t; + } + return Gh(r, e); + } + Yh.exports = Hh; + }); + var Xh = v((B4, Jh) => { + l(); + var $n = "-".charCodeAt(0), + zn = "+".charCodeAt(0), + Lo = ".".charCodeAt(0), + _C = "e".charCodeAt(0), + OC = "E".charCodeAt(0); + function EC(r) { + var e = r.charCodeAt(0), + t; + if (e === zn || e === $n) { + if (((t = r.charCodeAt(1)), t >= 48 && t <= 57)) return !0; + var i = r.charCodeAt(2); + return t === Lo && i >= 48 && i <= 57; + } + return e === Lo ? ((t = r.charCodeAt(1)), t >= 48 && t <= 57) : e >= 48 && e <= 57; + } + Jh.exports = function (r) { + var e = 0, + t = r.length, + i, + n, + a; + if (t === 0 || !EC(r)) return !1; + for ( + i = r.charCodeAt(e), (i === zn || i === $n) && e++; + e < t && ((i = r.charCodeAt(e)), !(i < 48 || i > 57)); + ) + e += 1; + if (((i = r.charCodeAt(e)), (n = r.charCodeAt(e + 1)), i === Lo && n >= 48 && n <= 57)) + for (e += 2; e < t && ((i = r.charCodeAt(e)), !(i < 48 || i > 57)); ) e += 1; + if ( + ((i = r.charCodeAt(e)), + (n = r.charCodeAt(e + 1)), + (a = r.charCodeAt(e + 2)), + (i === _C || i === OC) && ((n >= 48 && n <= 57) || ((n === zn || n === $n) && a >= 48 && a <= 57))) + ) + for (e += n === zn || n === $n ? 3 : 2; e < t && ((i = r.charCodeAt(e)), !(i < 48 || i > 57)); ) e += 1; + return { number: r.slice(0, e), unit: r.slice(e) }; + }; + }); + var tm = v((F4, em) => { + l(); + var TC = Vh(), + Kh = Wh(), + Zh = Qh(); + function ct(r) { + return this instanceof ct ? ((this.nodes = TC(r)), this) : new ct(r); + } + ct.prototype.toString = function () { + return Array.isArray(this.nodes) ? Zh(this.nodes) : ""; + }; + ct.prototype.walk = function (r, e) { + return (Kh(this.nodes, r, e), this); + }; + ct.unit = Xh(); + ct.walk = Kh; + ct.stringify = Zh; + em.exports = ct; + }); + function $o(r) { + return typeof r == "object" && r !== null; + } + function PC(r, e) { + let t = Ze(e); + do if ((t.pop(), (0, si.default)(r, t) !== void 0)) break; + while (t.length); + return t.length ? t : void 0; + } + function Gt(r) { + return typeof r == "string" + ? r + : r.reduce((e, t, i) => (t.includes(".") ? `${e}[${t}]` : i === 0 ? t : `${e}.${t}`), ""); + } + function im(r) { + return r.map((e) => `'${e}'`).join(", "); + } + function nm(r) { + return im(Object.keys(r)); + } + function zo(r, e, t, i = {}) { + let n = Array.isArray(e) ? Gt(e) : e.replace(/^['"]+|['"]+$/g, ""), + a = Array.isArray(e) ? e : Ze(n), + s = (0, si.default)(r.theme, a, t); + if (s === void 0) { + let u = `'${n}' does not exist in your theme config.`, + c = a.slice(0, -1), + f = (0, si.default)(r.theme, c); + if ($o(f)) { + let d = Object.keys(f).filter((m) => zo(r, [...c, m]).isValid), + p = (0, rm.default)(a[a.length - 1], d); + p + ? (u += ` Did you mean '${Gt([...c, p])}'?`) + : d.length > 0 && (u += ` '${Gt(c)}' has the following valid keys: ${im(d)}`); + } else { + let d = PC(r.theme, n); + if (d) { + let p = (0, si.default)(r.theme, d); + $o(p) + ? (u += ` '${Gt(d)}' has the following keys: ${nm(p)}`) + : (u += ` '${Gt(d)}' is not an object.`); + } else u += ` Your theme has the following top-level keys: ${nm(r.theme)}`; + } + return { isValid: !1, error: u }; + } + if ( + !( + typeof s == "string" || + typeof s == "number" || + typeof s == "function" || + s instanceof String || + s instanceof Number || + Array.isArray(s) + ) + ) { + let u = `'${n}' was found but does not resolve to a string.`; + if ($o(s)) { + let c = Object.keys(s).filter((f) => zo(r, [...a, f]).isValid); + c.length && (u += ` Did you mean something like '${Gt([...a, c[0]])}'?`); + } + return { isValid: !1, error: u }; + } + let [o] = a; + return { isValid: !0, value: Ge(o)(s, i) }; + } + function DC(r, e, t) { + e = e.map((n) => sm(r, n, t)); + let i = [""]; + for (let n of e) + n.type === "div" && n.value === "," ? i.push("") : (i[i.length - 1] += No.default.stringify(n)); + return i; + } + function sm(r, e, t) { + if (e.type === "function" && t[e.value] !== void 0) { + let i = DC(r, e.nodes, t); + ((e.type = "word"), (e.value = t[e.value](r, ...i))); + } + return e; + } + function IC(r, e, t) { + return Object.keys(t).some((n) => e.includes(`${n}(`)) + ? (0, No.default)(e) + .walk((n) => { + sm(r, n, t); + }) + .toString() + : e; + } + function* RC(r) { + r = r.replace(/^['"]+|['"]+$/g, ""); + let e = r.match(/^([^\s]+)(?![^\[]*\])(?:\s*\/\s*([^\/\s]+))$/), + t; + (yield [r, void 0], e && ((r = e[1]), (t = e[2]), yield [r, t])); + } + function MC(r, e, t) { + let i = Array.from(RC(e)).map(([n, a]) => + Object.assign(zo(r, n, t, { opacityValue: a }), { resolvedPath: n, alpha: a }) + ); + return i.find((n) => n.isValid) ?? i[0]; + } + function am(r) { + let e = r.tailwindConfig, + t = { + theme: (i, n, ...a) => { + let { isValid: s, value: o, error: u, alpha: c } = MC(e, n, a.length ? a : void 0); + if (!s) { + let p = i.parent, + m = p?.raws.tailwind?.candidate; + if (p && m !== void 0) { + (r.markInvalidUtilityNode(p), + p.remove(), + F.warn("invalid-theme-key-in-class", [ + `The utility \`${m}\` contains an invalid theme value and was not generated.`, + ])); + return; + } + throw i.error(u); + } + let f = Ot(o), + d = f !== void 0 && typeof f == "function"; + return ((c !== void 0 || d) && (c === void 0 && (c = 1), (o = Ie(f, c, f))), o); + }, + screen: (i, n) => { + n = n.replace(/^['"]+/g, "").replace(/['"]+$/g, ""); + let s = ot(e.theme.screens).find(({ name: o }) => o === n); + if (!s) throw i.error(`The '${n}' screen does not exist in your theme.`); + return at(s); + }, + }; + return (i) => { + i.walk((n) => { + let a = qC[n.type]; + a !== void 0 && (n[a] = IC(n, n[a], t)); + }); + }; + } + var si, + rm, + No, + qC, + om = C(() => { + l(); + ((si = X(Gs())), (rm = X(zh()))); + Jr(); + No = X(tm()); + wn(); + mn(); + gi(); + fr(); + hr(); + Oe(); + qC = { atrule: "params", decl: "value" }; + }); + function lm({ tailwindConfig: { theme: r } }) { + return function (e) { + e.walkAtRules("screen", (t) => { + let i = t.params, + a = ot(r.screens).find(({ name: s }) => s === i); + if (!a) throw t.error(`No \`${i}\` screen found.`); + ((t.name = "media"), (t.params = at(a))); + }); + }; + } + var um = C(() => { + l(); + wn(); + mn(); + }); + function BC(r) { + let e = r + .filter((o) => + o.type !== "pseudo" || o.nodes.length > 0 + ? !0 + : o.value.startsWith("::") || + [":before", ":after", ":first-line", ":first-letter"].includes(o.value) + ) + .reverse(), + t = new Set(["tag", "class", "id", "attribute"]), + i = e.findIndex((o) => t.has(o.type)); + if (i === -1) return e.reverse().join("").trim(); + let n = e[i], + a = fm[n.type] ? fm[n.type](n) : n; + e = e.slice(0, i); + let s = e.findIndex((o) => o.type === "combinator" && o.value === ">"); + return (s !== -1 && (e.splice(0, s), e.unshift(jn.default.universal())), [a, ...e.reverse()].join("").trim()); + } + function LC(r) { + return (jo.has(r) || jo.set(r, FC.transformSync(r)), jo.get(r)); + } + function Vo({ tailwindConfig: r }) { + return (e) => { + let t = new Map(), + i = new Set(); + if ( + (e.walkAtRules("defaults", (n) => { + if (n.nodes && n.nodes.length > 0) { + i.add(n); + return; + } + let a = n.params; + (t.has(a) || t.set(a, new Set()), t.get(a).add(n.parent), n.remove()); + }), + K(r, "optimizeUniversalDefaults")) + ) + for (let n of i) { + let a = new Map(), + s = t.get(n.params) ?? []; + for (let o of s) + for (let u of LC(o.selector)) { + let c = u.includes(":-") || u.includes("::-") || u.includes(":has") ? u : "__DEFAULT__", + f = a.get(c) ?? new Set(); + (a.set(c, f), f.add(u)); + } + if (K(r, "optimizeUniversalDefaults")) { + if (a.size === 0) { + n.remove(); + continue; + } + for (let [, o] of a) { + let u = j.rule({ source: n.source }); + ((u.selectors = [...o]), u.append(n.nodes.map((c) => c.clone())), n.before(u)); + } + } + n.remove(); + } + else if (i.size) { + let n = j.rule({ selectors: ["*", "::before", "::after"] }); + for (let s of i) + (n.append(s.nodes), n.parent || s.before(n), n.source || (n.source = s.source), s.remove()); + let a = n.clone({ selectors: ["::backdrop"] }); + n.after(a); + } + }; + } + var jn, + fm, + FC, + jo, + cm = C(() => { + l(); + st(); + jn = X(Me()); + je(); + fm = { + id(r) { + return jn.default.attribute({ attribute: "id", operator: "=", value: r.value, quoteMark: '"' }); + }, + }; + ((FC = (0, jn.default)((r) => + r.map((e) => { + let t = e.split((i) => i.type === "combinator" && i.value === " ").pop(); + return BC(t); + }) + )), + (jo = new Map())); + }); + function Uo() { + function r(e) { + let t = null; + (e.each((i) => { + if (!NC.has(i.type)) { + t = null; + return; + } + if (t === null) { + t = i; + return; + } + let n = pm[i.type]; + i.type === "atrule" && i.name === "font-face" + ? (t = i) + : n.every((a) => (i[a] ?? "").replace(/\s+/g, " ") === (t[a] ?? "").replace(/\s+/g, " ")) + ? (i.nodes && t.append(i.nodes), i.remove()) + : (t = i); + }), + e.each((i) => { + i.type === "atrule" && r(i); + })); + } + return (e) => { + r(e); + }; + } + var pm, + NC, + dm = C(() => { + l(); + ((pm = { atrule: ["name", "params"], rule: ["selector"] }), (NC = new Set(Object.keys(pm)))); + }); + function Wo() { + return (r) => { + r.walkRules((e) => { + let t = new Map(), + i = new Set([]), + n = new Map(); + e.walkDecls((a) => { + if (a.parent === e) { + if (t.has(a.prop)) { + if (t.get(a.prop).value === a.value) { + (i.add(t.get(a.prop)), t.set(a.prop, a)); + return; + } + (n.has(a.prop) || n.set(a.prop, new Set()), + n.get(a.prop).add(t.get(a.prop)), + n.get(a.prop).add(a)); + } + t.set(a.prop, a); + } + }); + for (let a of i) a.remove(); + for (let a of n.values()) { + let s = new Map(); + for (let o of a) { + let u = zC(o.value); + u !== null && (s.has(u) || s.set(u, new Set()), s.get(u).add(o)); + } + for (let o of s.values()) { + let u = Array.from(o).slice(0, -1); + for (let c of u) c.remove(); + } + } + }); + }; + } + function zC(r) { + let e = /^-?\d*.?\d+([\w%]+)?$/g.exec(r); + return e ? (e[1] ?? $C) : null; + } + var $C, + hm = C(() => { + l(); + $C = Symbol("unitless-number"); + }); + function jC(r) { + if (!r.walkAtRules) return; + let e = new Set(); + if ( + (r.walkAtRules("apply", (t) => { + e.add(t.parent); + }), + e.size !== 0) + ) + for (let t of e) { + let i = [], + n = []; + for (let a of t.nodes) + a.type === "atrule" && a.name === "apply" + ? (n.length > 0 && (i.push(n), (n = [])), i.push([a])) + : n.push(a); + if ((n.length > 0 && i.push(n), i.length !== 1)) { + for (let a of [...i].reverse()) { + let s = t.clone({ nodes: [] }); + (s.append(a), t.after(s)); + } + t.remove(); + } + } + } + function Vn() { + return (r) => { + jC(r); + }; + } + var mm = C(() => { + l(); + }); + function Un(r) { + return async function (e, t) { + let { tailwindDirectives: i, applyDirectives: n } = _o(e); + Vn()(e, t); + let a = r({ + tailwindDirectives: i, + applyDirectives: n, + registerDependency(s) { + t.messages.push({ plugin: "tailwindcss", parent: t.opts.from, ...s }); + }, + createContext(s, o) { + return bo(s, o, e); + }, + })(e, t); + if (a.tailwindConfig.separator === "-") + throw new Error( + "The '-' character cannot be used as a custom separator in JIT mode due to parsing ambiguity. Please use another character like '_' instead." + ); + (Iu(a.tailwindConfig), + await To(a)(e, t), + Vn()(e, t), + Do(a)(e, t), + am(a)(e, t), + lm(a)(e, t), + Vo(a)(e, t), + Uo(a)(e, t), + Wo(a)(e, t)); + }; + } + var gm = C(() => { + l(); + Sh(); + Rh(); + $h(); + om(); + um(); + cm(); + dm(); + hm(); + mm(); + ei(); + je(); + }); + function ym(r, e) { + let t = null, + i = null; + return ( + r.walkAtRules("config", (n) => { + if (((i = n.source?.input.file ?? e.opts.from ?? null), i === null)) + throw n.error( + "The `@config` directive cannot be used without setting `from` in your PostCSS config." + ); + if (t) throw n.error("Only one `@config` directive is allowed per file."); + let a = n.params.match(/(['"])(.*?)\1/); + if (!a) throw n.error("A path is required when using the `@config` directive."); + let s = a[2]; + if (Z.isAbsolute(s)) throw n.error("The `@config` directive cannot be used with an absolute path."); + if (((t = Z.resolve(Z.dirname(i), s)), !te.existsSync(t))) + throw n.error( + `The config file at "${s}" does not exist. Make sure the path is correct and the file exists.` + ); + n.remove(); + }), + t || null + ); + } + var wm = C(() => { + l(); + ze(); + bt(); + }); + var bm = v((vD, Go) => { + l(); + kh(); + gm(); + lt(); + wm(); + Go.exports = function (e) { + return { + postcssPlugin: "tailwindcss", + plugins: [ + Pe.DEBUG && + function (t) { + return ( + console.log(` +`), + console.time("JIT TOTAL"), + t + ); + }, + async function (t, i) { + e = ym(t, i) ?? e; + let n = Ao(e); + if (t.type === "document") { + let a = t.nodes.filter((s) => s.type === "root"); + for (let s of a) s.type === "root" && (await Un(n)(s, i)); + return; + } + await Un(n)(t, i); + }, + Pe.DEBUG && + function (t) { + return ( + console.timeEnd("JIT TOTAL"), + console.log(` +`), + t + ); + }, + ].filter(Boolean), + }; + }; + Go.exports.postcss = !0; + }); + var xm = v((xD, vm) => { + l(); + vm.exports = bm(); + }); + var Ho = v((kD, km) => { + l(); + km.exports = () => [ + "and_chr 114", + "and_uc 15.5", + "chrome 114", + "chrome 113", + "chrome 109", + "edge 114", + "firefox 114", + "ios_saf 16.5", + "ios_saf 16.4", + "ios_saf 16.3", + "ios_saf 16.1", + "opera 99", + "safari 16.5", + "samsung 21", + ]; + }); + var Wn = {}; + Ae(Wn, { agents: () => VC, feature: () => UC }); + function UC() { + return { + status: "cr", + title: "CSS Feature Queries", + stats: { + ie: { 6: "n", 7: "n", 8: "n", 9: "n", 10: "n", 11: "n", 5.5: "n" }, + edge: { + 12: "y", + 13: "y", + 14: "y", + 15: "y", + 16: "y", + 17: "y", + 18: "y", + 79: "y", + 80: "y", + 81: "y", + 83: "y", + 84: "y", + 85: "y", + 86: "y", + 87: "y", + 88: "y", + 89: "y", + 90: "y", + 91: "y", + 92: "y", + 93: "y", + 94: "y", + 95: "y", + 96: "y", + 97: "y", + 98: "y", + 99: "y", + 100: "y", + 101: "y", + 102: "y", + 103: "y", + 104: "y", + 105: "y", + 106: "y", + 107: "y", + 108: "y", + 109: "y", + 110: "y", + 111: "y", + 112: "y", + 113: "y", + 114: "y", + }, + firefox: { + 2: "n", + 3: "n", + 4: "n", + 5: "n", + 6: "n", + 7: "n", + 8: "n", + 9: "n", + 10: "n", + 11: "n", + 12: "n", + 13: "n", + 14: "n", + 15: "n", + 16: "n", + 17: "n", + 18: "n", + 19: "n", + 20: "n", + 21: "n", + 22: "y", + 23: "y", + 24: "y", + 25: "y", + 26: "y", + 27: "y", + 28: "y", + 29: "y", + 30: "y", + 31: "y", + 32: "y", + 33: "y", + 34: "y", + 35: "y", + 36: "y", + 37: "y", + 38: "y", + 39: "y", + 40: "y", + 41: "y", + 42: "y", + 43: "y", + 44: "y", + 45: "y", + 46: "y", + 47: "y", + 48: "y", + 49: "y", + 50: "y", + 51: "y", + 52: "y", + 53: "y", + 54: "y", + 55: "y", + 56: "y", + 57: "y", + 58: "y", + 59: "y", + 60: "y", + 61: "y", + 62: "y", + 63: "y", + 64: "y", + 65: "y", + 66: "y", + 67: "y", + 68: "y", + 69: "y", + 70: "y", + 71: "y", + 72: "y", + 73: "y", + 74: "y", + 75: "y", + 76: "y", + 77: "y", + 78: "y", + 79: "y", + 80: "y", + 81: "y", + 82: "y", + 83: "y", + 84: "y", + 85: "y", + 86: "y", + 87: "y", + 88: "y", + 89: "y", + 90: "y", + 91: "y", + 92: "y", + 93: "y", + 94: "y", + 95: "y", + 96: "y", + 97: "y", + 98: "y", + 99: "y", + 100: "y", + 101: "y", + 102: "y", + 103: "y", + 104: "y", + 105: "y", + 106: "y", + 107: "y", + 108: "y", + 109: "y", + 110: "y", + 111: "y", + 112: "y", + 113: "y", + 114: "y", + 115: "y", + 116: "y", + 117: "y", + 3.5: "n", + 3.6: "n", + }, + chrome: { + 4: "n", + 5: "n", + 6: "n", + 7: "n", + 8: "n", + 9: "n", + 10: "n", + 11: "n", + 12: "n", + 13: "n", + 14: "n", + 15: "n", + 16: "n", + 17: "n", + 18: "n", + 19: "n", + 20: "n", + 21: "n", + 22: "n", + 23: "n", + 24: "n", + 25: "n", + 26: "n", + 27: "n", + 28: "y", + 29: "y", + 30: "y", + 31: "y", + 32: "y", + 33: "y", + 34: "y", + 35: "y", + 36: "y", + 37: "y", + 38: "y", + 39: "y", + 40: "y", + 41: "y", + 42: "y", + 43: "y", + 44: "y", + 45: "y", + 46: "y", + 47: "y", + 48: "y", + 49: "y", + 50: "y", + 51: "y", + 52: "y", + 53: "y", + 54: "y", + 55: "y", + 56: "y", + 57: "y", + 58: "y", + 59: "y", + 60: "y", + 61: "y", + 62: "y", + 63: "y", + 64: "y", + 65: "y", + 66: "y", + 67: "y", + 68: "y", + 69: "y", + 70: "y", + 71: "y", + 72: "y", + 73: "y", + 74: "y", + 75: "y", + 76: "y", + 77: "y", + 78: "y", + 79: "y", + 80: "y", + 81: "y", + 83: "y", + 84: "y", + 85: "y", + 86: "y", + 87: "y", + 88: "y", + 89: "y", + 90: "y", + 91: "y", + 92: "y", + 93: "y", + 94: "y", + 95: "y", + 96: "y", + 97: "y", + 98: "y", + 99: "y", + 100: "y", + 101: "y", + 102: "y", + 103: "y", + 104: "y", + 105: "y", + 106: "y", + 107: "y", + 108: "y", + 109: "y", + 110: "y", + 111: "y", + 112: "y", + 113: "y", + 114: "y", + 115: "y", + 116: "y", + 117: "y", + }, + safari: { + 4: "n", + 5: "n", + 6: "n", + 7: "n", + 8: "n", + 9: "y", + 10: "y", + 11: "y", + 12: "y", + 13: "y", + 14: "y", + 15: "y", + 17: "y", + 9.1: "y", + 10.1: "y", + 11.1: "y", + 12.1: "y", + 13.1: "y", + 14.1: "y", + 15.1: "y", + "15.2-15.3": "y", + 15.4: "y", + 15.5: "y", + 15.6: "y", + "16.0": "y", + 16.1: "y", + 16.2: "y", + 16.3: "y", + 16.4: "y", + 16.5: "y", + 16.6: "y", + TP: "y", + 3.1: "n", + 3.2: "n", + 5.1: "n", + 6.1: "n", + 7.1: "n", + }, + opera: { + 9: "n", + 11: "n", + 12: "n", + 15: "y", + 16: "y", + 17: "y", + 18: "y", + 19: "y", + 20: "y", + 21: "y", + 22: "y", + 23: "y", + 24: "y", + 25: "y", + 26: "y", + 27: "y", + 28: "y", + 29: "y", + 30: "y", + 31: "y", + 32: "y", + 33: "y", + 34: "y", + 35: "y", + 36: "y", + 37: "y", + 38: "y", + 39: "y", + 40: "y", + 41: "y", + 42: "y", + 43: "y", + 44: "y", + 45: "y", + 46: "y", + 47: "y", + 48: "y", + 49: "y", + 50: "y", + 51: "y", + 52: "y", + 53: "y", + 54: "y", + 55: "y", + 56: "y", + 57: "y", + 58: "y", + 60: "y", + 62: "y", + 63: "y", + 64: "y", + 65: "y", + 66: "y", + 67: "y", + 68: "y", + 69: "y", + 70: "y", + 71: "y", + 72: "y", + 73: "y", + 74: "y", + 75: "y", + 76: "y", + 77: "y", + 78: "y", + 79: "y", + 80: "y", + 81: "y", + 82: "y", + 83: "y", + 84: "y", + 85: "y", + 86: "y", + 87: "y", + 88: "y", + 89: "y", + 90: "y", + 91: "y", + 92: "y", + 93: "y", + 94: "y", + 95: "y", + 96: "y", + 97: "y", + 98: "y", + 99: "y", + 100: "y", + 12.1: "y", + "9.5-9.6": "n", + "10.0-10.1": "n", + 10.5: "n", + 10.6: "n", + 11.1: "n", + 11.5: "n", + 11.6: "n", + }, + ios_saf: { + 8: "n", + 17: "y", + "9.0-9.2": "y", + 9.3: "y", + "10.0-10.2": "y", + 10.3: "y", + "11.0-11.2": "y", + "11.3-11.4": "y", + "12.0-12.1": "y", + "12.2-12.5": "y", + "13.0-13.1": "y", + 13.2: "y", + 13.3: "y", + "13.4-13.7": "y", + "14.0-14.4": "y", + "14.5-14.8": "y", + "15.0-15.1": "y", + "15.2-15.3": "y", + 15.4: "y", + 15.5: "y", + 15.6: "y", + "16.0": "y", + 16.1: "y", + 16.2: "y", + 16.3: "y", + 16.4: "y", + 16.5: "y", + 16.6: "y", + 3.2: "n", + "4.0-4.1": "n", + "4.2-4.3": "n", + "5.0-5.1": "n", + "6.0-6.1": "n", + "7.0-7.1": "n", + "8.1-8.4": "n", + }, + op_mini: { all: "y" }, + android: { + 3: "n", + 4: "n", + 114: "y", + 4.4: "y", + "4.4.3-4.4.4": "y", + 2.1: "n", + 2.2: "n", + 2.3: "n", + 4.1: "n", + "4.2-4.3": "n", + }, + bb: { 7: "n", 10: "n" }, + op_mob: { 10: "n", 11: "n", 12: "n", 73: "y", 11.1: "n", 11.5: "n", 12.1: "n" }, + and_chr: { 114: "y" }, + and_ff: { 115: "y" }, + ie_mob: { 10: "n", 11: "n" }, + and_uc: { 15.5: "y" }, + samsung: { + 4: "y", + 20: "y", + 21: "y", + "5.0-5.4": "y", + "6.2-6.4": "y", + "7.2-7.4": "y", + 8.2: "y", + 9.2: "y", + 10.1: "y", + "11.1-11.2": "y", + "12.0": "y", + "13.0": "y", + "14.0": "y", + "15.0": "y", + "16.0": "y", + "17.0": "y", + "18.0": "y", + "19.0": "y", + }, + and_qq: { 13.1: "y" }, + baidu: { 13.18: "y" }, + kaios: { 2.5: "y", "3.0-3.1": "y" }, + }, + }; + } + var VC, + Gn = C(() => { + l(); + VC = { + ie: { prefix: "ms" }, + edge: { + prefix: "webkit", + prefix_exceptions: { 12: "ms", 13: "ms", 14: "ms", 15: "ms", 16: "ms", 17: "ms", 18: "ms" }, + }, + firefox: { prefix: "moz" }, + chrome: { prefix: "webkit" }, + safari: { prefix: "webkit" }, + opera: { + prefix: "webkit", + prefix_exceptions: { + 9: "o", + 11: "o", + 12: "o", + "9.5-9.6": "o", + "10.0-10.1": "o", + 10.5: "o", + 10.6: "o", + 11.1: "o", + 11.5: "o", + 11.6: "o", + 12.1: "o", + }, + }, + ios_saf: { prefix: "webkit" }, + op_mini: { prefix: "o" }, + android: { prefix: "webkit" }, + bb: { prefix: "webkit" }, + op_mob: { prefix: "o", prefix_exceptions: { 73: "webkit" } }, + and_chr: { prefix: "webkit" }, + and_ff: { prefix: "moz" }, + ie_mob: { prefix: "ms" }, + and_uc: { prefix: "webkit", prefix_exceptions: { 15.5: "webkit" } }, + samsung: { prefix: "webkit" }, + and_qq: { prefix: "webkit" }, + baidu: { prefix: "webkit" }, + kaios: { prefix: "moz" }, + }; + }); + var Sm = v(() => { + l(); + }); + var le = v((AD, pt) => { + l(); + var { list: Yo } = ge(); + pt.exports.error = function (r) { + let e = new Error(r); + throw ((e.autoprefixer = !0), e); + }; + pt.exports.uniq = function (r) { + return [...new Set(r)]; + }; + pt.exports.removeNote = function (r) { + return r.includes(" ") ? r.split(" ")[0] : r; + }; + pt.exports.escapeRegexp = function (r) { + return r.replace(/[$()*+-.?[\\\]^{|}]/g, "\\$&"); + }; + pt.exports.regexp = function (r, e = !0) { + return (e && (r = this.escapeRegexp(r)), new RegExp(`(^|[\\s,(])(${r}($|[\\s(,]))`, "gi")); + }; + pt.exports.editList = function (r, e) { + let t = Yo.comma(r), + i = e(t, []); + if (t === i) return r; + let n = r.match(/,\s*/); + return ((n = n ? n[0] : ", "), i.join(n)); + }; + pt.exports.splitSelector = function (r) { + return Yo.comma(r).map((e) => Yo.space(e).map((t) => t.split(/(?=\.|#)/g))); + }; + }); + var dt = v((_D, _m) => { + l(); + var WC = Ho(), + Cm = (Gn(), Wn).agents, + GC = le(), + Am = class { + static prefixes() { + if (this.prefixesCache) return this.prefixesCache; + this.prefixesCache = []; + for (let e in Cm) this.prefixesCache.push(`-${Cm[e].prefix}-`); + return ( + (this.prefixesCache = GC.uniq(this.prefixesCache).sort((e, t) => t.length - e.length)), + this.prefixesCache + ); + } + static withPrefix(e) { + return ( + this.prefixesRegexp || (this.prefixesRegexp = new RegExp(this.prefixes().join("|"))), + this.prefixesRegexp.test(e) + ); + } + constructor(e, t, i, n) { + ((this.data = e), + (this.options = i || {}), + (this.browserslistOpts = n || {}), + (this.selected = this.parse(t))); + } + parse(e) { + let t = {}; + for (let i in this.browserslistOpts) t[i] = this.browserslistOpts[i]; + return ((t.path = this.options.from), WC(e, t)); + } + prefix(e) { + let [t, i] = e.split(" "), + n = this.data[t], + a = n.prefix_exceptions && n.prefix_exceptions[i]; + return (a || (a = n.prefix), `-${a}-`); + } + isSelected(e) { + return this.selected.includes(e); + } + }; + _m.exports = Am; + }); + var ai = v((OD, Om) => { + l(); + Om.exports = { + prefix(r) { + let e = r.match(/^(-\w+-)/); + return e ? e[0] : ""; + }, + unprefixed(r) { + return r.replace(/^-\w+-/, ""); + }, + }; + }); + var Ht = v((ED, Tm) => { + l(); + var HC = dt(), + Em = ai(), + YC = le(); + function Qo(r, e) { + let t = new r.constructor(); + for (let i of Object.keys(r || {})) { + let n = r[i]; + i === "parent" && typeof n == "object" + ? e && (t[i] = e) + : i === "source" || i === null + ? (t[i] = n) + : Array.isArray(n) + ? (t[i] = n.map((a) => Qo(a, t))) + : i !== "_autoprefixerPrefix" && + i !== "_autoprefixerValues" && + i !== "proxyCache" && + (typeof n == "object" && n !== null && (n = Qo(n, t)), (t[i] = n)); + } + return t; + } + var Hn = class { + static hack(e) { + return (this.hacks || (this.hacks = {}), e.names.map((t) => ((this.hacks[t] = e), this.hacks[t]))); + } + static load(e, t, i) { + let n = this.hacks && this.hacks[e]; + return n ? new n(e, t, i) : new this(e, t, i); + } + static clone(e, t) { + let i = Qo(e); + for (let n in t) i[n] = t[n]; + return i; + } + constructor(e, t, i) { + ((this.prefixes = t), (this.name = e), (this.all = i)); + } + parentPrefix(e) { + let t; + return ( + typeof e._autoprefixerPrefix != "undefined" + ? (t = e._autoprefixerPrefix) + : e.type === "decl" && e.prop[0] === "-" + ? (t = Em.prefix(e.prop)) + : e.type === "root" + ? (t = !1) + : e.type === "rule" && e.selector.includes(":-") && /:(-\w+-)/.test(e.selector) + ? (t = e.selector.match(/:(-\w+-)/)[1]) + : e.type === "atrule" && e.name[0] === "-" + ? (t = Em.prefix(e.name)) + : (t = this.parentPrefix(e.parent)), + HC.prefixes().includes(t) || (t = !1), + (e._autoprefixerPrefix = t), + e._autoprefixerPrefix + ); + } + process(e, t) { + if (!this.check(e)) return; + let i = this.parentPrefix(e), + n = this.prefixes.filter((s) => !i || i === YC.removeNote(s)), + a = []; + for (let s of n) this.add(e, s, a.concat([s]), t) && a.push(s); + return a; + } + clone(e, t) { + return Hn.clone(e, t); + } + }; + Tm.exports = Hn; + }); + var M = v((TD, Im) => { + l(); + var QC = Ht(), + JC = dt(), + Pm = le(), + Dm = class extends QC { + check() { + return !0; + } + prefixed(e, t) { + return t + e; + } + normalize(e) { + return e; + } + otherPrefixes(e, t) { + for (let i of JC.prefixes()) if (i !== t && e.includes(i)) return !0; + return !1; + } + set(e, t) { + return ((e.prop = this.prefixed(e.prop, t)), e); + } + needCascade(e) { + return ( + e._autoprefixerCascade || + (e._autoprefixerCascade = + this.all.options.cascade !== !1 && + e.raw("before").includes(` +`)), + e._autoprefixerCascade + ); + } + maxPrefixed(e, t) { + if (t._autoprefixerMax) return t._autoprefixerMax; + let i = 0; + for (let n of e) ((n = Pm.removeNote(n)), n.length > i && (i = n.length)); + return ((t._autoprefixerMax = i), t._autoprefixerMax); + } + calcBefore(e, t, i = "") { + let a = this.maxPrefixed(e, t) - Pm.removeNote(i).length, + s = t.raw("before"); + return (a > 0 && (s += Array(a).fill(" ").join("")), s); + } + restoreBefore(e) { + let t = e.raw("before").split(` +`), + i = t[t.length - 1]; + (this.all.group(e).up((n) => { + let a = n.raw("before").split(` +`), + s = a[a.length - 1]; + s.length < i.length && (i = s); + }), + (t[t.length - 1] = i), + (e.raws.before = t.join(` +`))); + } + insert(e, t, i) { + let n = this.set(this.clone(e), t); + if (!(!n || e.parent.some((s) => s.prop === n.prop && s.value === n.value))) + return ( + this.needCascade(e) && (n.raws.before = this.calcBefore(i, e, t)), + e.parent.insertBefore(e, n) + ); + } + isAlready(e, t) { + let i = this.all.group(e).up((n) => n.prop === t); + return (i || (i = this.all.group(e).down((n) => n.prop === t)), i); + } + add(e, t, i, n) { + let a = this.prefixed(e.prop, t); + if (!(this.isAlready(e, a) || this.otherPrefixes(e.value, t))) return this.insert(e, t, i, n); + } + process(e, t) { + if (!this.needCascade(e)) { + super.process(e, t); + return; + } + let i = super.process(e, t); + !i || !i.length || (this.restoreBefore(e), (e.raws.before = this.calcBefore(i, e))); + } + old(e, t) { + return [this.prefixed(e, t)]; + } + }; + Im.exports = Dm; + }); + var Rm = v((PD, qm) => { + l(); + qm.exports = function r(e) { + return { + mul: (t) => new r(e * t), + div: (t) => new r(e / t), + simplify: () => new r(e), + toString: () => e.toString(), + }; + }; + }); + var Fm = v((DD, Bm) => { + l(); + var XC = Rm(), + KC = Ht(), + Jo = le(), + ZC = /(min|max)-resolution\s*:\s*\d*\.?\d+(dppx|dpcm|dpi|x)/gi, + eA = /(min|max)-resolution(\s*:\s*)(\d*\.?\d+)(dppx|dpcm|dpi|x)/i, + Mm = class extends KC { + prefixName(e, t) { + return e === "-moz-" ? t + "--moz-device-pixel-ratio" : e + t + "-device-pixel-ratio"; + } + prefixQuery(e, t, i, n, a) { + return ( + (n = new XC(n)), + a === "dpi" ? (n = n.div(96)) : a === "dpcm" && (n = n.mul(2.54).div(96)), + (n = n.simplify()), + e === "-o-" && (n = n.n + "/" + n.d), + this.prefixName(e, t) + i + n + ); + } + clean(e) { + if (!this.bad) { + this.bad = []; + for (let t of this.prefixes) + (this.bad.push(this.prefixName(t, "min")), this.bad.push(this.prefixName(t, "max"))); + } + e.params = Jo.editList(e.params, (t) => t.filter((i) => this.bad.every((n) => !i.includes(n)))); + } + process(e) { + let t = this.parentPrefix(e), + i = t ? [t] : this.prefixes; + e.params = Jo.editList(e.params, (n, a) => { + for (let s of n) { + if (!s.includes("min-resolution") && !s.includes("max-resolution")) { + a.push(s); + continue; + } + for (let o of i) { + let u = s.replace(ZC, (c) => { + let f = c.match(eA); + return this.prefixQuery(o, f[1], f[2], f[3], f[4]); + }); + a.push(u); + } + a.push(s); + } + return Jo.uniq(a); + }); + } + }; + Bm.exports = Mm; + }); + var Nm = v((ID, Lm) => { + l(); + var Xo = "(".charCodeAt(0), + Ko = ")".charCodeAt(0), + Yn = "'".charCodeAt(0), + Zo = '"'.charCodeAt(0), + el = "\\".charCodeAt(0), + Yt = "/".charCodeAt(0), + tl = ",".charCodeAt(0), + rl = ":".charCodeAt(0), + Qn = "*".charCodeAt(0), + tA = "u".charCodeAt(0), + rA = "U".charCodeAt(0), + iA = "+".charCodeAt(0), + nA = /^[a-f0-9?-]+$/i; + Lm.exports = function (r) { + for ( + var e = [], + t = r, + i, + n, + a, + s, + o, + u, + c, + f, + d = 0, + p = t.charCodeAt(d), + m = t.length, + b = [{ nodes: e }], + x = 0, + y, + w = "", + k = "", + S = ""; + d < m; + ) + if (p <= 32) { + i = d; + do ((i += 1), (p = t.charCodeAt(i))); + while (p <= 32); + ((s = t.slice(d, i)), + (a = e[e.length - 1]), + p === Ko && x + ? (S = s) + : a && a.type === "div" + ? ((a.after = s), (a.sourceEndIndex += s.length)) + : p === tl || + p === rl || + (p === Yt && + t.charCodeAt(i + 1) !== Qn && + (!y || (y && y.type === "function" && y.value !== "calc"))) + ? (k = s) + : e.push({ type: "space", sourceIndex: d, sourceEndIndex: i, value: s }), + (d = i)); + } else if (p === Yn || p === Zo) { + ((i = d), (n = p === Yn ? "'" : '"'), (s = { type: "string", sourceIndex: d, quote: n })); + do + if (((o = !1), (i = t.indexOf(n, i + 1)), ~i)) + for (u = i; t.charCodeAt(u - 1) === el; ) ((u -= 1), (o = !o)); + else ((t += n), (i = t.length - 1), (s.unclosed = !0)); + while (o); + ((s.value = t.slice(d + 1, i)), + (s.sourceEndIndex = s.unclosed ? i : i + 1), + e.push(s), + (d = i + 1), + (p = t.charCodeAt(d))); + } else if (p === Yt && t.charCodeAt(d + 1) === Qn) + ((i = t.indexOf("*/", d)), + (s = { type: "comment", sourceIndex: d, sourceEndIndex: i + 2 }), + i === -1 && ((s.unclosed = !0), (i = t.length), (s.sourceEndIndex = i)), + (s.value = t.slice(d + 2, i)), + e.push(s), + (d = i + 2), + (p = t.charCodeAt(d))); + else if ((p === Yt || p === Qn) && y && y.type === "function" && y.value === "calc") + ((s = t[d]), + e.push({ type: "word", sourceIndex: d - k.length, sourceEndIndex: d + s.length, value: s }), + (d += 1), + (p = t.charCodeAt(d))); + else if (p === Yt || p === tl || p === rl) + ((s = t[d]), + e.push({ + type: "div", + sourceIndex: d - k.length, + sourceEndIndex: d + s.length, + value: s, + before: k, + after: "", + }), + (k = ""), + (d += 1), + (p = t.charCodeAt(d))); + else if (Xo === p) { + i = d; + do ((i += 1), (p = t.charCodeAt(i))); + while (p <= 32); + if ( + ((f = d), + (s = { type: "function", sourceIndex: d - w.length, value: w, before: t.slice(f + 1, i) }), + (d = i), + w === "url" && p !== Yn && p !== Zo) + ) { + i -= 1; + do + if (((o = !1), (i = t.indexOf(")", i + 1)), ~i)) + for (u = i; t.charCodeAt(u - 1) === el; ) ((u -= 1), (o = !o)); + else ((t += ")"), (i = t.length - 1), (s.unclosed = !0)); + while (o); + c = i; + do ((c -= 1), (p = t.charCodeAt(c))); + while (p <= 32); + (f < c + ? (d !== c + 1 + ? (s.nodes = [ + { + type: "word", + sourceIndex: d, + sourceEndIndex: c + 1, + value: t.slice(d, c + 1), + }, + ]) + : (s.nodes = []), + s.unclosed && c + 1 !== i + ? ((s.after = ""), + s.nodes.push({ + type: "space", + sourceIndex: c + 1, + sourceEndIndex: i, + value: t.slice(c + 1, i), + })) + : ((s.after = t.slice(c + 1, i)), (s.sourceEndIndex = i))) + : ((s.after = ""), (s.nodes = [])), + (d = i + 1), + (s.sourceEndIndex = s.unclosed ? i : d), + (p = t.charCodeAt(d)), + e.push(s)); + } else + ((x += 1), + (s.after = ""), + (s.sourceEndIndex = d + 1), + e.push(s), + b.push(s), + (e = s.nodes = []), + (y = s)); + w = ""; + } else if (Ko === p && x) + ((d += 1), + (p = t.charCodeAt(d)), + (y.after = S), + (y.sourceEndIndex += S.length), + (S = ""), + (x -= 1), + (b[b.length - 1].sourceEndIndex = d), + b.pop(), + (y = b[x]), + (e = y.nodes)); + else { + i = d; + do (p === el && (i += 1), (i += 1), (p = t.charCodeAt(i))); + while ( + i < m && + !( + p <= 32 || + p === Yn || + p === Zo || + p === tl || + p === rl || + p === Yt || + p === Xo || + (p === Qn && y && y.type === "function" && y.value === "calc") || + (p === Yt && y.type === "function" && y.value === "calc") || + (p === Ko && x) + ) + ); + ((s = t.slice(d, i)), + Xo === p + ? (w = s) + : (tA === s.charCodeAt(0) || rA === s.charCodeAt(0)) && + iA === s.charCodeAt(1) && + nA.test(s.slice(2)) + ? e.push({ type: "unicode-range", sourceIndex: d, sourceEndIndex: i, value: s }) + : e.push({ type: "word", sourceIndex: d, sourceEndIndex: i, value: s }), + (d = i)); + } + for (d = b.length - 1; d; d -= 1) ((b[d].unclosed = !0), (b[d].sourceEndIndex = t.length)); + return b[0].nodes; + }; + }); + var zm = v((qD, $m) => { + l(); + $m.exports = function r(e, t, i) { + var n, a, s, o; + for (n = 0, a = e.length; n < a; n += 1) + ((s = e[n]), + i || (o = t(s, n, e)), + o !== !1 && s.type === "function" && Array.isArray(s.nodes) && r(s.nodes, t, i), + i && t(s, n, e)); + }; + }); + var Wm = v((RD, Um) => { + l(); + function jm(r, e) { + var t = r.type, + i = r.value, + n, + a; + return e && (a = e(r)) !== void 0 + ? a + : t === "word" || t === "space" + ? i + : t === "string" + ? ((n = r.quote || ""), n + i + (r.unclosed ? "" : n)) + : t === "comment" + ? "/*" + i + (r.unclosed ? "" : "*/") + : t === "div" + ? (r.before || "") + i + (r.after || "") + : Array.isArray(r.nodes) + ? ((n = Vm(r.nodes, e)), + t !== "function" + ? n + : i + "(" + (r.before || "") + n + (r.after || "") + (r.unclosed ? "" : ")")) + : i; + } + function Vm(r, e) { + var t, i; + if (Array.isArray(r)) { + for (t = "", i = r.length - 1; ~i; i -= 1) t = jm(r[i], e) + t; + return t; + } + return jm(r, e); + } + Um.exports = Vm; + }); + var Hm = v((MD, Gm) => { + l(); + var Jn = "-".charCodeAt(0), + Xn = "+".charCodeAt(0), + il = ".".charCodeAt(0), + sA = "e".charCodeAt(0), + aA = "E".charCodeAt(0); + function oA(r) { + var e = r.charCodeAt(0), + t; + if (e === Xn || e === Jn) { + if (((t = r.charCodeAt(1)), t >= 48 && t <= 57)) return !0; + var i = r.charCodeAt(2); + return t === il && i >= 48 && i <= 57; + } + return e === il ? ((t = r.charCodeAt(1)), t >= 48 && t <= 57) : e >= 48 && e <= 57; + } + Gm.exports = function (r) { + var e = 0, + t = r.length, + i, + n, + a; + if (t === 0 || !oA(r)) return !1; + for ( + i = r.charCodeAt(e), (i === Xn || i === Jn) && e++; + e < t && ((i = r.charCodeAt(e)), !(i < 48 || i > 57)); + ) + e += 1; + if (((i = r.charCodeAt(e)), (n = r.charCodeAt(e + 1)), i === il && n >= 48 && n <= 57)) + for (e += 2; e < t && ((i = r.charCodeAt(e)), !(i < 48 || i > 57)); ) e += 1; + if ( + ((i = r.charCodeAt(e)), + (n = r.charCodeAt(e + 1)), + (a = r.charCodeAt(e + 2)), + (i === sA || i === aA) && ((n >= 48 && n <= 57) || ((n === Xn || n === Jn) && a >= 48 && a <= 57))) + ) + for (e += n === Xn || n === Jn ? 3 : 2; e < t && ((i = r.charCodeAt(e)), !(i < 48 || i > 57)); ) e += 1; + return { number: r.slice(0, e), unit: r.slice(e) }; + }; + }); + var Kn = v((BD, Jm) => { + l(); + var lA = Nm(), + Ym = zm(), + Qm = Wm(); + function ht(r) { + return this instanceof ht ? ((this.nodes = lA(r)), this) : new ht(r); + } + ht.prototype.toString = function () { + return Array.isArray(this.nodes) ? Qm(this.nodes) : ""; + }; + ht.prototype.walk = function (r, e) { + return (Ym(this.nodes, r, e), this); + }; + ht.unit = Hm(); + ht.walk = Ym; + ht.stringify = Qm; + Jm.exports = ht; + }); + var tg = v((FD, eg) => { + l(); + var { list: uA } = ge(), + Xm = Kn(), + fA = dt(), + Km = ai(), + Zm = class { + constructor(e) { + ((this.props = ["transition", "transition-property"]), (this.prefixes = e)); + } + add(e, t) { + let i, + n, + a = this.prefixes.add[e.prop], + s = this.ruleVendorPrefixes(e), + o = s || (a && a.prefixes) || [], + u = this.parse(e.value), + c = u.map((m) => this.findProp(m)), + f = []; + if (c.some((m) => m[0] === "-")) return; + for (let m of u) { + if (((n = this.findProp(m)), n[0] === "-")) continue; + let b = this.prefixes.add[n]; + if (!(!b || !b.prefixes)) + for (i of b.prefixes) { + if (s && !s.some((y) => i.includes(y))) continue; + let x = this.prefixes.prefixed(n, i); + x !== "-ms-transform" && + !c.includes(x) && + (this.disabled(n, i) || f.push(this.clone(n, x, m))); + } + } + u = u.concat(f); + let d = this.stringify(u), + p = this.stringify(this.cleanFromUnprefixed(u, "-webkit-")); + if ( + (o.includes("-webkit-") && this.cloneBefore(e, `-webkit-${e.prop}`, p), + this.cloneBefore(e, e.prop, p), + o.includes("-o-")) + ) { + let m = this.stringify(this.cleanFromUnprefixed(u, "-o-")); + this.cloneBefore(e, `-o-${e.prop}`, m); + } + for (i of o) + if (i !== "-webkit-" && i !== "-o-") { + let m = this.stringify(this.cleanOtherPrefixes(u, i)); + this.cloneBefore(e, i + e.prop, m); + } + d !== e.value && + !this.already(e, e.prop, d) && + (this.checkForWarning(t, e), e.cloneBefore(), (e.value = d)); + } + findProp(e) { + let t = e[0].value; + if (/^\d/.test(t)) { + for (let [i, n] of e.entries()) if (i !== 0 && n.type === "word") return n.value; + } + return t; + } + already(e, t, i) { + return e.parent.some((n) => n.prop === t && n.value === i); + } + cloneBefore(e, t, i) { + this.already(e, t, i) || e.cloneBefore({ prop: t, value: i }); + } + checkForWarning(e, t) { + if (t.prop !== "transition-property") return; + let i = !1, + n = !1; + (t.parent.each((a) => { + if (a.type !== "decl" || a.prop.indexOf("transition-") !== 0) return; + let s = uA.comma(a.value); + if (a.prop === "transition-property") { + s.forEach((o) => { + let u = this.prefixes.add[o]; + u && u.prefixes && u.prefixes.length > 0 && (i = !0); + }); + return; + } + return ((n = n || s.length > 1), !1); + }), + i && + n && + t.warn( + e, + "Replace transition-property to transition, because Autoprefixer could not support any cases of transition-property and other transition-*" + )); + } + remove(e) { + let t = this.parse(e.value); + t = t.filter((s) => { + let o = this.prefixes.remove[this.findProp(s)]; + return !o || !o.remove; + }); + let i = this.stringify(t); + if (e.value === i) return; + if (t.length === 0) { + e.remove(); + return; + } + let n = e.parent.some((s) => s.prop === e.prop && s.value === i), + a = e.parent.some((s) => s !== e && s.prop === e.prop && s.value.length > i.length); + if (n || a) { + e.remove(); + return; + } + e.value = i; + } + parse(e) { + let t = Xm(e), + i = [], + n = []; + for (let a of t.nodes) (n.push(a), a.type === "div" && a.value === "," && (i.push(n), (n = []))); + return (i.push(n), i.filter((a) => a.length > 0)); + } + stringify(e) { + if (e.length === 0) return ""; + let t = []; + for (let i of e) (i[i.length - 1].type !== "div" && i.push(this.div(e)), (t = t.concat(i))); + return ( + t[0].type === "div" && (t = t.slice(1)), + t[t.length - 1].type === "div" && (t = t.slice(0, -2 + 1 || void 0)), + Xm.stringify({ nodes: t }) + ); + } + clone(e, t, i) { + let n = [], + a = !1; + for (let s of i) + !a && s.type === "word" && s.value === e + ? (n.push({ type: "word", value: t }), (a = !0)) + : n.push(s); + return n; + } + div(e) { + for (let t of e) for (let i of t) if (i.type === "div" && i.value === ",") return i; + return { type: "div", value: ",", after: " " }; + } + cleanOtherPrefixes(e, t) { + return e.filter((i) => { + let n = Km.prefix(this.findProp(i)); + return n === "" || n === t; + }); + } + cleanFromUnprefixed(e, t) { + let i = e + .map((a) => this.findProp(a)) + .filter((a) => a.slice(0, t.length) === t) + .map((a) => this.prefixes.unprefixed(a)), + n = []; + for (let a of e) { + let s = this.findProp(a), + o = Km.prefix(s); + !i.includes(s) && (o === t || o === "") && n.push(a); + } + return n; + } + disabled(e, t) { + let i = ["order", "justify-content", "align-self", "align-content"]; + if (e.includes("flex") || i.includes(e)) { + if (this.prefixes.options.flexbox === !1) return !0; + if (this.prefixes.options.flexbox === "no-2009") return t.includes("2009"); + } + } + ruleVendorPrefixes(e) { + let { parent: t } = e; + if (t.type !== "rule") return !1; + if (!t.selector.includes(":-")) return !1; + let i = fA.prefixes().filter((n) => t.selector.includes(":" + n)); + return i.length > 0 ? i : !1; + } + }; + eg.exports = Zm; + }); + var Qt = v((LD, ig) => { + l(); + var cA = le(), + rg = class { + constructor(e, t, i, n) { + ((this.unprefixed = e), + (this.prefixed = t), + (this.string = i || t), + (this.regexp = n || cA.regexp(t))); + } + check(e) { + return e.includes(this.string) ? !!e.match(this.regexp) : !1; + } + }; + ig.exports = rg; + }); + var ke = v((ND, sg) => { + l(); + var pA = Ht(), + dA = Qt(), + hA = ai(), + mA = le(), + ng = class extends pA { + static save(e, t) { + let i = t.prop, + n = []; + for (let a in t._autoprefixerValues) { + let s = t._autoprefixerValues[a]; + if (s === t.value) continue; + let o, + u = hA.prefix(i); + if (u === "-pie-") continue; + if (u === a) { + ((o = t.value = s), n.push(o)); + continue; + } + let c = e.prefixed(i, a), + f = t.parent; + if (!f.every((b) => b.prop !== c)) { + n.push(o); + continue; + } + let d = s.replace(/\s+/, " "); + if (f.some((b) => b.prop === t.prop && b.value.replace(/\s+/, " ") === d)) { + n.push(o); + continue; + } + let m = this.clone(t, { value: s }); + ((o = t.parent.insertBefore(t, m)), n.push(o)); + } + return n; + } + check(e) { + let t = e.value; + return t.includes(this.name) ? !!t.match(this.regexp()) : !1; + } + regexp() { + return this.regexpCache || (this.regexpCache = mA.regexp(this.name)); + } + replace(e, t) { + return e.replace(this.regexp(), `$1${t}$2`); + } + value(e) { + return e.raws.value && e.raws.value.value === e.value ? e.raws.value.raw : e.value; + } + add(e, t) { + e._autoprefixerValues || (e._autoprefixerValues = {}); + let i = e._autoprefixerValues[t] || this.value(e), + n; + do if (((n = i), (i = this.replace(i, t)), i === !1)) return; + while (i !== n); + e._autoprefixerValues[t] = i; + } + old(e) { + return new dA(this.name, e + this.name); + } + }; + sg.exports = ng; + }); + var mt = v(($D, ag) => { + l(); + ag.exports = {}; + }); + var sl = v((zD, ug) => { + l(); + var og = Kn(), + gA = ke(), + yA = mt().insertAreas, + wA = /(^|[^-])linear-gradient\(\s*(top|left|right|bottom)/i, + bA = /(^|[^-])radial-gradient\(\s*\d+(\w*|%)\s+\d+(\w*|%)\s*,/i, + vA = /(!\s*)?autoprefixer:\s*ignore\s+next/i, + xA = /(!\s*)?autoprefixer\s*grid:\s*(on|off|(no-)?autoplace)/i, + kA = [ + "width", + "height", + "min-width", + "max-width", + "min-height", + "max-height", + "inline-size", + "min-inline-size", + "max-inline-size", + "block-size", + "min-block-size", + "max-block-size", + ]; + function nl(r) { + return r.parent.some((e) => e.prop === "grid-template" || e.prop === "grid-template-areas"); + } + function SA(r) { + let e = r.parent.some((i) => i.prop === "grid-template-rows"), + t = r.parent.some((i) => i.prop === "grid-template-columns"); + return e && t; + } + var lg = class { + constructor(e) { + this.prefixes = e; + } + add(e, t) { + let i = this.prefixes.add["@resolution"], + n = this.prefixes.add["@keyframes"], + a = this.prefixes.add["@viewport"], + s = this.prefixes.add["@supports"]; + (e.walkAtRules((f) => { + if (f.name === "keyframes") { + if (!this.disabled(f, t)) return n && n.process(f); + } else if (f.name === "viewport") { + if (!this.disabled(f, t)) return a && a.process(f); + } else if (f.name === "supports") { + if (this.prefixes.options.supports !== !1 && !this.disabled(f, t)) return s.process(f); + } else if (f.name === "media" && f.params.includes("-resolution") && !this.disabled(f, t)) + return i && i.process(f); + }), + e.walkRules((f) => { + if (!this.disabled(f, t)) return this.prefixes.add.selectors.map((d) => d.process(f, t)); + })); + function o(f) { + return f.parent.nodes.some((d) => { + if (d.type !== "decl") return !1; + let p = d.prop === "display" && /(inline-)?grid/.test(d.value), + m = d.prop.startsWith("grid-template"), + b = /^grid-([A-z]+-)?gap/.test(d.prop); + return p || m || b; + }); + } + function u(f) { + return f.parent.some((d) => d.prop === "display" && /(inline-)?flex/.test(d.value)); + } + let c = + this.gridStatus(e, t) && this.prefixes.add["grid-area"] && this.prefixes.add["grid-area"].prefixes; + return ( + e.walkDecls((f) => { + if (this.disabledDecl(f, t)) return; + let d = f.parent, + p = f.prop, + m = f.value; + if (p === "grid-row-span") { + t.warn("grid-row-span is not part of final Grid Layout. Use grid-row.", { node: f }); + return; + } else if (p === "grid-column-span") { + t.warn("grid-column-span is not part of final Grid Layout. Use grid-column.", { node: f }); + return; + } else if (p === "display" && m === "box") { + t.warn("You should write display: flex by final spec instead of display: box", { node: f }); + return; + } else if (p === "text-emphasis-position") + (m === "under" || m === "over") && + t.warn( + "You should use 2 values for text-emphasis-position For example, `under left` instead of just `under`.", + { node: f } + ); + else if (/^(align|justify|place)-(items|content)$/.test(p) && u(f)) + (m === "start" || m === "end") && + t.warn(`${m} value has mixed support, consider using flex-${m} instead`, { node: f }); + else if (p === "text-decoration-skip" && m === "ink") + t.warn( + "Replace text-decoration-skip: ink to text-decoration-skip-ink: auto, because spec had been changed", + { node: f } + ); + else { + if (c && this.gridStatus(f, t)) + if ( + (f.value === "subgrid" && t.warn("IE does not support subgrid", { node: f }), + /^(align|justify|place)-items$/.test(p) && o(f)) + ) { + let x = p.replace("-items", "-self"); + t.warn( + `IE does not support ${p} on grid containers. Try using ${x} on child elements instead: ${f.parent.selector} > * { ${x}: ${f.value} }`, + { node: f } + ); + } else if (/^(align|justify|place)-content$/.test(p) && o(f)) + t.warn(`IE does not support ${f.prop} on grid containers`, { node: f }); + else if (p === "display" && f.value === "contents") { + t.warn("Please do not use display: contents; if you have grid setting enabled", { + node: f, + }); + return; + } else if (f.prop === "grid-gap") { + let x = this.gridStatus(f, t); + x === "autoplace" && !SA(f) && !nl(f) + ? t.warn( + "grid-gap only works if grid-template(-areas) is being used or both rows and columns have been declared and cells have not been manually placed inside the explicit grid", + { node: f } + ) + : (x === !0 || x === "no-autoplace") && + !nl(f) && + t.warn("grid-gap only works if grid-template(-areas) is being used", { + node: f, + }); + } else if (p === "grid-auto-columns") { + t.warn("grid-auto-columns is not supported by IE", { node: f }); + return; + } else if (p === "grid-auto-rows") { + t.warn("grid-auto-rows is not supported by IE", { node: f }); + return; + } else if (p === "grid-auto-flow") { + let x = d.some((w) => w.prop === "grid-template-rows"), + y = d.some((w) => w.prop === "grid-template-columns"); + nl(f) + ? t.warn("grid-auto-flow is not supported by IE", { node: f }) + : m.includes("dense") + ? t.warn("grid-auto-flow: dense is not supported by IE", { node: f }) + : !x && + !y && + t.warn( + "grid-auto-flow works only if grid-template-rows and grid-template-columns are present in the same rule", + { node: f } + ); + return; + } else if (m.includes("auto-fit")) { + t.warn("auto-fit value is not supported by IE", { node: f, word: "auto-fit" }); + return; + } else if (m.includes("auto-fill")) { + t.warn("auto-fill value is not supported by IE", { node: f, word: "auto-fill" }); + return; + } else + p.startsWith("grid-template") && + m.includes("[") && + t.warn( + "Autoprefixer currently does not support line names. Try using grid-template-areas instead.", + { node: f, word: "[" } + ); + if (m.includes("radial-gradient")) + if (bA.test(f.value)) + t.warn( + "Gradient has outdated direction syntax. New syntax is like `closest-side at 0 0` instead of `0 0, closest-side`.", + { node: f } + ); + else { + let x = og(m); + for (let y of x.nodes) + if (y.type === "function" && y.value === "radial-gradient") + for (let w of y.nodes) + w.type === "word" && + (w.value === "cover" + ? t.warn( + "Gradient has outdated direction syntax. Replace `cover` to `farthest-corner`.", + { node: f } + ) + : w.value === "contain" && + t.warn( + "Gradient has outdated direction syntax. Replace `contain` to `closest-side`.", + { node: f } + )); + } + m.includes("linear-gradient") && + wA.test(m) && + t.warn( + "Gradient has outdated direction syntax. New syntax is like `to left` instead of `right`.", + { node: f } + ); + } + kA.includes(f.prop) && + (f.value.includes("-fill-available") || + (f.value.includes("fill-available") + ? t.warn("Replace fill-available to stretch, because spec had been changed", { + node: f, + }) + : f.value.includes("fill") && + og(m).nodes.some((y) => y.type === "word" && y.value === "fill") && + t.warn("Replace fill to stretch, because spec had been changed", { node: f }))); + let b; + if (f.prop === "transition" || f.prop === "transition-property") + return this.prefixes.transition.add(f, t); + if (f.prop === "align-self") { + if ( + (this.displayType(f) !== "grid" && + this.prefixes.options.flexbox !== !1 && + ((b = this.prefixes.add["align-self"]), b && b.prefixes && b.process(f)), + this.gridStatus(f, t) !== !1 && + ((b = this.prefixes.add["grid-row-align"]), b && b.prefixes)) + ) + return b.process(f, t); + } else if (f.prop === "justify-self") { + if ( + this.gridStatus(f, t) !== !1 && + ((b = this.prefixes.add["grid-column-align"]), b && b.prefixes) + ) + return b.process(f, t); + } else if (f.prop === "place-self") { + if ( + ((b = this.prefixes.add["place-self"]), b && b.prefixes && this.gridStatus(f, t) !== !1) + ) + return b.process(f, t); + } else if (((b = this.prefixes.add[f.prop]), b && b.prefixes)) return b.process(f, t); + }), + this.gridStatus(e, t) && yA(e, this.disabled), + e.walkDecls((f) => { + if (this.disabledValue(f, t)) return; + let d = this.prefixes.unprefixed(f.prop), + p = this.prefixes.values("add", d); + if (Array.isArray(p)) for (let m of p) m.process && m.process(f, t); + gA.save(this.prefixes, f); + }) + ); + } + remove(e, t) { + let i = this.prefixes.remove["@resolution"]; + e.walkAtRules((n, a) => { + this.prefixes.remove[`@${n.name}`] + ? this.disabled(n, t) || n.parent.removeChild(a) + : n.name === "media" && n.params.includes("-resolution") && i && i.clean(n); + }); + for (let n of this.prefixes.remove.selectors) + e.walkRules((a, s) => { + n.check(a) && (this.disabled(a, t) || a.parent.removeChild(s)); + }); + return e.walkDecls((n, a) => { + if (this.disabled(n, t)) return; + let s = n.parent, + o = this.prefixes.unprefixed(n.prop); + if ( + ((n.prop === "transition" || n.prop === "transition-property") && + this.prefixes.transition.remove(n), + this.prefixes.remove[n.prop] && this.prefixes.remove[n.prop].remove) + ) { + let u = this.prefixes.group(n).down((c) => this.prefixes.normalize(c.prop) === o); + if ((o === "flex-flow" && (u = !0), n.prop === "-webkit-box-orient")) { + let c = { "flex-direction": !0, "flex-flow": !0 }; + if (!n.parent.some((f) => c[f.prop])) return; + } + if (u && !this.withHackValue(n)) { + (n.raw("before").includes(` +`) && this.reduceSpaces(n), + s.removeChild(a)); + return; + } + } + for (let u of this.prefixes.values("remove", o)) { + if (!u.check || !u.check(n.value)) continue; + if (((o = u.unprefixed), this.prefixes.group(n).down((f) => f.value.includes(o)))) { + s.removeChild(a); + return; + } + } + }); + } + withHackValue(e) { + return e.prop === "-webkit-background-clip" && e.value === "text"; + } + disabledValue(e, t) { + return (this.gridStatus(e, t) === !1 && + e.type === "decl" && + e.prop === "display" && + e.value.includes("grid")) || + (this.prefixes.options.flexbox === !1 && + e.type === "decl" && + e.prop === "display" && + e.value.includes("flex")) || + (e.type === "decl" && e.prop === "content") + ? !0 + : this.disabled(e, t); + } + disabledDecl(e, t) { + if ( + this.gridStatus(e, t) === !1 && + e.type === "decl" && + (e.prop.includes("grid") || e.prop === "justify-items") + ) + return !0; + if (this.prefixes.options.flexbox === !1 && e.type === "decl") { + let i = ["order", "justify-content", "align-items", "align-content"]; + if (e.prop.includes("flex") || i.includes(e.prop)) return !0; + } + return this.disabled(e, t); + } + disabled(e, t) { + if (!e) return !1; + if (e._autoprefixerDisabled !== void 0) return e._autoprefixerDisabled; + if (e.parent) { + let n = e.prev(); + if (n && n.type === "comment" && vA.test(n.text)) + return ((e._autoprefixerDisabled = !0), (e._autoprefixerSelfDisabled = !0), !0); + } + let i = null; + if (e.nodes) { + let n; + (e.each((a) => { + a.type === "comment" && + /(!\s*)?autoprefixer:\s*(off|on)/i.test(a.text) && + (typeof n != "undefined" + ? t.warn( + "Second Autoprefixer control comment was ignored. Autoprefixer applies control comment to whole block, not to next rules.", + { node: a } + ) + : (n = /on/i.test(a.text))); + }), + n !== void 0 && (i = !n)); + } + if (!e.nodes || i === null) + if (e.parent) { + let n = this.disabled(e.parent, t); + e.parent._autoprefixerSelfDisabled === !0 ? (i = !1) : (i = n); + } else i = !1; + return ((e._autoprefixerDisabled = i), i); + } + reduceSpaces(e) { + let t = !1; + if ((this.prefixes.group(e).up(() => ((t = !0), !0)), t)) return; + let i = e.raw("before").split(` +`), + n = i[i.length - 1].length, + a = !1; + this.prefixes.group(e).down((s) => { + i = s.raw("before").split(` +`); + let o = i.length - 1; + i[o].length > n && + (a === !1 && (a = i[o].length - n), + (i[o] = i[o].slice(0, -a)), + (s.raws.before = i.join(` +`))); + }); + } + displayType(e) { + for (let t of e.parent.nodes) + if (t.prop === "display") { + if (t.value.includes("flex")) return "flex"; + if (t.value.includes("grid")) return "grid"; + } + return !1; + } + gridStatus(e, t) { + if (!e) return !1; + if (e._autoprefixerGridStatus !== void 0) return e._autoprefixerGridStatus; + let i = null; + if (e.nodes) { + let n; + (e.each((a) => { + if (a.type === "comment" && xA.test(a.text)) { + let s = /:\s*autoplace/i.test(a.text), + o = /no-autoplace/i.test(a.text); + typeof n != "undefined" + ? t.warn( + "Second Autoprefixer grid control comment was ignored. Autoprefixer applies control comments to the whole block, not to the next rules.", + { node: a } + ) + : s + ? (n = "autoplace") + : o + ? (n = !0) + : (n = /on/i.test(a.text)); + } + }), + n !== void 0 && (i = n)); + } + if (e.type === "atrule" && e.name === "supports") { + let n = e.params; + n.includes("grid") && n.includes("auto") && (i = !1); + } + if (!e.nodes || i === null) + if (e.parent) { + let n = this.gridStatus(e.parent, t); + e.parent._autoprefixerSelfDisabled === !0 ? (i = !1) : (i = n); + } else + typeof this.prefixes.options.grid != "undefined" + ? (i = this.prefixes.options.grid) + : typeof h.env.AUTOPREFIXER_GRID != "undefined" + ? h.env.AUTOPREFIXER_GRID === "autoplace" + ? (i = "autoplace") + : (i = !0) + : (i = !1); + return ((e._autoprefixerGridStatus = i), i); + } + }; + ug.exports = lg; + }); + var cg = v((jD, fg) => { + l(); + fg.exports = { + A: { + A: { 2: "K E F G A B JC" }, + B: { 1: "C L M H N D O P Q R S T U V W X Y Z a b c d e f g h i j n o p q r s t u v w x y z I" }, + C: { + 1: "2 3 4 5 6 7 8 9 AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB PB QB RB SB TB UB VB WB XB YB ZB aB bB cB 0B dB 1B eB fB gB hB iB jB kB lB mB nB oB m pB qB rB sB tB P Q R 2B S T U V W X Y Z a b c d e f g h i j n o p q r s t u v w x y z I uB 3B 4B", + 2: "0 1 KC zB J K E F G A B C L M H N D O k l LC MC", + }, + D: { + 1: "8 9 AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB PB QB RB SB TB UB VB WB XB YB ZB aB bB cB 0B dB 1B eB fB gB hB iB jB kB lB mB nB oB m pB qB rB sB tB P Q R S T U V W X Y Z a b c d e f g h i j n o p q r s t u v w x y z I uB 3B 4B", + 2: "0 1 2 3 4 5 6 7 J K E F G A B C L M H N D O k l", + }, + E: { + 1: "G A B C L M H D RC 6B vB wB 7B SC TC 8B 9B xB AC yB BC CC DC EC FC GC UC", + 2: "0 J K E F NC 5B OC PC QC", + }, + F: { + 1: "1 2 3 4 5 6 7 8 9 H N D O k l AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB PB QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB m pB qB rB sB tB P Q R 2B S T U V W X Y Z a b c d e f g h i j wB", + 2: "G B C VC WC XC YC vB HC ZC", + }, + G: { + 1: "D fC gC hC iC jC kC lC mC nC oC pC qC rC sC tC 8B 9B xB AC yB BC CC DC EC FC GC", + 2: "F 5B aC IC bC cC dC eC", + }, + H: { 1: "uC" }, + I: { 1: "I zC 0C", 2: "zB J vC wC xC yC IC" }, + J: { 2: "E A" }, + K: { 1: "m", 2: "A B C vB HC wB" }, + L: { 1: "I" }, + M: { 1: "uB" }, + N: { 2: "A B" }, + O: { 1: "xB" }, + P: { 1: "J k l 1C 2C 3C 4C 5C 6B 6C 7C 8C 9C AD yB BD CD DD" }, + Q: { 1: "7B" }, + R: { 1: "ED" }, + S: { 1: "FD GD" }, + }, + B: 4, + C: "CSS Feature Queries", + }; + }); + var mg = v((VD, hg) => { + l(); + function pg(r) { + return r[r.length - 1]; + } + var dg = { + parse(r) { + let e = [""], + t = [e]; + for (let i of r) { + if (i === "(") { + ((e = [""]), pg(t).push(e), t.push(e)); + continue; + } + if (i === ")") { + (t.pop(), (e = pg(t)), e.push("")); + continue; + } + e[e.length - 1] += i; + } + return t[0]; + }, + stringify(r) { + let e = ""; + for (let t of r) { + if (typeof t == "object") { + e += `(${dg.stringify(t)})`; + continue; + } + e += t; + } + return e; + }, + }; + hg.exports = dg; + }); + var vg = v((UD, bg) => { + l(); + var CA = cg(), + { feature: AA } = (Gn(), Wn), + { parse: _A } = ge(), + OA = dt(), + al = mg(), + EA = ke(), + TA = le(), + gg = AA(CA), + yg = []; + for (let r in gg.stats) { + let e = gg.stats[r]; + for (let t in e) { + let i = e[t]; + /y/.test(i) && yg.push(r + " " + t); + } + } + var wg = class { + constructor(e, t) { + ((this.Prefixes = e), (this.all = t)); + } + prefixer() { + if (this.prefixerCache) return this.prefixerCache; + let e = this.all.browsers.selected.filter((i) => yg.includes(i)), + t = new OA(this.all.browsers.data, e, this.all.options); + return ( + (this.prefixerCache = new this.Prefixes(this.all.data, t, this.all.options)), + this.prefixerCache + ); + } + parse(e) { + let t = e.split(":"), + i = t[0], + n = t[1]; + return (n || (n = ""), [i.trim(), n.trim()]); + } + virtual(e) { + let [t, i] = this.parse(e), + n = _A("a{}").first; + return (n.append({ prop: t, value: i, raws: { before: "" } }), n); + } + prefixed(e) { + let t = this.virtual(e); + if (this.disabled(t.first)) return t.nodes; + let i = { warn: () => null }, + n = this.prefixer().add[t.first.prop]; + n && n.process && n.process(t.first, i); + for (let a of t.nodes) { + for (let s of this.prefixer().values("add", t.first.prop)) s.process(a); + EA.save(this.all, a); + } + return t.nodes; + } + isNot(e) { + return typeof e == "string" && /not\s*/i.test(e); + } + isOr(e) { + return typeof e == "string" && /\s*or\s*/i.test(e); + } + isProp(e) { + return typeof e == "object" && e.length === 1 && typeof e[0] == "string"; + } + isHack(e, t) { + return !new RegExp(`(\\(|\\s)${TA.escapeRegexp(t)}:`).test(e); + } + toRemove(e, t) { + let [i, n] = this.parse(e), + a = this.all.unprefixed(i), + s = this.all.cleaner(); + if (s.remove[i] && s.remove[i].remove && !this.isHack(t, a)) return !0; + for (let o of s.values("remove", a)) if (o.check(n)) return !0; + return !1; + } + remove(e, t) { + let i = 0; + for (; i < e.length; ) { + if (!this.isNot(e[i - 1]) && this.isProp(e[i]) && this.isOr(e[i + 1])) { + if (this.toRemove(e[i][0], t)) { + e.splice(i, 2); + continue; + } + i += 2; + continue; + } + (typeof e[i] == "object" && (e[i] = this.remove(e[i], t)), (i += 1)); + } + return e; + } + cleanBrackets(e) { + return e.map((t) => + typeof t != "object" + ? t + : t.length === 1 && typeof t[0] == "object" + ? this.cleanBrackets(t[0]) + : this.cleanBrackets(t) + ); + } + convert(e) { + let t = [""]; + for (let i of e) (t.push([`${i.prop}: ${i.value}`]), t.push(" or ")); + return ((t[t.length - 1] = ""), t); + } + normalize(e) { + if (typeof e != "object") return e; + if (((e = e.filter((t) => t !== "")), typeof e[0] == "string")) { + let t = e[0].trim(); + if (t.includes(":") || t === "selector" || t === "not selector") return [al.stringify(e)]; + } + return e.map((t) => this.normalize(t)); + } + add(e, t) { + return e.map((i) => { + if (this.isProp(i)) { + let n = this.prefixed(i[0]); + return n.length > 1 ? this.convert(n) : i; + } + return typeof i == "object" ? this.add(i, t) : i; + }); + } + process(e) { + let t = al.parse(e.params); + ((t = this.normalize(t)), + (t = this.remove(t, e.params)), + (t = this.add(t, e.params)), + (t = this.cleanBrackets(t)), + (e.params = al.stringify(t))); + } + disabled(e) { + if ( + !this.all.options.grid && + ((e.prop === "display" && e.value.includes("grid")) || + e.prop.includes("grid") || + e.prop === "justify-items") + ) + return !0; + if (this.all.options.flexbox === !1) { + if (e.prop === "display" && e.value.includes("flex")) return !0; + let t = ["order", "justify-content", "align-items", "align-content"]; + if (e.prop.includes("flex") || t.includes(e.prop)) return !0; + } + return !1; + } + }; + bg.exports = wg; + }); + var Sg = v((WD, kg) => { + l(); + var xg = class { + constructor(e, t) { + ((this.prefix = t), + (this.prefixed = e.prefixed(this.prefix)), + (this.regexp = e.regexp(this.prefix)), + (this.prefixeds = e.possible().map((i) => [e.prefixed(i), e.regexp(i)])), + (this.unprefixed = e.name), + (this.nameRegexp = e.regexp())); + } + isHack(e) { + let t = e.parent.index(e) + 1, + i = e.parent.nodes; + for (; t < i.length; ) { + let n = i[t].selector; + if (!n) return !0; + if (n.includes(this.unprefixed) && n.match(this.nameRegexp)) return !1; + let a = !1; + for (let [s, o] of this.prefixeds) + if (n.includes(s) && n.match(o)) { + a = !0; + break; + } + if (!a) return !0; + t += 1; + } + return !0; + } + check(e) { + return !(!e.selector.includes(this.prefixed) || !e.selector.match(this.regexp) || this.isHack(e)); + } + }; + kg.exports = xg; + }); + var Jt = v((GD, Ag) => { + l(); + var { list: PA } = ge(), + DA = Sg(), + IA = Ht(), + qA = dt(), + RA = le(), + Cg = class extends IA { + constructor(e, t, i) { + super(e, t, i); + this.regexpCache = new Map(); + } + check(e) { + return e.selector.includes(this.name) ? !!e.selector.match(this.regexp()) : !1; + } + prefixed(e) { + return this.name.replace(/^(\W*)/, `$1${e}`); + } + regexp(e) { + if (!this.regexpCache.has(e)) { + let t = e ? this.prefixed(e) : this.name; + this.regexpCache.set(e, new RegExp(`(^|[^:"'=])${RA.escapeRegexp(t)}`, "gi")); + } + return this.regexpCache.get(e); + } + possible() { + return qA.prefixes(); + } + prefixeds(e) { + if (e._autoprefixerPrefixeds) { + if (e._autoprefixerPrefixeds[this.name]) return e._autoprefixerPrefixeds; + } else e._autoprefixerPrefixeds = {}; + let t = {}; + if (e.selector.includes(",")) { + let n = PA.comma(e.selector).filter((a) => a.includes(this.name)); + for (let a of this.possible()) t[a] = n.map((s) => this.replace(s, a)).join(", "); + } else for (let i of this.possible()) t[i] = this.replace(e.selector, i); + return ((e._autoprefixerPrefixeds[this.name] = t), e._autoprefixerPrefixeds); + } + already(e, t, i) { + let n = e.parent.index(e) - 1; + for (; n >= 0; ) { + let a = e.parent.nodes[n]; + if (a.type !== "rule") return !1; + let s = !1; + for (let o in t[this.name]) { + let u = t[this.name][o]; + if (a.selector === u) { + if (i === o) return !0; + s = !0; + break; + } + } + if (!s) return !1; + n -= 1; + } + return !1; + } + replace(e, t) { + return e.replace(this.regexp(), `$1${this.prefixed(t)}`); + } + add(e, t) { + let i = this.prefixeds(e); + if (this.already(e, i, t)) return; + let n = this.clone(e, { selector: i[this.name][t] }); + e.parent.insertBefore(e, n); + } + old(e) { + return new DA(this, e); + } + }; + Ag.exports = Cg; + }); + var Eg = v((HD, Og) => { + l(); + var MA = Ht(), + _g = class extends MA { + add(e, t) { + let i = t + e.name; + if (e.parent.some((s) => s.name === i && s.params === e.params)) return; + let a = this.clone(e, { name: i }); + return e.parent.insertBefore(e, a); + } + process(e) { + let t = this.parentPrefix(e); + for (let i of this.prefixes) (!t || t === i) && this.add(e, i); + } + }; + Og.exports = _g; + }); + var Pg = v((YD, Tg) => { + l(); + var BA = Jt(), + ol = class extends BA { + prefixed(e) { + return e === "-webkit-" + ? ":-webkit-full-screen" + : e === "-moz-" + ? ":-moz-full-screen" + : `:${e}fullscreen`; + } + }; + ol.names = [":fullscreen"]; + Tg.exports = ol; + }); + var Ig = v((QD, Dg) => { + l(); + var FA = Jt(), + ll = class extends FA { + possible() { + return super.possible().concat(["-moz- old", "-ms- old"]); + } + prefixed(e) { + return e === "-webkit-" + ? "::-webkit-input-placeholder" + : e === "-ms-" + ? "::-ms-input-placeholder" + : e === "-ms- old" + ? ":-ms-input-placeholder" + : e === "-moz- old" + ? ":-moz-placeholder" + : `::${e}placeholder`; + } + }; + ll.names = ["::placeholder"]; + Dg.exports = ll; + }); + var Rg = v((JD, qg) => { + l(); + var LA = Jt(), + ul = class extends LA { + prefixed(e) { + return e === "-ms-" ? ":-ms-input-placeholder" : `:${e}placeholder-shown`; + } + }; + ul.names = [":placeholder-shown"]; + qg.exports = ul; + }); + var Bg = v((XD, Mg) => { + l(); + var NA = Jt(), + $A = le(), + fl = class extends NA { + constructor(e, t, i) { + super(e, t, i); + this.prefixes && (this.prefixes = $A.uniq(this.prefixes.map((n) => "-webkit-"))); + } + prefixed(e) { + return e === "-webkit-" ? "::-webkit-file-upload-button" : `::${e}file-selector-button`; + } + }; + fl.names = ["::file-selector-button"]; + Mg.exports = fl; + }); + var pe = v((KD, Fg) => { + l(); + Fg.exports = function (r) { + let e; + return ( + r === "-webkit- 2009" || r === "-moz-" + ? (e = 2009) + : r === "-ms-" + ? (e = 2012) + : r === "-webkit-" && (e = "final"), + r === "-webkit- 2009" && (r = "-webkit-"), + [e, r] + ); + }; + }); + var zg = v((ZD, $g) => { + l(); + var Lg = ge().list, + Ng = pe(), + zA = M(), + Xt = class extends zA { + prefixed(e, t) { + let i; + return (([i, t] = Ng(t)), i === 2009 ? t + "box-flex" : super.prefixed(e, t)); + } + normalize() { + return "flex"; + } + set(e, t) { + let i = Ng(t)[0]; + if (i === 2009) + return ( + (e.value = Lg.space(e.value)[0]), + (e.value = Xt.oldValues[e.value] || e.value), + super.set(e, t) + ); + if (i === 2012) { + let n = Lg.space(e.value); + n.length === 3 && n[2] === "0" && (e.value = n.slice(0, 2).concat("0px").join(" ")); + } + return super.set(e, t); + } + }; + Xt.names = ["flex", "box-flex"]; + Xt.oldValues = { auto: "1", none: "0" }; + $g.exports = Xt; + }); + var Ug = v((eI, Vg) => { + l(); + var jg = pe(), + jA = M(), + cl = class extends jA { + prefixed(e, t) { + let i; + return ( + ([i, t] = jg(t)), + i === 2009 ? t + "box-ordinal-group" : i === 2012 ? t + "flex-order" : super.prefixed(e, t) + ); + } + normalize() { + return "order"; + } + set(e, t) { + return jg(t)[0] === 2009 && /\d/.test(e.value) + ? ((e.value = (parseInt(e.value) + 1).toString()), super.set(e, t)) + : super.set(e, t); + } + }; + cl.names = ["order", "flex-order", "box-ordinal-group"]; + Vg.exports = cl; + }); + var Gg = v((tI, Wg) => { + l(); + var VA = M(), + pl = class extends VA { + check(e) { + let t = e.value; + return ( + !t.toLowerCase().includes("alpha(") && + !t.includes("DXImageTransform.Microsoft") && + !t.includes("data:image/svg+xml") + ); + } + }; + pl.names = ["filter"]; + Wg.exports = pl; + }); + var Yg = v((rI, Hg) => { + l(); + var UA = M(), + dl = class extends UA { + insert(e, t, i, n) { + if (t !== "-ms-") return super.insert(e, t, i); + let a = this.clone(e), + s = e.prop.replace(/end$/, "start"), + o = t + e.prop.replace(/end$/, "span"); + if (!e.parent.some((u) => u.prop === o)) { + if (((a.prop = o), e.value.includes("span"))) a.value = e.value.replace(/span\s/i, ""); + else { + let u; + if ( + (e.parent.walkDecls(s, (c) => { + u = c; + }), + u) + ) { + let c = Number(e.value) - Number(u.value) + ""; + a.value = c; + } else e.warn(n, `Can not prefix ${e.prop} (${s} is not found)`); + } + e.cloneBefore(a); + } + } + }; + dl.names = ["grid-row-end", "grid-column-end"]; + Hg.exports = dl; + }); + var Jg = v((iI, Qg) => { + l(); + var WA = M(), + hl = class extends WA { + check(e) { + return !e.value.split(/\s+/).some((t) => { + let i = t.toLowerCase(); + return i === "reverse" || i === "alternate-reverse"; + }); + } + }; + hl.names = ["animation", "animation-direction"]; + Qg.exports = hl; + }); + var Kg = v((nI, Xg) => { + l(); + var GA = pe(), + HA = M(), + ml = class extends HA { + insert(e, t, i) { + let n; + if ((([n, t] = GA(t)), n !== 2009)) return super.insert(e, t, i); + let a = e.value.split(/\s+/).filter((d) => d !== "wrap" && d !== "nowrap" && "wrap-reverse"); + if ( + a.length === 0 || + e.parent.some((d) => d.prop === t + "box-orient" || d.prop === t + "box-direction") + ) + return; + let o = a[0], + u = o.includes("row") ? "horizontal" : "vertical", + c = o.includes("reverse") ? "reverse" : "normal", + f = this.clone(e); + return ( + (f.prop = t + "box-orient"), + (f.value = u), + this.needCascade(e) && (f.raws.before = this.calcBefore(i, e, t)), + e.parent.insertBefore(e, f), + (f = this.clone(e)), + (f.prop = t + "box-direction"), + (f.value = c), + this.needCascade(e) && (f.raws.before = this.calcBefore(i, e, t)), + e.parent.insertBefore(e, f) + ); + } + }; + ml.names = ["flex-flow", "box-direction", "box-orient"]; + Xg.exports = ml; + }); + var ey = v((sI, Zg) => { + l(); + var YA = pe(), + QA = M(), + gl = class extends QA { + normalize() { + return "flex"; + } + prefixed(e, t) { + let i; + return ( + ([i, t] = YA(t)), + i === 2009 ? t + "box-flex" : i === 2012 ? t + "flex-positive" : super.prefixed(e, t) + ); + } + }; + gl.names = ["flex-grow", "flex-positive"]; + Zg.exports = gl; + }); + var ry = v((aI, ty) => { + l(); + var JA = pe(), + XA = M(), + yl = class extends XA { + set(e, t) { + if (JA(t)[0] !== 2009) return super.set(e, t); + } + }; + yl.names = ["flex-wrap"]; + ty.exports = yl; + }); + var ny = v((oI, iy) => { + l(); + var KA = M(), + Kt = mt(), + wl = class extends KA { + insert(e, t, i, n) { + if (t !== "-ms-") return super.insert(e, t, i); + let a = Kt.parse(e), + [s, o] = Kt.translate(a, 0, 2), + [u, c] = Kt.translate(a, 1, 3); + ([ + ["grid-row", s], + ["grid-row-span", o], + ["grid-column", u], + ["grid-column-span", c], + ].forEach(([f, d]) => { + Kt.insertDecl(e, f, d); + }), + Kt.warnTemplateSelectorNotFound(e, n), + Kt.warnIfGridRowColumnExists(e, n)); + } + }; + wl.names = ["grid-area"]; + iy.exports = wl; + }); + var ay = v((lI, sy) => { + l(); + var ZA = M(), + oi = mt(), + bl = class extends ZA { + insert(e, t, i) { + if (t !== "-ms-") return super.insert(e, t, i); + if (e.parent.some((s) => s.prop === "-ms-grid-row-align")) return; + let [[n, a]] = oi.parse(e); + a + ? (oi.insertDecl(e, "grid-row-align", n), oi.insertDecl(e, "grid-column-align", a)) + : (oi.insertDecl(e, "grid-row-align", n), oi.insertDecl(e, "grid-column-align", n)); + } + }; + bl.names = ["place-self"]; + sy.exports = bl; + }); + var ly = v((uI, oy) => { + l(); + var e5 = M(), + vl = class extends e5 { + check(e) { + let t = e.value; + return !t.includes("/") || t.includes("span"); + } + normalize(e) { + return e.replace("-start", ""); + } + prefixed(e, t) { + let i = super.prefixed(e, t); + return (t === "-ms-" && (i = i.replace("-start", "")), i); + } + }; + vl.names = ["grid-row-start", "grid-column-start"]; + oy.exports = vl; + }); + var cy = v((fI, fy) => { + l(); + var uy = pe(), + t5 = M(), + Zt = class extends t5 { + check(e) { + return e.parent && !e.parent.some((t) => t.prop && t.prop.startsWith("grid-")); + } + prefixed(e, t) { + let i; + return (([i, t] = uy(t)), i === 2012 ? t + "flex-item-align" : super.prefixed(e, t)); + } + normalize() { + return "align-self"; + } + set(e, t) { + let i = uy(t)[0]; + if (i === 2012) return ((e.value = Zt.oldValues[e.value] || e.value), super.set(e, t)); + if (i === "final") return super.set(e, t); + } + }; + Zt.names = ["align-self", "flex-item-align"]; + Zt.oldValues = { "flex-end": "end", "flex-start": "start" }; + fy.exports = Zt; + }); + var dy = v((cI, py) => { + l(); + var r5 = M(), + i5 = le(), + xl = class extends r5 { + constructor(e, t, i) { + super(e, t, i); + this.prefixes && + (this.prefixes = i5.uniq(this.prefixes.map((n) => (n === "-ms-" ? "-webkit-" : n)))); + } + }; + xl.names = ["appearance"]; + py.exports = xl; + }); + var gy = v((pI, my) => { + l(); + var hy = pe(), + n5 = M(), + kl = class extends n5 { + normalize() { + return "flex-basis"; + } + prefixed(e, t) { + let i; + return (([i, t] = hy(t)), i === 2012 ? t + "flex-preferred-size" : super.prefixed(e, t)); + } + set(e, t) { + let i; + if ((([i, t] = hy(t)), i === 2012 || i === "final")) return super.set(e, t); + } + }; + kl.names = ["flex-basis", "flex-preferred-size"]; + my.exports = kl; + }); + var wy = v((dI, yy) => { + l(); + var s5 = M(), + Sl = class extends s5 { + normalize() { + return this.name.replace("box-image", "border"); + } + prefixed(e, t) { + let i = super.prefixed(e, t); + return (t === "-webkit-" && (i = i.replace("border", "box-image")), i); + } + }; + Sl.names = [ + "mask-border", + "mask-border-source", + "mask-border-slice", + "mask-border-width", + "mask-border-outset", + "mask-border-repeat", + "mask-box-image", + "mask-box-image-source", + "mask-box-image-slice", + "mask-box-image-width", + "mask-box-image-outset", + "mask-box-image-repeat", + ]; + yy.exports = Sl; + }); + var vy = v((hI, by) => { + l(); + var a5 = M(), + Ne = class extends a5 { + insert(e, t, i) { + let n = e.prop === "mask-composite", + a; + (n ? (a = e.value.split(",")) : (a = e.value.match(Ne.regexp) || []), + (a = a.map((c) => c.trim()).filter((c) => c))); + let s = a.length, + o; + if ( + (s && + ((o = this.clone(e)), + (o.value = a.map((c) => Ne.oldValues[c] || c).join(", ")), + a.includes("intersect") && (o.value += ", xor"), + (o.prop = t + "mask-composite")), + n) + ) + return s + ? (this.needCascade(e) && (o.raws.before = this.calcBefore(i, e, t)), + e.parent.insertBefore(e, o)) + : void 0; + let u = this.clone(e); + return ( + (u.prop = t + u.prop), + s && (u.value = u.value.replace(Ne.regexp, "")), + this.needCascade(e) && (u.raws.before = this.calcBefore(i, e, t)), + e.parent.insertBefore(e, u), + s + ? (this.needCascade(e) && (o.raws.before = this.calcBefore(i, e, t)), + e.parent.insertBefore(e, o)) + : e + ); + } + }; + Ne.names = ["mask", "mask-composite"]; + Ne.oldValues = { add: "source-over", subtract: "source-out", intersect: "source-in", exclude: "xor" }; + Ne.regexp = new RegExp(`\\s+(${Object.keys(Ne.oldValues).join("|")})\\b(?!\\))\\s*(?=[,])`, "ig"); + by.exports = Ne; + }); + var Sy = v((mI, ky) => { + l(); + var xy = pe(), + o5 = M(), + er = class extends o5 { + prefixed(e, t) { + let i; + return ( + ([i, t] = xy(t)), + i === 2009 ? t + "box-align" : i === 2012 ? t + "flex-align" : super.prefixed(e, t) + ); + } + normalize() { + return "align-items"; + } + set(e, t) { + let i = xy(t)[0]; + return ( + (i === 2009 || i === 2012) && (e.value = er.oldValues[e.value] || e.value), + super.set(e, t) + ); + } + }; + er.names = ["align-items", "flex-align", "box-align"]; + er.oldValues = { "flex-end": "end", "flex-start": "start" }; + ky.exports = er; + }); + var Ay = v((gI, Cy) => { + l(); + var l5 = M(), + Cl = class extends l5 { + set(e, t) { + return (t === "-ms-" && e.value === "contain" && (e.value = "element"), super.set(e, t)); + } + insert(e, t, i) { + if (!(e.value === "all" && t === "-ms-")) return super.insert(e, t, i); + } + }; + Cl.names = ["user-select"]; + Cy.exports = Cl; + }); + var Ey = v((yI, Oy) => { + l(); + var _y = pe(), + u5 = M(), + Al = class extends u5 { + normalize() { + return "flex-shrink"; + } + prefixed(e, t) { + let i; + return (([i, t] = _y(t)), i === 2012 ? t + "flex-negative" : super.prefixed(e, t)); + } + set(e, t) { + let i; + if ((([i, t] = _y(t)), i === 2012 || i === "final")) return super.set(e, t); + } + }; + Al.names = ["flex-shrink", "flex-negative"]; + Oy.exports = Al; + }); + var Py = v((wI, Ty) => { + l(); + var f5 = M(), + _l = class extends f5 { + prefixed(e, t) { + return `${t}column-${e}`; + } + normalize(e) { + return e.includes("inside") + ? "break-inside" + : e.includes("before") + ? "break-before" + : "break-after"; + } + set(e, t) { + return ( + ((e.prop === "break-inside" && e.value === "avoid-column") || e.value === "avoid-page") && + (e.value = "avoid"), + super.set(e, t) + ); + } + insert(e, t, i) { + if (e.prop !== "break-inside") return super.insert(e, t, i); + if (!(/region/i.test(e.value) || /page/i.test(e.value))) return super.insert(e, t, i); + } + }; + _l.names = [ + "break-inside", + "page-break-inside", + "column-break-inside", + "break-before", + "page-break-before", + "column-break-before", + "break-after", + "page-break-after", + "column-break-after", + ]; + Ty.exports = _l; + }); + var Iy = v((bI, Dy) => { + l(); + var c5 = M(), + Ol = class extends c5 { + prefixed(e, t) { + return t + "print-color-adjust"; + } + normalize() { + return "color-adjust"; + } + }; + Ol.names = ["color-adjust", "print-color-adjust"]; + Dy.exports = Ol; + }); + var Ry = v((vI, qy) => { + l(); + var p5 = M(), + tr = class extends p5 { + insert(e, t, i) { + if (t === "-ms-") { + let n = this.set(this.clone(e), t); + this.needCascade(e) && (n.raws.before = this.calcBefore(i, e, t)); + let a = "ltr"; + return ( + e.parent.nodes.forEach((s) => { + s.prop === "direction" && (s.value === "rtl" || s.value === "ltr") && (a = s.value); + }), + (n.value = tr.msValues[a][e.value] || e.value), + e.parent.insertBefore(e, n) + ); + } + return super.insert(e, t, i); + } + }; + tr.names = ["writing-mode"]; + tr.msValues = { + ltr: { "horizontal-tb": "lr-tb", "vertical-rl": "tb-rl", "vertical-lr": "tb-lr" }, + rtl: { "horizontal-tb": "rl-tb", "vertical-rl": "bt-rl", "vertical-lr": "bt-lr" }, + }; + qy.exports = tr; + }); + var By = v((xI, My) => { + l(); + var d5 = M(), + El = class extends d5 { + set(e, t) { + return ((e.value = e.value.replace(/\s+fill(\s)/, "$1")), super.set(e, t)); + } + }; + El.names = ["border-image"]; + My.exports = El; + }); + var Ny = v((kI, Ly) => { + l(); + var Fy = pe(), + h5 = M(), + rr = class extends h5 { + prefixed(e, t) { + let i; + return (([i, t] = Fy(t)), i === 2012 ? t + "flex-line-pack" : super.prefixed(e, t)); + } + normalize() { + return "align-content"; + } + set(e, t) { + let i = Fy(t)[0]; + if (i === 2012) return ((e.value = rr.oldValues[e.value] || e.value), super.set(e, t)); + if (i === "final") return super.set(e, t); + } + }; + rr.names = ["align-content", "flex-line-pack"]; + rr.oldValues = { + "flex-end": "end", + "flex-start": "start", + "space-between": "justify", + "space-around": "distribute", + }; + Ly.exports = rr; + }); + var zy = v((SI, $y) => { + l(); + var m5 = M(), + Se = class extends m5 { + prefixed(e, t) { + return t === "-moz-" ? t + (Se.toMozilla[e] || e) : super.prefixed(e, t); + } + normalize(e) { + return Se.toNormal[e] || e; + } + }; + Se.names = ["border-radius"]; + Se.toMozilla = {}; + Se.toNormal = {}; + for (let r of ["top", "bottom"]) + for (let e of ["left", "right"]) { + let t = `border-${r}-${e}-radius`, + i = `border-radius-${r}${e}`; + (Se.names.push(t), Se.names.push(i), (Se.toMozilla[t] = i), (Se.toNormal[i] = t)); + } + $y.exports = Se; + }); + var Vy = v((CI, jy) => { + l(); + var g5 = M(), + Tl = class extends g5 { + prefixed(e, t) { + return e.includes("-start") + ? t + e.replace("-block-start", "-before") + : t + e.replace("-block-end", "-after"); + } + normalize(e) { + return e.includes("-before") + ? e.replace("-before", "-block-start") + : e.replace("-after", "-block-end"); + } + }; + Tl.names = [ + "border-block-start", + "border-block-end", + "margin-block-start", + "margin-block-end", + "padding-block-start", + "padding-block-end", + "border-before", + "border-after", + "margin-before", + "margin-after", + "padding-before", + "padding-after", + ]; + jy.exports = Tl; + }); + var Wy = v((AI, Uy) => { + l(); + var y5 = M(), + { parseTemplate: w5, warnMissedAreas: b5, getGridGap: v5, warnGridGap: x5, inheritGridGap: k5 } = mt(), + Pl = class extends y5 { + insert(e, t, i, n) { + if (t !== "-ms-") return super.insert(e, t, i); + if (e.parent.some((m) => m.prop === "-ms-grid-rows")) return; + let a = v5(e), + s = k5(e, a), + { rows: o, columns: u, areas: c } = w5({ decl: e, gap: s || a }), + f = Object.keys(c).length > 0, + d = Boolean(o), + p = Boolean(u); + return ( + x5({ gap: a, hasColumns: p, decl: e, result: n }), + b5(c, e, n), + ((d && p) || f) && e.cloneBefore({ prop: "-ms-grid-rows", value: o, raws: {} }), + p && e.cloneBefore({ prop: "-ms-grid-columns", value: u, raws: {} }), + e + ); + } + }; + Pl.names = ["grid-template"]; + Uy.exports = Pl; + }); + var Hy = v((_I, Gy) => { + l(); + var S5 = M(), + Dl = class extends S5 { + prefixed(e, t) { + return t + e.replace("-inline", ""); + } + normalize(e) { + return e.replace(/(margin|padding|border)-(start|end)/, "$1-inline-$2"); + } + }; + Dl.names = [ + "border-inline-start", + "border-inline-end", + "margin-inline-start", + "margin-inline-end", + "padding-inline-start", + "padding-inline-end", + "border-start", + "border-end", + "margin-start", + "margin-end", + "padding-start", + "padding-end", + ]; + Gy.exports = Dl; + }); + var Qy = v((OI, Yy) => { + l(); + var C5 = M(), + Il = class extends C5 { + check(e) { + return !e.value.includes("flex-") && e.value !== "baseline"; + } + prefixed(e, t) { + return t + "grid-row-align"; + } + normalize() { + return "align-self"; + } + }; + Il.names = ["grid-row-align"]; + Yy.exports = Il; + }); + var Xy = v((EI, Jy) => { + l(); + var A5 = M(), + ir = class extends A5 { + keyframeParents(e) { + let { parent: t } = e; + for (; t; ) { + if (t.type === "atrule" && t.name === "keyframes") return !0; + ({ parent: t } = t); + } + return !1; + } + contain3d(e) { + if (e.prop === "transform-origin") return !1; + for (let t of ir.functions3d) if (e.value.includes(`${t}(`)) return !0; + return !1; + } + set(e, t) { + return ( + (e = super.set(e, t)), + t === "-ms-" && (e.value = e.value.replace(/rotatez/gi, "rotate")), + e + ); + } + insert(e, t, i) { + if (t === "-ms-") { + if (!this.contain3d(e) && !this.keyframeParents(e)) return super.insert(e, t, i); + } else if (t === "-o-") { + if (!this.contain3d(e)) return super.insert(e, t, i); + } else return super.insert(e, t, i); + } + }; + ir.names = ["transform", "transform-origin"]; + ir.functions3d = [ + "matrix3d", + "translate3d", + "translateZ", + "scale3d", + "scaleZ", + "rotate3d", + "rotateX", + "rotateY", + "perspective", + ]; + Jy.exports = ir; + }); + var ew = v((TI, Zy) => { + l(); + var Ky = pe(), + _5 = M(), + ql = class extends _5 { + normalize() { + return "flex-direction"; + } + insert(e, t, i) { + let n; + if ((([n, t] = Ky(t)), n !== 2009)) return super.insert(e, t, i); + if (e.parent.some((f) => f.prop === t + "box-orient" || f.prop === t + "box-direction")) return; + let s = e.value, + o, + u; + s === "inherit" || s === "initial" || s === "unset" + ? ((o = s), (u = s)) + : ((o = s.includes("row") ? "horizontal" : "vertical"), + (u = s.includes("reverse") ? "reverse" : "normal")); + let c = this.clone(e); + return ( + (c.prop = t + "box-orient"), + (c.value = o), + this.needCascade(e) && (c.raws.before = this.calcBefore(i, e, t)), + e.parent.insertBefore(e, c), + (c = this.clone(e)), + (c.prop = t + "box-direction"), + (c.value = u), + this.needCascade(e) && (c.raws.before = this.calcBefore(i, e, t)), + e.parent.insertBefore(e, c) + ); + } + old(e, t) { + let i; + return (([i, t] = Ky(t)), i === 2009 ? [t + "box-orient", t + "box-direction"] : super.old(e, t)); + } + }; + ql.names = ["flex-direction", "box-direction", "box-orient"]; + Zy.exports = ql; + }); + var rw = v((PI, tw) => { + l(); + var O5 = M(), + Rl = class extends O5 { + check(e) { + return e.value === "pixelated"; + } + prefixed(e, t) { + return t === "-ms-" ? "-ms-interpolation-mode" : super.prefixed(e, t); + } + set(e, t) { + return t !== "-ms-" + ? super.set(e, t) + : ((e.prop = "-ms-interpolation-mode"), (e.value = "nearest-neighbor"), e); + } + normalize() { + return "image-rendering"; + } + process(e, t) { + return super.process(e, t); + } + }; + Rl.names = ["image-rendering", "interpolation-mode"]; + tw.exports = Rl; + }); + var nw = v((DI, iw) => { + l(); + var E5 = M(), + T5 = le(), + Ml = class extends E5 { + constructor(e, t, i) { + super(e, t, i); + this.prefixes && + (this.prefixes = T5.uniq(this.prefixes.map((n) => (n === "-ms-" ? "-webkit-" : n)))); + } + }; + Ml.names = ["backdrop-filter"]; + iw.exports = Ml; + }); + var aw = v((II, sw) => { + l(); + var P5 = M(), + D5 = le(), + Bl = class extends P5 { + constructor(e, t, i) { + super(e, t, i); + this.prefixes && + (this.prefixes = D5.uniq(this.prefixes.map((n) => (n === "-ms-" ? "-webkit-" : n)))); + } + check(e) { + return e.value.toLowerCase() === "text"; + } + }; + Bl.names = ["background-clip"]; + sw.exports = Bl; + }); + var lw = v((qI, ow) => { + l(); + var I5 = M(), + q5 = ["none", "underline", "overline", "line-through", "blink", "inherit", "initial", "unset"], + Fl = class extends I5 { + check(e) { + return e.value.split(/\s+/).some((t) => !q5.includes(t)); + } + }; + Fl.names = ["text-decoration"]; + ow.exports = Fl; + }); + var cw = v((RI, fw) => { + l(); + var uw = pe(), + R5 = M(), + nr = class extends R5 { + prefixed(e, t) { + let i; + return ( + ([i, t] = uw(t)), + i === 2009 ? t + "box-pack" : i === 2012 ? t + "flex-pack" : super.prefixed(e, t) + ); + } + normalize() { + return "justify-content"; + } + set(e, t) { + let i = uw(t)[0]; + if (i === 2009 || i === 2012) { + let n = nr.oldValues[e.value] || e.value; + if (((e.value = n), i !== 2009 || n !== "distribute")) return super.set(e, t); + } else if (i === "final") return super.set(e, t); + } + }; + nr.names = ["justify-content", "flex-pack", "box-pack"]; + nr.oldValues = { + "flex-end": "end", + "flex-start": "start", + "space-between": "justify", + "space-around": "distribute", + }; + fw.exports = nr; + }); + var dw = v((MI, pw) => { + l(); + var M5 = M(), + Ll = class extends M5 { + set(e, t) { + let i = e.value.toLowerCase(); + return ( + t === "-webkit-" && + !i.includes(" ") && + i !== "contain" && + i !== "cover" && + (e.value = e.value + " " + e.value), + super.set(e, t) + ); + } + }; + Ll.names = ["background-size"]; + pw.exports = Ll; + }); + var mw = v((BI, hw) => { + l(); + var B5 = M(), + Nl = mt(), + $l = class extends B5 { + insert(e, t, i) { + if (t !== "-ms-") return super.insert(e, t, i); + let n = Nl.parse(e), + [a, s] = Nl.translate(n, 0, 1); + (n[0] && n[0].includes("span") && (s = n[0].join("").replace(/\D/g, "")), + [ + [e.prop, a], + [`${e.prop}-span`, s], + ].forEach(([u, c]) => { + Nl.insertDecl(e, u, c); + })); + } + }; + $l.names = ["grid-row", "grid-column"]; + hw.exports = $l; + }); + var ww = v((FI, yw) => { + l(); + var F5 = M(), + { + prefixTrackProp: gw, + prefixTrackValue: L5, + autoplaceGridItems: N5, + getGridGap: $5, + inheritGridGap: z5, + } = mt(), + j5 = sl(), + zl = class extends F5 { + prefixed(e, t) { + return t === "-ms-" ? gw({ prop: e, prefix: t }) : super.prefixed(e, t); + } + normalize(e) { + return e.replace(/^grid-(rows|columns)/, "grid-template-$1"); + } + insert(e, t, i, n) { + if (t !== "-ms-") return super.insert(e, t, i); + let { parent: a, prop: s, value: o } = e, + u = s.includes("rows"), + c = s.includes("columns"), + f = a.some((k) => k.prop === "grid-template" || k.prop === "grid-template-areas"); + if (f && u) return !1; + let d = new j5({ options: {} }), + p = d.gridStatus(a, n), + m = $5(e); + m = z5(e, m) || m; + let b = u ? m.row : m.column; + (p === "no-autoplace" || p === !0) && !f && (b = null); + let x = L5({ value: o, gap: b }); + e.cloneBefore({ prop: gw({ prop: s, prefix: t }), value: x }); + let y = a.nodes.find((k) => k.prop === "grid-auto-flow"), + w = "row"; + if ((y && !d.disabled(y, n) && (w = y.value.trim()), p === "autoplace")) { + let k = a.nodes.find((_) => _.prop === "grid-template-rows"); + if (!k && f) return; + if (!k && !f) { + e.warn(n, "Autoplacement does not work without grid-template-rows property"); + return; + } + (!a.nodes.find((_) => _.prop === "grid-template-columns") && + !f && + e.warn(n, "Autoplacement does not work without grid-template-columns property"), + c && !f && N5(e, n, m, w)); + } + } + }; + zl.names = ["grid-template-rows", "grid-template-columns", "grid-rows", "grid-columns"]; + yw.exports = zl; + }); + var vw = v((LI, bw) => { + l(); + var V5 = M(), + jl = class extends V5 { + check(e) { + return !e.value.includes("flex-") && e.value !== "baseline"; + } + prefixed(e, t) { + return t + "grid-column-align"; + } + normalize() { + return "justify-self"; + } + }; + jl.names = ["grid-column-align"]; + bw.exports = jl; + }); + var kw = v((NI, xw) => { + l(); + var U5 = M(), + Vl = class extends U5 { + prefixed(e, t) { + return t + "scroll-chaining"; + } + normalize() { + return "overscroll-behavior"; + } + set(e, t) { + return ( + e.value === "auto" + ? (e.value = "chained") + : (e.value === "none" || e.value === "contain") && (e.value = "none"), + super.set(e, t) + ); + } + }; + Vl.names = ["overscroll-behavior", "scroll-chaining"]; + xw.exports = Vl; + }); + var Aw = v(($I, Cw) => { + l(); + var W5 = M(), + { + parseGridAreas: G5, + warnMissedAreas: H5, + prefixTrackProp: Y5, + prefixTrackValue: Sw, + getGridGap: Q5, + warnGridGap: J5, + inheritGridGap: X5, + } = mt(); + function K5(r) { + return r + .trim() + .slice(1, -1) + .split(/["']\s*["']?/g); + } + var Ul = class extends W5 { + insert(e, t, i, n) { + if (t !== "-ms-") return super.insert(e, t, i); + let a = !1, + s = !1, + o = e.parent, + u = Q5(e); + ((u = X5(e, u) || u), + o.walkDecls(/-ms-grid-rows/, (d) => d.remove()), + o.walkDecls(/grid-template-(rows|columns)/, (d) => { + if (d.prop === "grid-template-rows") { + s = !0; + let { prop: p, value: m } = d; + d.cloneBefore({ prop: Y5({ prop: p, prefix: t }), value: Sw({ value: m, gap: u.row }) }); + } else a = !0; + })); + let c = K5(e.value); + (a && + !s && + u.row && + c.length > 1 && + e.cloneBefore({ + prop: "-ms-grid-rows", + value: Sw({ value: `repeat(${c.length}, auto)`, gap: u.row }), + raws: {}, + }), + J5({ gap: u, hasColumns: a, decl: e, result: n })); + let f = G5({ rows: c, gap: u }); + return (H5(f, e, n), e); + } + }; + Ul.names = ["grid-template-areas"]; + Cw.exports = Ul; + }); + var Ow = v((zI, _w) => { + l(); + var Z5 = M(), + Wl = class extends Z5 { + set(e, t) { + return ( + t === "-webkit-" && (e.value = e.value.replace(/\s*(right|left)\s*/i, "")), + super.set(e, t) + ); + } + }; + Wl.names = ["text-emphasis-position"]; + _w.exports = Wl; + }); + var Tw = v((jI, Ew) => { + l(); + var e_ = M(), + Gl = class extends e_ { + set(e, t) { + return e.prop === "text-decoration-skip-ink" && e.value === "auto" + ? ((e.prop = t + "text-decoration-skip"), (e.value = "ink"), e) + : super.set(e, t); + } + }; + Gl.names = ["text-decoration-skip-ink", "text-decoration-skip"]; + Ew.exports = Gl; + }); + var Mw = v((VI, Rw) => { + l(); + ("use strict"); + Rw.exports = { wrap: Pw, limit: Dw, validate: Iw, test: Hl, curry: t_, name: qw }; + function Pw(r, e, t) { + var i = e - r; + return ((((t - r) % i) + i) % i) + r; + } + function Dw(r, e, t) { + return Math.max(r, Math.min(e, t)); + } + function Iw(r, e, t, i, n) { + if (!Hl(r, e, t, i, n)) throw new Error(t + " is outside of range [" + r + "," + e + ")"); + return t; + } + function Hl(r, e, t, i, n) { + return !(t < r || t > e || (n && t === e) || (i && t === r)); + } + function qw(r, e, t, i) { + return (t ? "(" : "[") + r + "," + e + (i ? ")" : "]"); + } + function t_(r, e, t, i) { + var n = qw.bind(null, r, e, t, i); + return { + wrap: Pw.bind(null, r, e), + limit: Dw.bind(null, r, e), + validate: function (a) { + return Iw(r, e, a, t, i); + }, + test: function (a) { + return Hl(r, e, a, t, i); + }, + toString: n, + name: n, + }; + } + }); + var Lw = v((UI, Fw) => { + l(); + var Yl = Kn(), + r_ = Mw(), + i_ = Qt(), + n_ = ke(), + s_ = le(), + Bw = /top|left|right|bottom/gi, + Qe = class extends n_ { + replace(e, t) { + let i = Yl(e); + for (let n of i.nodes) + if (n.type === "function" && n.value === this.name) + if ( + ((n.nodes = this.newDirection(n.nodes)), + (n.nodes = this.normalize(n.nodes)), + t === "-webkit- old") + ) { + if (!this.oldWebkit(n)) return !1; + } else ((n.nodes = this.convertDirection(n.nodes)), (n.value = t + n.value)); + return i.toString(); + } + replaceFirst(e, ...t) { + return t + .map((n) => (n === " " ? { type: "space", value: n } : { type: "word", value: n })) + .concat(e.slice(1)); + } + normalizeUnit(e, t) { + return `${(parseFloat(e) / t) * 360}deg`; + } + normalize(e) { + if (!e[0]) return e; + if (/-?\d+(.\d+)?grad/.test(e[0].value)) e[0].value = this.normalizeUnit(e[0].value, 400); + else if (/-?\d+(.\d+)?rad/.test(e[0].value)) + e[0].value = this.normalizeUnit(e[0].value, 2 * Math.PI); + else if (/-?\d+(.\d+)?turn/.test(e[0].value)) e[0].value = this.normalizeUnit(e[0].value, 1); + else if (e[0].value.includes("deg")) { + let t = parseFloat(e[0].value); + ((t = r_.wrap(0, 360, t)), (e[0].value = `${t}deg`)); + } + return ( + e[0].value === "0deg" + ? (e = this.replaceFirst(e, "to", " ", "top")) + : e[0].value === "90deg" + ? (e = this.replaceFirst(e, "to", " ", "right")) + : e[0].value === "180deg" + ? (e = this.replaceFirst(e, "to", " ", "bottom")) + : e[0].value === "270deg" && (e = this.replaceFirst(e, "to", " ", "left")), + e + ); + } + newDirection(e) { + if (e[0].value === "to" || ((Bw.lastIndex = 0), !Bw.test(e[0].value))) return e; + e.unshift({ type: "word", value: "to" }, { type: "space", value: " " }); + for (let t = 2; t < e.length && e[t].type !== "div"; t++) + e[t].type === "word" && (e[t].value = this.revertDirection(e[t].value)); + return e; + } + isRadial(e) { + let t = "before"; + for (let i of e) + if (t === "before" && i.type === "space") t = "at"; + else if (t === "at" && i.value === "at") t = "after"; + else { + if (t === "after" && i.type === "space") return !0; + if (i.type === "div") break; + t = "before"; + } + return !1; + } + convertDirection(e) { + return ( + e.length > 0 && + (e[0].value === "to" + ? this.fixDirection(e) + : e[0].value.includes("deg") + ? this.fixAngle(e) + : this.isRadial(e) && this.fixRadial(e)), + e + ); + } + fixDirection(e) { + e.splice(0, 2); + for (let t of e) { + if (t.type === "div") break; + t.type === "word" && (t.value = this.revertDirection(t.value)); + } + } + fixAngle(e) { + let t = e[0].value; + ((t = parseFloat(t)), + (t = Math.abs(450 - t) % 360), + (t = this.roundFloat(t, 3)), + (e[0].value = `${t}deg`)); + } + fixRadial(e) { + let t = [], + i = [], + n, + a, + s, + o, + u; + for (o = 0; o < e.length - 2; o++) + if ( + ((n = e[o]), + (a = e[o + 1]), + (s = e[o + 2]), + n.type === "space" && a.value === "at" && s.type === "space") + ) { + u = o + 3; + break; + } else t.push(n); + let c; + for (o = u; o < e.length; o++) + if (e[o].type === "div") { + c = e[o]; + break; + } else i.push(e[o]); + e.splice(0, o, ...i, c, ...t); + } + revertDirection(e) { + return Qe.directions[e.toLowerCase()] || e; + } + roundFloat(e, t) { + return parseFloat(e.toFixed(t)); + } + oldWebkit(e) { + let { nodes: t } = e, + i = Yl.stringify(e.nodes); + if ( + this.name !== "linear-gradient" || + (t[0] && t[0].value.includes("deg")) || + i.includes("px") || + i.includes("-corner") || + i.includes("-side") + ) + return !1; + let n = [[]]; + for (let a of t) (n[n.length - 1].push(a), a.type === "div" && a.value === "," && n.push([])); + (this.oldDirection(n), this.colorStops(n), (e.nodes = [])); + for (let a of n) e.nodes = e.nodes.concat(a); + return ( + e.nodes.unshift({ type: "word", value: "linear" }, this.cloneDiv(e.nodes)), + (e.value = "-webkit-gradient"), + !0 + ); + } + oldDirection(e) { + let t = this.cloneDiv(e[0]); + if (e[0][0].value !== "to") return e.unshift([{ type: "word", value: Qe.oldDirections.bottom }, t]); + { + let i = []; + for (let a of e[0].slice(2)) a.type === "word" && i.push(a.value.toLowerCase()); + i = i.join(" "); + let n = Qe.oldDirections[i] || i; + return ((e[0] = [{ type: "word", value: n }, t]), e[0]); + } + } + cloneDiv(e) { + for (let t of e) if (t.type === "div" && t.value === ",") return t; + return { type: "div", value: ",", after: " " }; + } + colorStops(e) { + let t = []; + for (let i = 0; i < e.length; i++) { + let n, + a = e[i], + s; + if (i === 0) continue; + let o = Yl.stringify(a[0]); + a[1] && a[1].type === "word" + ? (n = a[1].value) + : a[2] && a[2].type === "word" && (n = a[2].value); + let u; + i === 1 && (!n || n === "0%") + ? (u = `from(${o})`) + : i === e.length - 1 && (!n || n === "100%") + ? (u = `to(${o})`) + : n + ? (u = `color-stop(${n}, ${o})`) + : (u = `color-stop(${o})`); + let c = a[a.length - 1]; + ((e[i] = [{ type: "word", value: u }]), + c.type === "div" && c.value === "," && (s = e[i].push(c)), + t.push(s)); + } + return t; + } + old(e) { + if (e === "-webkit-") { + let t = this.name === "linear-gradient" ? "linear" : "radial", + i = "-gradient", + n = s_.regexp(`-webkit-(${t}-gradient|gradient\\(\\s*${t})`, !1); + return new i_(this.name, e + this.name, i, n); + } else return super.old(e); + } + add(e, t) { + let i = e.prop; + if (i.includes("mask")) { + if (t === "-webkit-" || t === "-webkit- old") return super.add(e, t); + } else if (i === "list-style" || i === "list-style-image" || i === "content") { + if (t === "-webkit-" || t === "-webkit- old") return super.add(e, t); + } else return super.add(e, t); + } + }; + Qe.names = ["linear-gradient", "repeating-linear-gradient", "radial-gradient", "repeating-radial-gradient"]; + Qe.directions = { top: "bottom", left: "right", bottom: "top", right: "left" }; + Qe.oldDirections = { + top: "left bottom, left top", + left: "right top, left top", + bottom: "left top, left bottom", + right: "left top, right top", + "top right": "left bottom, right top", + "top left": "right bottom, left top", + "right top": "left bottom, right top", + "right bottom": "left top, right bottom", + "bottom right": "left top, right bottom", + "bottom left": "right top, left bottom", + "left top": "right bottom, left top", + "left bottom": "right top, left bottom", + }; + Fw.exports = Qe; + }); + var zw = v((WI, $w) => { + l(); + var a_ = Qt(), + o_ = ke(); + function Nw(r) { + return new RegExp(`(^|[\\s,(])(${r}($|[\\s),]))`, "gi"); + } + var Ql = class extends o_ { + regexp() { + return (this.regexpCache || (this.regexpCache = Nw(this.name)), this.regexpCache); + } + isStretch() { + return this.name === "stretch" || this.name === "fill" || this.name === "fill-available"; + } + replace(e, t) { + return t === "-moz-" && this.isStretch() + ? e.replace(this.regexp(), "$1-moz-available$3") + : t === "-webkit-" && this.isStretch() + ? e.replace(this.regexp(), "$1-webkit-fill-available$3") + : super.replace(e, t); + } + old(e) { + let t = e + this.name; + return ( + this.isStretch() && + (e === "-moz-" ? (t = "-moz-available") : e === "-webkit-" && (t = "-webkit-fill-available")), + new a_(this.name, t, t, Nw(t)) + ); + } + add(e, t) { + if (!(e.prop.includes("grid") && t !== "-webkit-")) return super.add(e, t); + } + }; + Ql.names = ["max-content", "min-content", "fit-content", "fill", "fill-available", "stretch"]; + $w.exports = Ql; + }); + var Uw = v((GI, Vw) => { + l(); + var jw = Qt(), + l_ = ke(), + Jl = class extends l_ { + replace(e, t) { + return t === "-webkit-" + ? e.replace(this.regexp(), "$1-webkit-optimize-contrast") + : t === "-moz-" + ? e.replace(this.regexp(), "$1-moz-crisp-edges") + : super.replace(e, t); + } + old(e) { + return e === "-webkit-" + ? new jw(this.name, "-webkit-optimize-contrast") + : e === "-moz-" + ? new jw(this.name, "-moz-crisp-edges") + : super.old(e); + } + }; + Jl.names = ["pixelated"]; + Vw.exports = Jl; + }); + var Gw = v((HI, Ww) => { + l(); + var u_ = ke(), + Xl = class extends u_ { + replace(e, t) { + let i = super.replace(e, t); + return (t === "-webkit-" && (i = i.replace(/("[^"]+"|'[^']+')(\s+\d+\w)/gi, "url($1)$2")), i); + } + }; + Xl.names = ["image-set"]; + Ww.exports = Xl; + }); + var Yw = v((YI, Hw) => { + l(); + var f_ = ge().list, + c_ = ke(), + Kl = class extends c_ { + replace(e, t) { + return f_ + .space(e) + .map((i) => { + if (i.slice(0, +this.name.length + 1) !== this.name + "(") return i; + let n = i.lastIndexOf(")"), + a = i.slice(n + 1), + s = i.slice(this.name.length + 1, n); + if (t === "-webkit-") { + let o = s.match(/\d*.?\d+%?/); + o ? ((s = s.slice(o[0].length).trim()), (s += `, ${o[0]}`)) : (s += ", 0.5"); + } + return t + this.name + "(" + s + ")" + a; + }) + .join(" "); + } + }; + Kl.names = ["cross-fade"]; + Hw.exports = Kl; + }); + var Jw = v((QI, Qw) => { + l(); + var p_ = pe(), + d_ = Qt(), + h_ = ke(), + Zl = class extends h_ { + constructor(e, t) { + super(e, t); + e === "display-flex" && (this.name = "flex"); + } + check(e) { + return e.prop === "display" && e.value === this.name; + } + prefixed(e) { + let t, i; + return ( + ([t, e] = p_(e)), + t === 2009 + ? this.name === "flex" + ? (i = "box") + : (i = "inline-box") + : t === 2012 + ? this.name === "flex" + ? (i = "flexbox") + : (i = "inline-flexbox") + : t === "final" && (i = this.name), + e + i + ); + } + replace(e, t) { + return this.prefixed(t); + } + old(e) { + let t = this.prefixed(e); + if (!!t) return new d_(this.name, t); + } + }; + Zl.names = ["display-flex", "inline-flex"]; + Qw.exports = Zl; + }); + var Kw = v((JI, Xw) => { + l(); + var m_ = ke(), + eu = class extends m_ { + constructor(e, t) { + super(e, t); + e === "display-grid" && (this.name = "grid"); + } + check(e) { + return e.prop === "display" && e.value === this.name; + } + }; + eu.names = ["display-grid", "inline-grid"]; + Xw.exports = eu; + }); + var eb = v((XI, Zw) => { + l(); + var g_ = ke(), + tu = class extends g_ { + constructor(e, t) { + super(e, t); + e === "filter-function" && (this.name = "filter"); + } + }; + tu.names = ["filter", "filter-function"]; + Zw.exports = tu; + }); + var nb = v((KI, ib) => { + l(); + var tb = ai(), + B = M(), + rb = Fm(), + y_ = tg(), + w_ = sl(), + b_ = vg(), + ru = dt(), + sr = Jt(), + v_ = Eg(), + $e = ke(), + ar = le(), + x_ = Pg(), + k_ = Ig(), + S_ = Rg(), + C_ = Bg(), + A_ = zg(), + __ = Ug(), + O_ = Gg(), + E_ = Yg(), + T_ = Jg(), + P_ = Kg(), + D_ = ey(), + I_ = ry(), + q_ = ny(), + R_ = ay(), + M_ = ly(), + B_ = cy(), + F_ = dy(), + L_ = gy(), + N_ = wy(), + $_ = vy(), + z_ = Sy(), + j_ = Ay(), + V_ = Ey(), + U_ = Py(), + W_ = Iy(), + G_ = Ry(), + H_ = By(), + Y_ = Ny(), + Q_ = zy(), + J_ = Vy(), + X_ = Wy(), + K_ = Hy(), + Z_ = Qy(), + eO = Xy(), + tO = ew(), + rO = rw(), + iO = nw(), + nO = aw(), + sO = lw(), + aO = cw(), + oO = dw(), + lO = mw(), + uO = ww(), + fO = vw(), + cO = kw(), + pO = Aw(), + dO = Ow(), + hO = Tw(), + mO = Lw(), + gO = zw(), + yO = Uw(), + wO = Gw(), + bO = Yw(), + vO = Jw(), + xO = Kw(), + kO = eb(); + sr.hack(x_); + sr.hack(k_); + sr.hack(S_); + sr.hack(C_); + B.hack(A_); + B.hack(__); + B.hack(O_); + B.hack(E_); + B.hack(T_); + B.hack(P_); + B.hack(D_); + B.hack(I_); + B.hack(q_); + B.hack(R_); + B.hack(M_); + B.hack(B_); + B.hack(F_); + B.hack(L_); + B.hack(N_); + B.hack($_); + B.hack(z_); + B.hack(j_); + B.hack(V_); + B.hack(U_); + B.hack(W_); + B.hack(G_); + B.hack(H_); + B.hack(Y_); + B.hack(Q_); + B.hack(J_); + B.hack(X_); + B.hack(K_); + B.hack(Z_); + B.hack(eO); + B.hack(tO); + B.hack(rO); + B.hack(iO); + B.hack(nO); + B.hack(sO); + B.hack(aO); + B.hack(oO); + B.hack(lO); + B.hack(uO); + B.hack(fO); + B.hack(cO); + B.hack(pO); + B.hack(dO); + B.hack(hO); + $e.hack(mO); + $e.hack(gO); + $e.hack(yO); + $e.hack(wO); + $e.hack(bO); + $e.hack(vO); + $e.hack(xO); + $e.hack(kO); + var iu = new Map(), + li = class { + constructor(e, t, i = {}) { + ((this.data = e), + (this.browsers = t), + (this.options = i), + ([this.add, this.remove] = this.preprocess(this.select(this.data))), + (this.transition = new y_(this)), + (this.processor = new w_(this))); + } + cleaner() { + if (this.cleanerCache) return this.cleanerCache; + if (this.browsers.selected.length) { + let e = new ru(this.browsers.data, []); + this.cleanerCache = new li(this.data, e, this.options); + } else return this; + return this.cleanerCache; + } + select(e) { + let t = { add: {}, remove: {} }; + for (let i in e) { + let n = e[i], + a = n.browsers.map((u) => { + let c = u.split(" "); + return { browser: `${c[0]} ${c[1]}`, note: c[2] }; + }), + s = a.filter((u) => u.note).map((u) => `${this.browsers.prefix(u.browser)} ${u.note}`); + ((s = ar.uniq(s)), + (a = a + .filter((u) => this.browsers.isSelected(u.browser)) + .map((u) => { + let c = this.browsers.prefix(u.browser); + return u.note ? `${c} ${u.note}` : c; + })), + (a = this.sort(ar.uniq(a))), + this.options.flexbox === "no-2009" && (a = a.filter((u) => !u.includes("2009")))); + let o = n.browsers.map((u) => this.browsers.prefix(u)); + (n.mistakes && (o = o.concat(n.mistakes)), + (o = o.concat(s)), + (o = ar.uniq(o)), + a.length + ? ((t.add[i] = a), + a.length < o.length && (t.remove[i] = o.filter((u) => !a.includes(u)))) + : (t.remove[i] = o)); + } + return t; + } + sort(e) { + return e.sort((t, i) => { + let n = ar.removeNote(t).length, + a = ar.removeNote(i).length; + return n === a ? i.length - t.length : a - n; + }); + } + preprocess(e) { + let t = { selectors: [], "@supports": new b_(li, this) }; + for (let n in e.add) { + let a = e.add[n]; + if (n === "@keyframes" || n === "@viewport") t[n] = new v_(n, a, this); + else if (n === "@resolution") t[n] = new rb(n, a, this); + else if (this.data[n].selector) t.selectors.push(sr.load(n, a, this)); + else { + let s = this.data[n].props; + if (s) { + let o = $e.load(n, a, this); + for (let u of s) (t[u] || (t[u] = { values: [] }), t[u].values.push(o)); + } else { + let o = (t[n] && t[n].values) || []; + ((t[n] = B.load(n, a, this)), (t[n].values = o)); + } + } + } + let i = { selectors: [] }; + for (let n in e.remove) { + let a = e.remove[n]; + if (this.data[n].selector) { + let s = sr.load(n, a); + for (let o of a) i.selectors.push(s.old(o)); + } else if (n === "@keyframes" || n === "@viewport") + for (let s of a) { + let o = `@${s}${n.slice(1)}`; + i[o] = { remove: !0 }; + } + else if (n === "@resolution") i[n] = new rb(n, a, this); + else { + let s = this.data[n].props; + if (s) { + let o = $e.load(n, [], this); + for (let u of a) { + let c = o.old(u); + if (c) + for (let f of s) + (i[f] || (i[f] = {}), + i[f].values || (i[f].values = []), + i[f].values.push(c)); + } + } else + for (let o of a) { + let u = this.decl(n).old(n, o); + if (n === "align-self") { + let c = t[n] && t[n].prefixes; + if (c) { + if (o === "-webkit- 2009" && c.includes("-webkit-")) continue; + if (o === "-webkit-" && c.includes("-webkit- 2009")) continue; + } + } + for (let c of u) (i[c] || (i[c] = {}), (i[c].remove = !0)); + } + } + } + return [t, i]; + } + decl(e) { + return (iu.has(e) || iu.set(e, B.load(e)), iu.get(e)); + } + unprefixed(e) { + let t = this.normalize(tb.unprefixed(e)); + return (t === "flex-direction" && (t = "flex-flow"), t); + } + normalize(e) { + return this.decl(e).normalize(e); + } + prefixed(e, t) { + return ((e = tb.unprefixed(e)), this.decl(e).prefixed(e, t)); + } + values(e, t) { + let i = this[e], + n = i["*"] && i["*"].values, + a = i[t] && i[t].values; + return n && a ? ar.uniq(n.concat(a)) : n || a || []; + } + group(e) { + let t = e.parent, + i = t.index(e), + { length: n } = t.nodes, + a = this.unprefixed(e.prop), + s = (o, u) => { + for (i += o; i >= 0 && i < n; ) { + let c = t.nodes[i]; + if (c.type === "decl") { + if ( + (o === -1 && c.prop === a && !ru.withPrefix(c.value)) || + this.unprefixed(c.prop) !== a + ) + break; + if (u(c) === !0) return !0; + if (o === 1 && c.prop === a && !ru.withPrefix(c.value)) break; + } + i += o; + } + return !1; + }; + return { + up(o) { + return s(-1, o); + }, + down(o) { + return s(1, o); + }, + }; + } + }; + ib.exports = li; + }); + var ab = v((ZI, sb) => { + l(); + sb.exports = { + "backdrop-filter": { + feature: "css-backdrop-filter", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5", "safari 16.5"], + }, + element: { + props: [ + "background", + "background-image", + "border-image", + "mask", + "list-style", + "list-style-image", + "content", + "mask-image", + ], + feature: "css-element-function", + browsers: ["firefox 114"], + }, + "user-select": { + mistakes: ["-khtml-"], + feature: "user-select-none", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5", "safari 16.5"], + }, + "background-clip": { + feature: "background-clip-text", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + hyphens: { + feature: "css-hyphens", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5", "safari 16.5"], + }, + fill: { + props: [ + "width", + "min-width", + "max-width", + "height", + "min-height", + "max-height", + "inline-size", + "min-inline-size", + "max-inline-size", + "block-size", + "min-block-size", + "max-block-size", + "grid", + "grid-template", + "grid-template-rows", + "grid-template-columns", + "grid-auto-columns", + "grid-auto-rows", + ], + feature: "intrinsic-width", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "fill-available": { + props: [ + "width", + "min-width", + "max-width", + "height", + "min-height", + "max-height", + "inline-size", + "min-inline-size", + "max-inline-size", + "block-size", + "min-block-size", + "max-block-size", + "grid", + "grid-template", + "grid-template-rows", + "grid-template-columns", + "grid-auto-columns", + "grid-auto-rows", + ], + feature: "intrinsic-width", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + stretch: { + props: [ + "width", + "min-width", + "max-width", + "height", + "min-height", + "max-height", + "inline-size", + "min-inline-size", + "max-inline-size", + "block-size", + "min-block-size", + "max-block-size", + "grid", + "grid-template", + "grid-template-rows", + "grid-template-columns", + "grid-auto-columns", + "grid-auto-rows", + ], + feature: "intrinsic-width", + browsers: ["firefox 114"], + }, + "fit-content": { + props: [ + "width", + "min-width", + "max-width", + "height", + "min-height", + "max-height", + "inline-size", + "min-inline-size", + "max-inline-size", + "block-size", + "min-block-size", + "max-block-size", + "grid", + "grid-template", + "grid-template-rows", + "grid-template-columns", + "grid-auto-columns", + "grid-auto-rows", + ], + feature: "intrinsic-width", + browsers: ["firefox 114"], + }, + "text-decoration-style": { + feature: "text-decoration", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5"], + }, + "text-decoration-color": { + feature: "text-decoration", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5"], + }, + "text-decoration-line": { + feature: "text-decoration", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5"], + }, + "text-decoration": { + feature: "text-decoration", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5"], + }, + "text-decoration-skip": { + feature: "text-decoration", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5"], + }, + "text-decoration-skip-ink": { + feature: "text-decoration", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5"], + }, + "text-size-adjust": { + feature: "text-size-adjust", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5"], + }, + "mask-clip": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-composite": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-image": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-origin": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-repeat": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-border-repeat": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-border-source": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + mask: { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-position": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-size": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-border": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-border-outset": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-border-width": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-border-slice": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "clip-path": { feature: "css-clip-path", browsers: ["samsung 21"] }, + "box-decoration-break": { + feature: "css-boxdecorationbreak", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "ios_saf 16.1", + "ios_saf 16.3", + "ios_saf 16.4", + "ios_saf 16.5", + "opera 99", + "safari 16.5", + "samsung 21", + ], + }, + appearance: { feature: "css-appearance", browsers: ["samsung 21"] }, + "image-set": { + props: [ + "background", + "background-image", + "border-image", + "cursor", + "mask", + "mask-image", + "list-style", + "list-style-image", + "content", + ], + feature: "css-image-set", + browsers: ["and_uc 15.5", "chrome 109", "samsung 21"], + }, + "cross-fade": { + props: [ + "background", + "background-image", + "border-image", + "mask", + "list-style", + "list-style-image", + "content", + "mask-image", + ], + feature: "css-cross-fade", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + isolate: { + props: ["unicode-bidi"], + feature: "css-unicode-bidi", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5", "safari 16.5"], + }, + "color-adjust": { + feature: "css-color-adjust", + browsers: ["chrome 109", "chrome 113", "chrome 114", "edge 114", "opera 99"], + }, + }; + }); + var lb = v((eq, ob) => { + l(); + ob.exports = {}; + }); + var pb = v((tq, cb) => { + l(); + var SO = Ho(), + { agents: CO } = (Gn(), Wn), + nu = Sm(), + AO = dt(), + _O = nb(), + OO = ab(), + EO = lb(), + ub = { browsers: CO, prefixes: OO }, + fb = ` Replace Autoprefixer \`browsers\` option to Browserslist config. Use \`browserslist\` key in \`package.json\` or \`.browserslistrc\` file. @@ -51,12 +18914,564 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho https://github.com/browserslist/browserslist#readme https://twitter.com/browserslist -`;function TO(r){return Object.prototype.toString.apply(r)==="[object Object]"}var su=new Map;function PO(r,e){e.browsers.selected.length!==0&&(e.add.selectors.length>0||Object.keys(e.add).length>2||r.warn(`Autoprefixer target browsers do not need any prefixes.You do not need Autoprefixer anymore. +`; + function TO(r) { + return Object.prototype.toString.apply(r) === "[object Object]"; + } + var su = new Map(); + function PO(r, e) { + e.browsers.selected.length !== 0 && + (e.add.selectors.length > 0 || + Object.keys(e.add).length > 2 || + r.warn(`Autoprefixer target browsers do not need any prefixes.You do not need Autoprefixer anymore. Check your Browserslist config to be sure that your targets are set up correctly. Learn more at: https://github.com/postcss/autoprefixer#readme https://github.com/browserslist/browserslist#readme -`))}cb.exports=or;function or(...r){let e;if(r.length===1&&TO(r[0])?(e=r[0],r=void 0):r.length===0||r.length===1&&!r[0]?r=void 0:r.length<=2&&(Array.isArray(r[0])||!r[0])?(e=r[1],r=r[0]):typeof r[r.length-1]=="object"&&(e=r.pop()),e||(e={}),e.browser)throw new Error("Change `browser` option to `overrideBrowserslist` in Autoprefixer");if(e.browserslist)throw new Error("Change `browserslist` option to `overrideBrowserslist` in Autoprefixer");e.overrideBrowserslist?r=e.overrideBrowserslist:e.browsers&&(typeof console!="undefined"&&console.warn&&(nu.red?console.warn(nu.red(fb.replace(/`[^`]+`/g,n=>nu.yellow(n.slice(1,-1))))):console.warn(fb)),r=e.browsers);let t={ignoreUnknownVersions:e.ignoreUnknownVersions,stats:e.stats,env:e.env};function i(n){let a=ub,s=new AO(a.browsers,r,n,t),o=s.selected.join(", ")+JSON.stringify(e);return su.has(o)||su.set(o,new _O(a.prefixes,s,e)),su.get(o)}return{postcssPlugin:"autoprefixer",prepare(n){let a=i({from:n.opts.from,env:e.env});return{OnceExit(s){PO(n,a),e.remove!==!1&&a.processor.remove(s,n),e.add!==!1&&a.processor.add(s,n)}}},info(n){return n=n||{},n.from=n.from||h.cwd(),EO(i(n))},options:e,browsers:r}}or.postcss=!0;or.data=ub;or.defaults=SO.defaults;or.info=()=>or().info()});var hb=v((rq,db)=>{l();db.exports={aqua:/#00ffff(ff)?(?!\w)|#0ff(f)?(?!\w)/gi,azure:/#f0ffff(ff)?(?!\w)/gi,beige:/#f5f5dc(ff)?(?!\w)/gi,bisque:/#ffe4c4(ff)?(?!\w)/gi,black:/#000000(ff)?(?!\w)|#000(f)?(?!\w)/gi,blue:/#0000ff(ff)?(?!\w)|#00f(f)?(?!\w)/gi,brown:/#a52a2a(ff)?(?!\w)/gi,coral:/#ff7f50(ff)?(?!\w)/gi,cornsilk:/#fff8dc(ff)?(?!\w)/gi,crimson:/#dc143c(ff)?(?!\w)/gi,cyan:/#00ffff(ff)?(?!\w)|#0ff(f)?(?!\w)/gi,darkblue:/#00008b(ff)?(?!\w)/gi,darkcyan:/#008b8b(ff)?(?!\w)/gi,darkgrey:/#a9a9a9(ff)?(?!\w)/gi,darkred:/#8b0000(ff)?(?!\w)/gi,deeppink:/#ff1493(ff)?(?!\w)/gi,dimgrey:/#696969(ff)?(?!\w)/gi,gold:/#ffd700(ff)?(?!\w)/gi,green:/#008000(ff)?(?!\w)/gi,grey:/#808080(ff)?(?!\w)/gi,honeydew:/#f0fff0(ff)?(?!\w)/gi,hotpink:/#ff69b4(ff)?(?!\w)/gi,indigo:/#4b0082(ff)?(?!\w)/gi,ivory:/#fffff0(ff)?(?!\w)/gi,khaki:/#f0e68c(ff)?(?!\w)/gi,lavender:/#e6e6fa(ff)?(?!\w)/gi,lime:/#00ff00(ff)?(?!\w)|#0f0(f)?(?!\w)/gi,linen:/#faf0e6(ff)?(?!\w)/gi,maroon:/#800000(ff)?(?!\w)/gi,moccasin:/#ffe4b5(ff)?(?!\w)/gi,navy:/#000080(ff)?(?!\w)/gi,oldlace:/#fdf5e6(ff)?(?!\w)/gi,olive:/#808000(ff)?(?!\w)/gi,orange:/#ffa500(ff)?(?!\w)/gi,orchid:/#da70d6(ff)?(?!\w)/gi,peru:/#cd853f(ff)?(?!\w)/gi,pink:/#ffc0cb(ff)?(?!\w)/gi,plum:/#dda0dd(ff)?(?!\w)/gi,purple:/#800080(ff)?(?!\w)/gi,red:/#ff0000(ff)?(?!\w)|#f00(f)?(?!\w)/gi,salmon:/#fa8072(ff)?(?!\w)/gi,seagreen:/#2e8b57(ff)?(?!\w)/gi,seashell:/#fff5ee(ff)?(?!\w)/gi,sienna:/#a0522d(ff)?(?!\w)/gi,silver:/#c0c0c0(ff)?(?!\w)/gi,skyblue:/#87ceeb(ff)?(?!\w)/gi,snow:/#fffafa(ff)?(?!\w)/gi,tan:/#d2b48c(ff)?(?!\w)/gi,teal:/#008080(ff)?(?!\w)/gi,thistle:/#d8bfd8(ff)?(?!\w)/gi,tomato:/#ff6347(ff)?(?!\w)/gi,violet:/#ee82ee(ff)?(?!\w)/gi,wheat:/#f5deb3(ff)?(?!\w)/gi,white:/#ffffff(ff)?(?!\w)|#fff(f)?(?!\w)/gi}});var gb=v((iq,mb)=>{l();var au=hb(),ou={whitespace:/\s+/g,urlHexPairs:/%[\dA-F]{2}/g,quotes:/"/g};function DO(r){return r.trim().replace(ou.whitespace," ")}function IO(r){return encodeURIComponent(r).replace(ou.urlHexPairs,RO)}function qO(r){return Object.keys(au).forEach(function(e){au[e].test(r)&&(r=r.replace(au[e],e))}),r}function RO(r){switch(r){case"%20":return" ";case"%3D":return"=";case"%3A":return":";case"%2F":return"/";default:return r.toLowerCase()}}function lu(r){if(typeof r!="string")throw new TypeError("Expected a string, but received "+typeof r);r.charCodeAt(0)===65279&&(r=r.slice(1));var e=qO(DO(r)).replace(ou.quotes,"'");return"data:image/svg+xml,"+IO(e)}lu.toSrcset=function(e){return lu(e).replace(/ /g,"%20")};mb.exports=lu});var uu={};Ae(uu,{default:()=>MO});var yb,MO,fu=C(()=>{l();wi();yb=X(Si()),MO=et(yb.default.theme)});var kb=v((sq,xb)=>{l();var Zn=gb(),BO=(qn(),In).default,wb=(fu(),uu).default,gt=(mi(),as).default,[FO,{lineHeight:LO}]=wb.fontSize.base,{spacing:Je,borderWidth:bb,borderRadius:vb}=wb;function yt(r,e){return r.replace("",`var(${e}, 1)`)}var NO=BO.withOptions(function(r={strategy:void 0}){return function({addBase:e,addComponents:t,theme:i}){let n=r.strategy===void 0?["base","class"]:[r.strategy],a=[{base:["[type='text']","input:where(:not([type]))","[type='email']","[type='url']","[type='password']","[type='number']","[type='date']","[type='datetime-local']","[type='month']","[type='search']","[type='tel']","[type='time']","[type='week']","[multiple]","textarea","select"],class:[".form-input",".form-textarea",".form-select",".form-multiselect"],styles:{appearance:"none","background-color":"#fff","border-color":yt(i("colors.gray.500",gt.gray[500]),"--tw-border-opacity"),"border-width":bb.DEFAULT,"border-radius":vb.none,"padding-top":Je[2],"padding-right":Je[3],"padding-bottom":Je[2],"padding-left":Je[3],"font-size":FO,"line-height":LO,"--tw-shadow":"0 0 #0000","&:focus":{outline:"2px solid transparent","outline-offset":"2px","--tw-ring-inset":"var(--tw-empty,/*!*/ /*!*/)","--tw-ring-offset-width":"0px","--tw-ring-offset-color":"#fff","--tw-ring-color":yt(i("colors.blue.600",gt.blue[600]),"--tw-ring-opacity"),"--tw-ring-offset-shadow":"var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)","--tw-ring-shadow":"var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)","box-shadow":"var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)","border-color":yt(i("colors.blue.600",gt.blue[600]),"--tw-border-opacity")}}},{base:["input::placeholder","textarea::placeholder"],class:[".form-input::placeholder",".form-textarea::placeholder"],styles:{color:yt(i("colors.gray.500",gt.gray[500]),"--tw-text-opacity"),opacity:"1"}},{base:["::-webkit-datetime-edit-fields-wrapper"],class:[".form-input::-webkit-datetime-edit-fields-wrapper"],styles:{padding:"0"}},{base:["::-webkit-date-and-time-value"],class:[".form-input::-webkit-date-and-time-value"],styles:{"min-height":"1.5em"}},{base:["::-webkit-date-and-time-value"],class:[".form-input::-webkit-date-and-time-value"],styles:{"text-align":"inherit"}},{base:["::-webkit-datetime-edit"],class:[".form-input::-webkit-datetime-edit"],styles:{display:"inline-flex"}},{base:["::-webkit-datetime-edit","::-webkit-datetime-edit-year-field","::-webkit-datetime-edit-month-field","::-webkit-datetime-edit-day-field","::-webkit-datetime-edit-hour-field","::-webkit-datetime-edit-minute-field","::-webkit-datetime-edit-second-field","::-webkit-datetime-edit-millisecond-field","::-webkit-datetime-edit-meridiem-field"],class:[".form-input::-webkit-datetime-edit",".form-input::-webkit-datetime-edit-year-field",".form-input::-webkit-datetime-edit-month-field",".form-input::-webkit-datetime-edit-day-field",".form-input::-webkit-datetime-edit-hour-field",".form-input::-webkit-datetime-edit-minute-field",".form-input::-webkit-datetime-edit-second-field",".form-input::-webkit-datetime-edit-millisecond-field",".form-input::-webkit-datetime-edit-meridiem-field"],styles:{"padding-top":0,"padding-bottom":0}},{base:["select"],class:[".form-select"],styles:{"background-image":`url("${Zn(``)}")`,"background-position":`right ${Je[2]} center`,"background-repeat":"no-repeat","background-size":"1.5em 1.5em","padding-right":Je[10],"print-color-adjust":"exact"}},{base:["[multiple]",'[size]:where(select:not([size="1"]))'],class:['.form-select:where([size]:not([size="1"]))'],styles:{"background-image":"initial","background-position":"initial","background-repeat":"unset","background-size":"initial","padding-right":Je[3],"print-color-adjust":"unset"}},{base:["[type='checkbox']","[type='radio']"],class:[".form-checkbox",".form-radio"],styles:{appearance:"none",padding:"0","print-color-adjust":"exact",display:"inline-block","vertical-align":"middle","background-origin":"border-box","user-select":"none","flex-shrink":"0",height:Je[4],width:Je[4],color:yt(i("colors.blue.600",gt.blue[600]),"--tw-text-opacity"),"background-color":"#fff","border-color":yt(i("colors.gray.500",gt.gray[500]),"--tw-border-opacity"),"border-width":bb.DEFAULT,"--tw-shadow":"0 0 #0000"}},{base:["[type='checkbox']"],class:[".form-checkbox"],styles:{"border-radius":vb.none}},{base:["[type='radio']"],class:[".form-radio"],styles:{"border-radius":"100%"}},{base:["[type='checkbox']:focus","[type='radio']:focus"],class:[".form-checkbox:focus",".form-radio:focus"],styles:{outline:"2px solid transparent","outline-offset":"2px","--tw-ring-inset":"var(--tw-empty,/*!*/ /*!*/)","--tw-ring-offset-width":"2px","--tw-ring-offset-color":"#fff","--tw-ring-color":yt(i("colors.blue.600",gt.blue[600]),"--tw-ring-opacity"),"--tw-ring-offset-shadow":"var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)","--tw-ring-shadow":"var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)","box-shadow":"var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)"}},{base:["[type='checkbox']:checked","[type='radio']:checked"],class:[".form-checkbox:checked",".form-radio:checked"],styles:{"border-color":"transparent","background-color":"currentColor","background-size":"100% 100%","background-position":"center","background-repeat":"no-repeat"}},{base:["[type='checkbox']:checked"],class:[".form-checkbox:checked"],styles:{"background-image":`url("${Zn('')}")`,"@media (forced-colors: active) ":{appearance:"auto"}}},{base:["[type='radio']:checked"],class:[".form-radio:checked"],styles:{"background-image":`url("${Zn('')}")`,"@media (forced-colors: active) ":{appearance:"auto"}}},{base:["[type='checkbox']:checked:hover","[type='checkbox']:checked:focus","[type='radio']:checked:hover","[type='radio']:checked:focus"],class:[".form-checkbox:checked:hover",".form-checkbox:checked:focus",".form-radio:checked:hover",".form-radio:checked:focus"],styles:{"border-color":"transparent","background-color":"currentColor"}},{base:["[type='checkbox']:indeterminate"],class:[".form-checkbox:indeterminate"],styles:{"background-image":`url("${Zn('')}")`,"border-color":"transparent","background-color":"currentColor","background-size":"100% 100%","background-position":"center","background-repeat":"no-repeat","@media (forced-colors: active) ":{appearance:"auto"}}},{base:["[type='checkbox']:indeterminate:hover","[type='checkbox']:indeterminate:focus"],class:[".form-checkbox:indeterminate:hover",".form-checkbox:indeterminate:focus"],styles:{"border-color":"transparent","background-color":"currentColor"}},{base:["[type='file']"],class:null,styles:{background:"unset","border-color":"inherit","border-width":"0","border-radius":"0",padding:"0","font-size":"unset","line-height":"inherit"}},{base:["[type='file']:focus"],class:null,styles:{outline:["1px solid ButtonText","1px auto -webkit-focus-ring-color"]}}],s=o=>a.map(u=>u[o]===null?null:{[u[o]]:u.styles}).filter(Boolean);n.includes("base")&&e(s("base")),n.includes("class")&&t(s("class"))}});xb.exports=NO});var Sb={};Ae(Sb,{default:()=>$O});var $O,Cb=C(()=>{l();$O=[kb()]});var _b={};Ae(_b,{default:()=>zO});var Ab,zO,Ob=C(()=>{l();wi();Ab=X(Si()),zO=et(Ab.default)});l();"use strict";var jO=Xe(xm()),VO=Xe(ge()),UO=Xe(pb()),WO=Xe((Cb(),Sb)),GO=Xe((fu(),uu)),HO=Xe((Ob(),_b)),YO=Xe((mi(),as)),QO=Xe((qn(),In)),JO=Xe((xs(),lf));function Xe(r){return r&&r.__esModule?r:{default:r}}console.warn("cdn.tailwindcss.com should not be used in production. To use Tailwind CSS in production, install it as a PostCSS plugin or use the Tailwind CLI: https://tailwindcss.com/docs/installation");var es="tailwind",cu="text/tailwindcss",Eb="/template.html",Ct,Tb=!0,Pb=0,pu=new Set,du,Db="",Ib=(r=!1)=>({get(e,t){return(!r||t==="config")&&typeof e[t]=="object"&&e[t]!==null?new Proxy(e[t],Ib()):e[t]},set(e,t,i){return e[t]=i,(!r||t==="config")&&hu(!0),!0}});window[es]=new Proxy({config:{},defaultTheme:GO.default,defaultConfig:HO.default,colors:YO.default,plugin:QO.default,resolveConfig:JO.default},Ib(!0));function qb(r){du.observe(r,{attributes:!0,attributeFilter:["type"],characterData:!0,subtree:!0,childList:!0})}new MutationObserver(async r=>{let e=!1;if(!du){du=new MutationObserver(async()=>await hu(!0));for(let t of document.querySelectorAll(`style[type="${cu}"]`))qb(t)}for(let t of r)for(let i of t.addedNodes)i.nodeType===1&&i.tagName==="STYLE"&&i.getAttribute("type")===cu&&(qb(i),e=!0);await hu(e)}).observe(document.documentElement,{attributes:!0,attributeFilter:["class"],childList:!0,subtree:!0});async function hu(r=!1){r&&(Pb++,pu.clear());let e="";for(let i of document.querySelectorAll(`style[type="${cu}"]`))e+=i.textContent;let t=new Set;for(let i of document.querySelectorAll("[class]"))for(let n of i.classList)pu.has(n)||t.add(n);if(document.body&&(Tb||t.size>0||e!==Db||!Ct||!Ct.isConnected)){for(let n of t)pu.add(n);Tb=!1,Db=e,self[Eb]=Array.from(t).join(" ");let{css:i}=await(0,VO.default)([(0,jO.default)({...window[es].config,_hash:Pb,content:[Eb],plugins:[...WO.default,...Array.isArray(window[es].config.plugins)?window[es].config.plugins:[]]}),(0,UO.default)({remove:!1})]).process(`@tailwind base;@tailwind components;@tailwind utilities;${e}`);(!Ct||!Ct.isConnected)&&(Ct=document.createElement("style"),document.head.append(Ct)),Ct.textContent=i}}})(); +`)); + } + cb.exports = or; + function or(...r) { + let e; + if ( + (r.length === 1 && TO(r[0]) + ? ((e = r[0]), (r = void 0)) + : r.length === 0 || (r.length === 1 && !r[0]) + ? (r = void 0) + : r.length <= 2 && (Array.isArray(r[0]) || !r[0]) + ? ((e = r[1]), (r = r[0])) + : typeof r[r.length - 1] == "object" && (e = r.pop()), + e || (e = {}), + e.browser) + ) + throw new Error("Change `browser` option to `overrideBrowserslist` in Autoprefixer"); + if (e.browserslist) + throw new Error("Change `browserslist` option to `overrideBrowserslist` in Autoprefixer"); + e.overrideBrowserslist + ? (r = e.overrideBrowserslist) + : e.browsers && + (typeof console != "undefined" && + console.warn && + (nu.red + ? console.warn(nu.red(fb.replace(/`[^`]+`/g, (n) => nu.yellow(n.slice(1, -1))))) + : console.warn(fb)), + (r = e.browsers)); + let t = { ignoreUnknownVersions: e.ignoreUnknownVersions, stats: e.stats, env: e.env }; + function i(n) { + let a = ub, + s = new AO(a.browsers, r, n, t), + o = s.selected.join(", ") + JSON.stringify(e); + return (su.has(o) || su.set(o, new _O(a.prefixes, s, e)), su.get(o)); + } + return { + postcssPlugin: "autoprefixer", + prepare(n) { + let a = i({ from: n.opts.from, env: e.env }); + return { + OnceExit(s) { + (PO(n, a), + e.remove !== !1 && a.processor.remove(s, n), + e.add !== !1 && a.processor.add(s, n)); + }, + }; + }, + info(n) { + return ((n = n || {}), (n.from = n.from || h.cwd()), EO(i(n))); + }, + options: e, + browsers: r, + }; + } + or.postcss = !0; + or.data = ub; + or.defaults = SO.defaults; + or.info = () => or().info(); + }); + var hb = v((rq, db) => { + l(); + db.exports = { + aqua: /#00ffff(ff)?(?!\w)|#0ff(f)?(?!\w)/gi, + azure: /#f0ffff(ff)?(?!\w)/gi, + beige: /#f5f5dc(ff)?(?!\w)/gi, + bisque: /#ffe4c4(ff)?(?!\w)/gi, + black: /#000000(ff)?(?!\w)|#000(f)?(?!\w)/gi, + blue: /#0000ff(ff)?(?!\w)|#00f(f)?(?!\w)/gi, + brown: /#a52a2a(ff)?(?!\w)/gi, + coral: /#ff7f50(ff)?(?!\w)/gi, + cornsilk: /#fff8dc(ff)?(?!\w)/gi, + crimson: /#dc143c(ff)?(?!\w)/gi, + cyan: /#00ffff(ff)?(?!\w)|#0ff(f)?(?!\w)/gi, + darkblue: /#00008b(ff)?(?!\w)/gi, + darkcyan: /#008b8b(ff)?(?!\w)/gi, + darkgrey: /#a9a9a9(ff)?(?!\w)/gi, + darkred: /#8b0000(ff)?(?!\w)/gi, + deeppink: /#ff1493(ff)?(?!\w)/gi, + dimgrey: /#696969(ff)?(?!\w)/gi, + gold: /#ffd700(ff)?(?!\w)/gi, + green: /#008000(ff)?(?!\w)/gi, + grey: /#808080(ff)?(?!\w)/gi, + honeydew: /#f0fff0(ff)?(?!\w)/gi, + hotpink: /#ff69b4(ff)?(?!\w)/gi, + indigo: /#4b0082(ff)?(?!\w)/gi, + ivory: /#fffff0(ff)?(?!\w)/gi, + khaki: /#f0e68c(ff)?(?!\w)/gi, + lavender: /#e6e6fa(ff)?(?!\w)/gi, + lime: /#00ff00(ff)?(?!\w)|#0f0(f)?(?!\w)/gi, + linen: /#faf0e6(ff)?(?!\w)/gi, + maroon: /#800000(ff)?(?!\w)/gi, + moccasin: /#ffe4b5(ff)?(?!\w)/gi, + navy: /#000080(ff)?(?!\w)/gi, + oldlace: /#fdf5e6(ff)?(?!\w)/gi, + olive: /#808000(ff)?(?!\w)/gi, + orange: /#ffa500(ff)?(?!\w)/gi, + orchid: /#da70d6(ff)?(?!\w)/gi, + peru: /#cd853f(ff)?(?!\w)/gi, + pink: /#ffc0cb(ff)?(?!\w)/gi, + plum: /#dda0dd(ff)?(?!\w)/gi, + purple: /#800080(ff)?(?!\w)/gi, + red: /#ff0000(ff)?(?!\w)|#f00(f)?(?!\w)/gi, + salmon: /#fa8072(ff)?(?!\w)/gi, + seagreen: /#2e8b57(ff)?(?!\w)/gi, + seashell: /#fff5ee(ff)?(?!\w)/gi, + sienna: /#a0522d(ff)?(?!\w)/gi, + silver: /#c0c0c0(ff)?(?!\w)/gi, + skyblue: /#87ceeb(ff)?(?!\w)/gi, + snow: /#fffafa(ff)?(?!\w)/gi, + tan: /#d2b48c(ff)?(?!\w)/gi, + teal: /#008080(ff)?(?!\w)/gi, + thistle: /#d8bfd8(ff)?(?!\w)/gi, + tomato: /#ff6347(ff)?(?!\w)/gi, + violet: /#ee82ee(ff)?(?!\w)/gi, + wheat: /#f5deb3(ff)?(?!\w)/gi, + white: /#ffffff(ff)?(?!\w)|#fff(f)?(?!\w)/gi, + }; + }); + var gb = v((iq, mb) => { + l(); + var au = hb(), + ou = { whitespace: /\s+/g, urlHexPairs: /%[\dA-F]{2}/g, quotes: /"/g }; + function DO(r) { + return r.trim().replace(ou.whitespace, " "); + } + function IO(r) { + return encodeURIComponent(r).replace(ou.urlHexPairs, RO); + } + function qO(r) { + return ( + Object.keys(au).forEach(function (e) { + au[e].test(r) && (r = r.replace(au[e], e)); + }), + r + ); + } + function RO(r) { + switch (r) { + case "%20": + return " "; + case "%3D": + return "="; + case "%3A": + return ":"; + case "%2F": + return "/"; + default: + return r.toLowerCase(); + } + } + function lu(r) { + if (typeof r != "string") throw new TypeError("Expected a string, but received " + typeof r); + r.charCodeAt(0) === 65279 && (r = r.slice(1)); + var e = qO(DO(r)).replace(ou.quotes, "'"); + return "data:image/svg+xml," + IO(e); + } + lu.toSrcset = function (e) { + return lu(e).replace(/ /g, "%20"); + }; + mb.exports = lu; + }); + var uu = {}; + Ae(uu, { default: () => MO }); + var yb, + MO, + fu = C(() => { + l(); + wi(); + ((yb = X(Si())), (MO = et(yb.default.theme))); + }); + var kb = v((sq, xb) => { + l(); + var Zn = gb(), + BO = (qn(), In).default, + wb = (fu(), uu).default, + gt = (mi(), as).default, + [FO, { lineHeight: LO }] = wb.fontSize.base, + { spacing: Je, borderWidth: bb, borderRadius: vb } = wb; + function yt(r, e) { + return r.replace("", `var(${e}, 1)`); + } + var NO = BO.withOptions(function (r = { strategy: void 0 }) { + return function ({ addBase: e, addComponents: t, theme: i }) { + let n = r.strategy === void 0 ? ["base", "class"] : [r.strategy], + a = [ + { + base: [ + "[type='text']", + "input:where(:not([type]))", + "[type='email']", + "[type='url']", + "[type='password']", + "[type='number']", + "[type='date']", + "[type='datetime-local']", + "[type='month']", + "[type='search']", + "[type='tel']", + "[type='time']", + "[type='week']", + "[multiple]", + "textarea", + "select", + ], + class: [".form-input", ".form-textarea", ".form-select", ".form-multiselect"], + styles: { + appearance: "none", + "background-color": "#fff", + "border-color": yt(i("colors.gray.500", gt.gray[500]), "--tw-border-opacity"), + "border-width": bb.DEFAULT, + "border-radius": vb.none, + "padding-top": Je[2], + "padding-right": Je[3], + "padding-bottom": Je[2], + "padding-left": Je[3], + "font-size": FO, + "line-height": LO, + "--tw-shadow": "0 0 #0000", + "&:focus": { + outline: "2px solid transparent", + "outline-offset": "2px", + "--tw-ring-inset": "var(--tw-empty,/*!*/ /*!*/)", + "--tw-ring-offset-width": "0px", + "--tw-ring-offset-color": "#fff", + "--tw-ring-color": yt(i("colors.blue.600", gt.blue[600]), "--tw-ring-opacity"), + "--tw-ring-offset-shadow": + "var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)", + "--tw-ring-shadow": + "var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)", + "box-shadow": + "var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)", + "border-color": yt(i("colors.blue.600", gt.blue[600]), "--tw-border-opacity"), + }, + }, + }, + { + base: ["input::placeholder", "textarea::placeholder"], + class: [".form-input::placeholder", ".form-textarea::placeholder"], + styles: { + color: yt(i("colors.gray.500", gt.gray[500]), "--tw-text-opacity"), + opacity: "1", + }, + }, + { + base: ["::-webkit-datetime-edit-fields-wrapper"], + class: [".form-input::-webkit-datetime-edit-fields-wrapper"], + styles: { padding: "0" }, + }, + { + base: ["::-webkit-date-and-time-value"], + class: [".form-input::-webkit-date-and-time-value"], + styles: { "min-height": "1.5em" }, + }, + { + base: ["::-webkit-date-and-time-value"], + class: [".form-input::-webkit-date-and-time-value"], + styles: { "text-align": "inherit" }, + }, + { + base: ["::-webkit-datetime-edit"], + class: [".form-input::-webkit-datetime-edit"], + styles: { display: "inline-flex" }, + }, + { + base: [ + "::-webkit-datetime-edit", + "::-webkit-datetime-edit-year-field", + "::-webkit-datetime-edit-month-field", + "::-webkit-datetime-edit-day-field", + "::-webkit-datetime-edit-hour-field", + "::-webkit-datetime-edit-minute-field", + "::-webkit-datetime-edit-second-field", + "::-webkit-datetime-edit-millisecond-field", + "::-webkit-datetime-edit-meridiem-field", + ], + class: [ + ".form-input::-webkit-datetime-edit", + ".form-input::-webkit-datetime-edit-year-field", + ".form-input::-webkit-datetime-edit-month-field", + ".form-input::-webkit-datetime-edit-day-field", + ".form-input::-webkit-datetime-edit-hour-field", + ".form-input::-webkit-datetime-edit-minute-field", + ".form-input::-webkit-datetime-edit-second-field", + ".form-input::-webkit-datetime-edit-millisecond-field", + ".form-input::-webkit-datetime-edit-meridiem-field", + ], + styles: { "padding-top": 0, "padding-bottom": 0 }, + }, + { + base: ["select"], + class: [".form-select"], + styles: { + "background-image": `url("${Zn(``)}")`, + "background-position": `right ${Je[2]} center`, + "background-repeat": "no-repeat", + "background-size": "1.5em 1.5em", + "padding-right": Je[10], + "print-color-adjust": "exact", + }, + }, + { + base: ["[multiple]", '[size]:where(select:not([size="1"]))'], + class: ['.form-select:where([size]:not([size="1"]))'], + styles: { + "background-image": "initial", + "background-position": "initial", + "background-repeat": "unset", + "background-size": "initial", + "padding-right": Je[3], + "print-color-adjust": "unset", + }, + }, + { + base: ["[type='checkbox']", "[type='radio']"], + class: [".form-checkbox", ".form-radio"], + styles: { + appearance: "none", + padding: "0", + "print-color-adjust": "exact", + display: "inline-block", + "vertical-align": "middle", + "background-origin": "border-box", + "user-select": "none", + "flex-shrink": "0", + height: Je[4], + width: Je[4], + color: yt(i("colors.blue.600", gt.blue[600]), "--tw-text-opacity"), + "background-color": "#fff", + "border-color": yt(i("colors.gray.500", gt.gray[500]), "--tw-border-opacity"), + "border-width": bb.DEFAULT, + "--tw-shadow": "0 0 #0000", + }, + }, + { + base: ["[type='checkbox']"], + class: [".form-checkbox"], + styles: { "border-radius": vb.none }, + }, + { base: ["[type='radio']"], class: [".form-radio"], styles: { "border-radius": "100%" } }, + { + base: ["[type='checkbox']:focus", "[type='radio']:focus"], + class: [".form-checkbox:focus", ".form-radio:focus"], + styles: { + outline: "2px solid transparent", + "outline-offset": "2px", + "--tw-ring-inset": "var(--tw-empty,/*!*/ /*!*/)", + "--tw-ring-offset-width": "2px", + "--tw-ring-offset-color": "#fff", + "--tw-ring-color": yt(i("colors.blue.600", gt.blue[600]), "--tw-ring-opacity"), + "--tw-ring-offset-shadow": + "var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)", + "--tw-ring-shadow": + "var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)", + "box-shadow": "var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)", + }, + }, + { + base: ["[type='checkbox']:checked", "[type='radio']:checked"], + class: [".form-checkbox:checked", ".form-radio:checked"], + styles: { + "border-color": "transparent", + "background-color": "currentColor", + "background-size": "100% 100%", + "background-position": "center", + "background-repeat": "no-repeat", + }, + }, + { + base: ["[type='checkbox']:checked"], + class: [".form-checkbox:checked"], + styles: { + "background-image": `url("${Zn('')}")`, + "@media (forced-colors: active) ": { appearance: "auto" }, + }, + }, + { + base: ["[type='radio']:checked"], + class: [".form-radio:checked"], + styles: { + "background-image": `url("${Zn('')}")`, + "@media (forced-colors: active) ": { appearance: "auto" }, + }, + }, + { + base: [ + "[type='checkbox']:checked:hover", + "[type='checkbox']:checked:focus", + "[type='radio']:checked:hover", + "[type='radio']:checked:focus", + ], + class: [ + ".form-checkbox:checked:hover", + ".form-checkbox:checked:focus", + ".form-radio:checked:hover", + ".form-radio:checked:focus", + ], + styles: { "border-color": "transparent", "background-color": "currentColor" }, + }, + { + base: ["[type='checkbox']:indeterminate"], + class: [".form-checkbox:indeterminate"], + styles: { + "background-image": `url("${Zn('')}")`, + "border-color": "transparent", + "background-color": "currentColor", + "background-size": "100% 100%", + "background-position": "center", + "background-repeat": "no-repeat", + "@media (forced-colors: active) ": { appearance: "auto" }, + }, + }, + { + base: ["[type='checkbox']:indeterminate:hover", "[type='checkbox']:indeterminate:focus"], + class: [".form-checkbox:indeterminate:hover", ".form-checkbox:indeterminate:focus"], + styles: { "border-color": "transparent", "background-color": "currentColor" }, + }, + { + base: ["[type='file']"], + class: null, + styles: { + background: "unset", + "border-color": "inherit", + "border-width": "0", + "border-radius": "0", + padding: "0", + "font-size": "unset", + "line-height": "inherit", + }, + }, + { + base: ["[type='file']:focus"], + class: null, + styles: { outline: ["1px solid ButtonText", "1px auto -webkit-focus-ring-color"] }, + }, + ], + s = (o) => a.map((u) => (u[o] === null ? null : { [u[o]]: u.styles })).filter(Boolean); + (n.includes("base") && e(s("base")), n.includes("class") && t(s("class"))); + }; + }); + xb.exports = NO; + }); + var Sb = {}; + Ae(Sb, { default: () => $O }); + var $O, + Cb = C(() => { + l(); + $O = [kb()]; + }); + var _b = {}; + Ae(_b, { default: () => zO }); + var Ab, + zO, + Ob = C(() => { + l(); + wi(); + ((Ab = X(Si())), (zO = et(Ab.default))); + }); + l(); + ("use strict"); + var jO = Xe(xm()), + VO = Xe(ge()), + UO = Xe(pb()), + WO = Xe((Cb(), Sb)), + GO = Xe((fu(), uu)), + HO = Xe((Ob(), _b)), + YO = Xe((mi(), as)), + QO = Xe((qn(), In)), + JO = Xe((xs(), lf)); + function Xe(r) { + return r && r.__esModule ? r : { default: r }; + } + console.warn( + "cdn.tailwindcss.com should not be used in production. To use Tailwind CSS in production, install it as a PostCSS plugin or use the Tailwind CLI: https://tailwindcss.com/docs/installation" + ); + var es = "tailwind", + cu = "text/tailwindcss", + Eb = "/template.html", + Ct, + Tb = !0, + Pb = 0, + pu = new Set(), + du, + Db = "", + Ib = (r = !1) => ({ + get(e, t) { + return (!r || t === "config") && typeof e[t] == "object" && e[t] !== null + ? new Proxy(e[t], Ib()) + : e[t]; + }, + set(e, t, i) { + return ((e[t] = i), (!r || t === "config") && hu(!0), !0); + }, + }); + window[es] = new Proxy( + { + config: {}, + defaultTheme: GO.default, + defaultConfig: HO.default, + colors: YO.default, + plugin: QO.default, + resolveConfig: JO.default, + }, + Ib(!0) + ); + function qb(r) { + du.observe(r, { attributes: !0, attributeFilter: ["type"], characterData: !0, subtree: !0, childList: !0 }); + } + new MutationObserver(async (r) => { + let e = !1; + if (!du) { + du = new MutationObserver(async () => await hu(!0)); + for (let t of document.querySelectorAll(`style[type="${cu}"]`)) qb(t); + } + for (let t of r) + for (let i of t.addedNodes) + i.nodeType === 1 && i.tagName === "STYLE" && i.getAttribute("type") === cu && (qb(i), (e = !0)); + await hu(e); + }).observe(document.documentElement, { attributes: !0, attributeFilter: ["class"], childList: !0, subtree: !0 }); + async function hu(r = !1) { + r && (Pb++, pu.clear()); + let e = ""; + for (let i of document.querySelectorAll(`style[type="${cu}"]`)) e += i.textContent; + let t = new Set(); + for (let i of document.querySelectorAll("[class]")) for (let n of i.classList) pu.has(n) || t.add(n); + if (document.body && (Tb || t.size > 0 || e !== Db || !Ct || !Ct.isConnected)) { + for (let n of t) pu.add(n); + ((Tb = !1), (Db = e), (self[Eb] = Array.from(t).join(" "))); + let { css: i } = await (0, VO.default)([ + (0, jO.default)({ + ...window[es].config, + _hash: Pb, + content: [Eb], + plugins: [ + ...WO.default, + ...(Array.isArray(window[es].config.plugins) ? window[es].config.plugins : []), + ], + }), + (0, UO.default)({ remove: !1 }), + ]).process(`@tailwind base;@tailwind components;@tailwind utilities;${e}`); + ((!Ct || !Ct.isConnected) && ((Ct = document.createElement("style")), document.head.append(Ct)), + (Ct.textContent = i)); + } + } +})(); /*! https://mths.be/cssesc v3.0.0 by @mathias */ diff --git a/electron/build/icon.png b/electron/build/icon.png index aea1c67e2096792226e1262be4a3c1c190f0375c..05ae15263f1c388a06bf7d6adf5d8ee2e36165c3 100644 GIT binary patch literal 296023 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
  • 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 z zjYHp~otJ%X)8Qd6OBb;Xg|=>8pc!`|x{|zs`r5Nqtnd>5M919mZtXH`&)N;{*wxvF z;{6C8JX@6kax<2#W+~sIs{QknsH%F_OY(9y9k1hOBJ2Kdw7N6iwy&ps;&^BEJsW$@ zBX2>Whq~aowgPGznWhu{8bqGKZRy36DKnnwwNef~ zyy$~>!`%&ne}_c2m!lu7rr5M10Flz7e({^4h}{DEqTE{USEoKpoT*S|I-(Y`M-kHHsq?ijPvHlImqx@JsX7C^T#LW~Q1&|Cqy-IgOQ*GA8*RJ! zt=|v$_MnHN?uX0KV{P7t2b_Gt@yFK;$=(udYXUSMJA*Qbn&N#i&^{OsTGJ%Rh(zhp z`TevshN`VhyvJCqtlT-U>yNEs^Yr$nAZRi)G{nU~7NpMr?gu_-&=8=J6Kq9CM^CP- zBt8TM?NGkx831xmsv)cqcT{?iRk4%)?_Yjxg0;!rZt#*IxX z&F0r6$diq?`$of$L-tNATObV#10+y%cT;4TrK%mp{;P0UMPl4%K`~M!sAY3_D89HO zsOsfiv)`3DQ`x6*N4FdWWqdi2C>aq1TB1nY#4bp0E|Ytek{>~mE9$Bms#p#-W;~{y zy|bjD1B;Nb@YnoubaHZX62!*wZ4ZCS7>FH7j0_D4;=}jv5?m87Y%@FG7nWaWQ(xpr z(BVl^y@+7Pi6{%8CM0~WDRJqWyJu2D!OpXUGP53rBa7`(wg-E#w;}DLgtl~MFoI;W zETK%r)-VgBu8K!i^vcX_^qo28^UOcz!ics$PxZcz~=(c!?c?p=cw7e~fj+c++VLI>5!GRIbp5OxHS#JI- zz%3FPeq1kyfB@w2@$p8<)Rgk-U@0z0RP@CT<@b{l9C`-&)l>gfbfnyXK%Df12qrjC z^k=j)3U;j}hvJN&nc%1r&nX_$ck;F_JAS808LKL@KIM6fN53ul2AHnWV=!^N8#Yo4Gkuy=A#IWjrHowUOMPhi!u80^Yfoufq^r2MQTw@QW7o(2F7c& z^MI=(Syfebf7o&VzzL3=yc`_rb-1K&AUtC_79v`KTHe^RYpwUXUgWZY%GKY-sgq?D zJq&3`Z#FxKDLS5`NO}2di!Qv`tU$g9G+sJ<2V#e<fFs}Wve#)~ zZJ_Qf^=ChtED>K9;0&$$UFA)ET8Gn{aL`Ui#+yXNtJ&y<$mVt#Eslziy{+BP7V!pFKf4YnCNP^w!-4&hd(LZ_tgr>HN$7|i6a*YSLbC`{^+szoiXvFif^W@r!vIM}2peu!U zh&cpOfSkaaNg8##8Ri_1&%m5!iaH69FC2Xk>99S<)k zD58pXQKzS+V7F9+n8?%3Y?oqoCgMDajT1Rv%A3YTH)%i~4uF?+8&^tP3OkS#oo({6 zYR)-KPxeGmd&Z76G^E0z+G#qV=TUAsf?bvBB629TM0sx&naJsLmP^0&Q&-}eZ@YZC z6s-vvze|}4S1Ib)S0w85XChCp%I|wK<*qv|UI6i!Ev>CJ?wg99K0aTXo6`tgXlU|Z zDJ%X_ri-hq{NiF1QBl!ftv>7x$G>7k1Fp=>aw%zPX@Nuy;Rh)|v2tD)&Yn@Is?Hj3 zB6j}QRj@PC_t=LC8qj&W2#c)`fd zz_JbK(>TEdw6%sEZJUKZ`&K8hb4!!(_T`oeS>5aQgaV#zmX*FmFZ(th5z-%ycBGSb zNI+oTF{nWRtl&qB^iPY!`TDpn9|s4PZa|B0H?7m@qoSjUBd?cQeJr=DmVVXxVBg-| za`5pXSI?q^aOlVIN1`F3@l=cJ$E#|uRpyj-SmjhIzDeKmsF_Qngmv6sw-1QOi5l8P z_ui#dB{c;06>U2BXWwX9DG@F_fG8-{&`*V zbgZb_W>EW!Q$~wg>KEI}()tT*T@K;9@a zND9!M{0^KBgfAnqHQ2$A1ajdTpA|8T3z&JJBbiAjc97pDqb5C;x3neNnVvS@jj*xQKx=TmCmr48-v8@VK%Q_KpiYlbds$gSmS28efe1 z%Xl@B;1^QiN7z!ZXL)xBb1mboInJk?xrkFReETiTUC`9ik6a{8F@I~a%plt zZG1|>Pd=Aw`BuE5Yet>x<05nzxMX_%in^yIP*@8gk__@qq!X{k6*Xzs4RZb3BJa(J zvT9!Y7sTjFag2WQ*600X9vE2S_pW5Y*Q<8U&fW#9e_9b{EId6478;zoO&`yQ@BQ|5 z+OF4>e1q=xUy!|!_*#V3k?x<`LfO$G=X=jPr?aldS*TUOW11Lg+p%QNBe0yAk=Q1*u!e> z(P2!{pdm_^vhqhzqud~FUKAigw|5=L!>cUC>mmgviIuPpltTrLXJ-(KBAeUB5U$rcYq zMZXdY^JOJpSigmDcPBL9RL#**5E!2=6t$Hw4Z7D4`QrCriu8LJYSTy%gp*Pfvok`M z&yBB!SDQ*kE+sF|FebP?Dsa5$;nqiDYt|b}h{c}*L`FNmy~D#^+C-7J;)_0%6u!Sz z0R@!^@_4B{itXZr*v5OArlPPdQLQi=30#PUEWz%jJ45S3O%!BBAFiaDRbHo{hxXn_O6kGjwSuoL%|)Y@y-dS^X%vngc0r zi3<~7Marw=7ctkLMaLIIFwv?DwuNJiI;xH^_Ouh=+s~Se1=;Cxi=V2Rzqxla*#;og z=Mcw!8{ESZEchM%l?O9|L2gU>MqQpfo`r4YT^xJIi>$1yzhljun4RUP{An6+s6EZs zD2>TSJ>jaRhZ4*9y9t!Or8Idm-B^21mobxzMMgH^0aO4lnEOLb1Q*LPZP7PM@6!5G zC)<|Y5{8Qn(u)*rJCR1*{LA}>ke%2~k3iseOswwHnjIM_9lMGVbs z)v7fxc9Od*hy1GU=DKe3hx``uUSgMnkFLYiKE;2A^>w^`+YF}T;BKR=iJ`7*;92*` zdB9jc&xYl;w=eb5;{mQuy%ZAz2rO%NC z;0_+{`KR4H^6G={Kj1|*y~qd1C;n7FFPM8nO@a%nGPhsab~Gv7^=Yo`VNRQ%P^VWM zy$3xbSFo(*P9;B-x2vPv&JLjHIJqfzn+F$L-!@|bHb-M1Rq)AoBT4?G(j^2X1!JdUH?Gb{opW}A1nMk%mP`71?#PD^OmeI7Ze+9GleeRgyUtQj-BzR+t4JWtv*2BVVhl+IR~Din|^Ncsz-JjPY|U5Yg9_W{tw19#&d$ z9QWm%78FrsL8EK|yg@(om*aN#vYDCyHytY3zQ&oGlC7ES(aI36sdmeD_!%oyBR!R5 zK5=3~tZf(M(&e>s!R!dqVC|r{d+AW*xM}-S~OP!Coh4FBj>Oje2opq+k5ox z*=H>Gyc$WFsDQ8DqxSa;u+C`iF@f%0`ac>s=??oHj=fek9!PZOAF%46A8Dq!&^2d` zw&%{wC3;iy5E6W5ZdFx4j5h&nOA6SQWutp`OV&P;>m2h|T-g@frz1<%&R^@*Hzk_vzjtJ&WIBf~_&vb$B%}nG1&z5wnhHmoBu)ZJW zs1M(b=Hn((Pj{l1k#v84S=H~iowco@`3DIk)(5uavmVPLhM@`jQgn_}(!#)7zAHtz}qG(nqz!C5J2P0F%Udp)?a6P7(07KO3vXujplGmhEk$-3J14 z(<$Z?Pelz+S4Sy(j)Mb)L-^wV;9&lFd%1raqZ&vS9@Or8(a}mpz{<efrWz4Q1Tnpcx|im{+Lj&bv=w4k=@h)b;bXb`q&6F^;Hx=@zcde3b?_x9#qtk+gL z^=Kiis=;Q_b3I<*>X)Ul9r7QYOA^iwI1&sz`8LcU!WU^a+oILzlRG_g(JS8l+2l>* zEw>{a%PwI&p(ku(Z$8@vBZfBle2i9AfNf&JJt(I8#wg%b5lR5ZTrKA8D@vI=JW4{n%JLO(%EFpq>`>AVg`b_lqWXY_?V`>j`Nc?>zd!`1BxL3ekYJY2Dp zr*9O}9)zcF=Sl18dA^jl6ZVt2F{%W0*Z6k#eaS1sIFgaMIhe0UKla@g<`m$IY)Oum zoV=K>XcJW;|JeG$*+v zH#SDFtmE(NryIVg!1=O^149IMR^D`+#NfKpt(xB$@;&L2Z+d3!0J;o09}{?H+ji=E z{U9d)Q%RhX%P*zqW~!?A(G{NS z3CXZX@wV$uV(V*m>BAiJ0Sa$v33;9$nd=r=Bg^(KP^|PBOTN17U#26l&N>v;f4%+V z6_;pOjWPSWG-VS(#q?_Uz)qwF(Z$K~-dXA+{*w z`?50`-F}!%I(?D9sl2TRd21a$u3!%bM&P-;c=sj$Q`I79aQ72F-)gjJCo<-x*QPTX zfbxx(A7wgfp7W+T&LBIF($vzDLQnO|`N+dl=!oScP|m*(y5KUGXk<5)7$=;L+nw)V z%&qq8&gd-L%TAnMiI@FGAu}RFh96+s3uefI7&<><28w0xra%U&26st}E|Xo>CT&d^ zeKcR|*XQFu-5iE=QKD`$WCqpmodyr3Ey2CN`%aBFssHZK z|9Q&8Wnt6m?S9_A|L5Kq$UvF#o&RZ`s%dzNX+ZlTsK(LVAGvYGLp;GK1ofw9HKUIQ z;B8~8_OHu3TL@Zx4tr`7AD?Hp&@+~O7OUgUqLnmOpW&ab_Zc316jim>?_8?c-QYsL zShEgDvL@9{zHCPrqTq6y{B31>p2}~)`1WErqMWo z@p!m%mm^9cebzZ0$l0P7j@nqbzQL(?$LeW0(Y>5{Qx~c$egG{Km)UXQE11`RQqWix@cJX zvEWy1Cc$n$Ukjv-oM{tx_;XNtH} zqRZz&^_Ynx?=CKdYdUyzS`N4uiNjP4Ru6Q>h?g7OHJWa6m%VqQF6&v1`K2M=C|8IB zcii>?p%VfWfhVd0X9Kk4^K^hu;1hoN<4(+t*JPoid=ccPWemb;d^ot%8|K`Vks)zf zY9X}Ed9Z<`+e~|pJfVGPWk~$^Z|-n}A%SJ9z)eSmB1J6c^%{1X(764k2=q*l9q8Z? zcNNSWA5RDTVZ6!jUSd--0R|d(2v{-jF{iV2qe~D@c{JjLKj(?L$VTcfoZO2dEgQ~1a3dga`H=U-MFI5S|F4O=(2_BS7zFl7cq?g3SJXj zA&C7}isaO5HSS&E=+wilDjq+k;;lIM%cT(fd-_6?^aJA0;bWzO#B2tDx zxb$l*o@EDIk$CdWSd{q$*t-|O?f(kXVjL>^b0z{=kx0cYnu{8S+U|Hi@6R>V9r$&A zu`kuy!0x|VA#^l?ZAY=PO}_Av%y^;r>R3Wv8ZJ@f9%pZFk8JS|XB)g0umX?fk0lgg z-R1JLlXJ_lUJg2Wt+j|^)hIQ-WT(Demrlorhw@6Ah^nOWGM^%6_j?OdIw(6^PW_eN z#djGlAn8%c84}2<^UpMRUV*Rwod%x$`=TfKREU+o! z0(!v2Iz)WWk_kJM`l9-KkRe;b((+6AUwT&Xsp;ZlPQM3x=ibn*gTq^ayJ>v4Ba-6Z z8|(b}H63j04|*JqJX zt}F~^b)e6wa~G2SIbi`_{dhvmD(HtQ_JO2Y&*}6>)!h2}nY>XT5rexwO=37bWe*xX zy`=bN|4Iy2Gb*rM_c3?hKr%5|W39I`skN8RZ?fi3)9=_)Jh#eCN zDQVYBRUwkvu9V{*HYN2qw!aK@$i;~ zrW>jiLEfwdO3*+*7&k139n>wcn(PTw$(NmxFKABb+-^2s%9~%li++|xRuupRuQ0w5 zpxg^XO41 zC&R@p>{)-FdAZEO!NavTa4Y6}8hL$I{DhpYqvvxawHUbFe%-$x{7$Cp@%d&1PSbW# zj>S^CGm3$nOkLgKVlzHNRv=eh6x(#2cOiYN&YQ#$Wuu0tWCr2{dDH8K9i3pxAag<> z_S-syRP7E^ub@S_Llk53ces?t-Ij@>L#`?^8y^BF z{YPqCAJYSAICc{Av2q(Gh*^ci_iri|h`gyu>eLK)!2UEPR*0=eIvk+sPcE_w4Rl z)cL>#lGH=%$%!ApT`YjHqD}MAm5O zbN+5fJ5U64ku=Y1!y$_^p|TxgtL4!r56IqK`0}fMY7 zm^Ag*C0fTtFZ-V|-RgH6pcI;cLJ>mhvkc3v^s-BjGJUuo(U*oZng=*!eYYpS0@n*Ji`42XGLPP|U^#s!lkjH)knsTf4=71%(g7>ywdo zrN>4dtQFd0m7Xr!dY&&|OdJksb2jp9k%fNSYvSf-Df13PJRE%VutyA-m@`Uz*|?~7 z=KKL@a*a2CaSgRpT`-UbafGTmvn@59J1*ZALBH;nbURgkDRzNd@HzG<0VFjH^viYL z9%oD#P=3GozI-!CLR3#aMW`Ln52RA}R9F;=*$&D=-;`+q?C82X;$~wmxdzyR{`E)a zrt1=|fc8!NqI$QByBIJodU6x^m-4yKHFzW*I~u;sX(4V#^Z1835_{HEr_gceP9;> zEMCcgVuiUDr)cR)Y8nF*ohqZ4)}vcf<;#u)J>R}w)|h!Kz8WtbAFC$SXJ!)Oxv4H* zj`2#W-cGvXEcunYQ=Odna1pqP=7BIBpmXt_0JvrNOQ19?x6x7O?4P7<4OtR|9J8b= zYgA`>+ja>8j%g94X|d{~Aa*x`Hya;M*C`)x@B| z=lZzddO@tP=|Hn>rsMu;IA0Dvz)I)ytafCtkuz&**Y5_+2KK)y);?N|_C1l@_&G9V+;!Z+FQGa>; zg{8zl+oCaFoX6r=keY_(ck8Ti^wF5NGWJygy&$D;q@BHfzy|LChX{Z7t94SY5hZp5 z4I+%4X8jxFlHbFBoOY$%tuK*rLq#<>TSqO8jpQRkzkLp90v%aKu{yhP+?(_JQq?(ToJymm}9O z>DVyWC?z~t{%Zhq_ZTmBt&d~@2~HVy+{ff1f(sP5BGEH|=6M#W+S&$+m3b{ccyc&{ zjF(QLVgwDaHXK~_DS7c*^-SOUn$)9}kLeq}O@y)T7Qodxo78G& zdGaA_Twvn!JL3i0;=cE(6uqBW`Lz}YBLR$8O+vHMWK$kI&cde{{+|vK^=-$eLaydv<6N_3!Dulbt!AVaR;Yr~Y)w*O+x0 zX+!#4`O>jFp5Iy0!J&Kgi9FLsQ6CK z*TV_SXnTs|6+viEctgx?N0#q#@9~dk#74in=>Ir9Z`CuM7+Voa@|;jG(UYL6wl>dC z?p)x=yqh1#)+Kw~h64=}*8E6@-I?AGi~Q-;Zza@B*jnEj3co~JZaEI!9t~+FaI}A_ zLp&V#RWHgTgvyS0y^0Iby>UHbo_>Mf(H?7DDaQo6fKNu|3RlvJdCvX{@Rtkf(3 z3PBtWy6&Tk9+!=Ks-H4`lzu7ux%7&KFXOMpZ&n=()57q-Rn-|F6^2UT%?ec2oNEVt z8#GDy=JR-#@}5D4?4$o46tNr2ew^4nu7#v=xXyO;J*8jQ-1f3A%W3^;B#`;1m4z^p z9oC{JHnL`3_Dh|vsK`)#b9HnitP&*510 za^KP213=N=+BP+R5)qA;-vDx*>rb9*4D^_d@nyFKo&L1M>nuDVAs>@HKa58x#nF(a z4b?@o;`K2Nk!jcqUmaKQKJe}Rdi}coQ@1d@mwjD-miGe>m2;s!?&j0#?TLH2l)io@ zv{dp;5aD5$4;yyIyeX_Ax$GMcvFheI*o8lXIgF$uB`uxG&CR{hbn1h&8K__Mc1&|J zVUgand=qi`H<*7(+jxn^@3Kw>MM5l_HDDQ`;RjxaiW4H<<@EC&N3L#Pt1E?;%dMyf zeQnx2R3qXSC;pdApBk?)h5tPa$Cg}#o%+KUW_o1M9Wu}D-y)2){eBl>X=ztJe0s69 zg*Mi`liV`w#s*JIE0|)P#($TBL9Al+(>hgb%whzu_j6c*=nAm6Z(!JAQk)O@s#gp= zB$DpYcADFNb1Z7Btt>eEk20)SMMJ&23No?#@@EqOnwhI32bmuFmFhQ+6hxy{o*u=7 z2*+SIpm4o3o7cH3&hOtdIm#XkJ6Ysb!7||JkF#=63W71-a%(BycqHnLgVQMc9{=IN z@;P*(gEA#-bBK4BQ@N~iU;KI{1pUSuwsr-BG5FFyO!1lh&-@}QTJbL0vp`}ZnTl`v z?v?M9g)W!hGLJ|FnS;pQYoFa;#h=Q+p8wBR2ZuuE{?E>6ZMQL}o12AM-8EvNo+lO^qwa3k8SnE%@EHqy8Z3ZiDH@;9@LAP;Zx_XfKFqIlH0K2-n>T%Mz zS7~~Gcs9oim)h+(39F4xb<8Gc!Zo|8r9sauM43 zkTVQayBh@=^>vf{%+#k`8DZSM{p-ET$16Zw7p;LoA^q{EG;JWj(&W1Kt?=Wm4>oV> ziVjJi?!(u+&dFk54_<$e?V~?CVJVkX#&|_rW%~T| z$bWR!J?XT70#p=gg*ryJ#{%OA9$t0 z4dTI}jY6F-ZQhUXWo4LQ#v7I4lmX?r1ddH$llGyD;l|j+!Ui!X(&;xz`0J`u%=QvD zH|4T`EI)m{tA`%vGBxhU@=rA!rt{ZlJ;*&XFmA^yu;uf%&5A(wuBxP(9fs=}X-5kv+auBs?e1dE&qN!F1epv`>D3u)$Dakfz1tkKC}(Dq zc;sB>-OD_OEOfE_HsvGZ?Z&qX-pp@zp|RC8dVy9#51z;kmT=IU`nAYpgH?@_-PcoE zhT+){!^x1X%KnC`r?yUGpQEUG=nDMHrY8xMF?6c7%T3dWYaw{+PtlY>-zTI z9jYf}9ZY}tFAsUslUz+Im&c+Im(w}}a`K^R2d*65o`5W&6nLcURCY~7ef^6tKEq-l znl4yb?q;i#9m{!(Z}jeETM`6D3?K$~=ikmcoOYG_yJN}rGYqX}lyEC`^E~gp^EneC z5+v040i5rmz4L$mPxdmW-kRPlyoOFVYd5j=NhQr<;1G_44<_3MO2o0hfG3`kol&PX zx!D!b|71H}jpaiyh@Ew}SnIR7qBjxyi6#@)m!!hUsbR(yyvHJ^G8k1rB6#XcL=Ijp zkS%AQBXZr{Ip3awhxTwWUSDYgjCc8Wk$VQ71iJQ(@He8D{OHMkU;8k^OLQWO#ry=u zgf8%P4Oi?}>)_Y#2HDPTtJwq>1loNLi#Bh9){xb ztRK&d-YRQM;&nII*{6^mr3PHtpDe<86&!xDGpHh-AX*=He{pkJc3fmj5Ksk7z$e*@ zyLOxEOtj~JUropR!{3{Z87&(cm|kUoP7rT}4#*ZYFg)aXUH4dL3i2`go7dei$3(Wx zTxx2yyhbh+k+DSny*}~VzNjg!9f)~(dFpz0cBPqaMfzYu+4+}d&NcmW+a!X~J zjY2o_nRCBZ&YZ->Jcz<3Ru!^t#qp}P|GR+Rai!m!o}F{UhP_nXdpHRqLJsCfQzk!0 zME{2-^zFVFQ{yyoYHVcfM$cOYYa-s`h48OaoCdz$-c58ud@9AF23C{ktAcf*h3PE9 zdYPNM2k6dRT)&A3w;>WVe^F5(S92m6tu7dxsn=<1h__x6^a*qd!(tBlOZE1Fsg?O0 z-wjo&R5HO=98?;2zZmiKX3daXnicIyl`katTg|kG*^^@&*|Xt~>8CFuM9G8_s##GrGx$zj65ygq#izN)^xI-@d(6m% zAumu7{nw8*k_d?jaAKKE>2UVXu_&M&>D`k(w1`wZFIYd+8ncv- zUi%2Ia@ajEMw5}i>XO;6J>Y`P0itvXgBw)X$U}ojwBD8h+pn7%O04v*M=uIuL?Bw$mpdGLLkT%|qD2|iF-Kf9|MypP1&W8FM`Bc!UQ z6Se^(wvZ6!gaFssgM*AvQD5KvBqC(IvybU0Or+1qt@h2V@WkJ%p2N8GAU&t@%^-as z)8m8^&OYg=sQV?Vi!;h6NQ}7;213*KJp8XK;R8cMA&rd!3Ks})fkvdlLqnbGx^A?P zdB1O(AO9XSyC-8tkP(IYi8P5bVl(=V<|bI4AIKR7?H<~|#*L&2W1hD2>hD~n3N&h^ ze~DHayjOiic!8UsN-Zw^Y>*-VL0_sx-R@-w6sO*&!;M4`ZEM5!FAadq%4aVSg0E$4iE`+jXi2pKadnQ=|qyx>3?8>^6)^KAc2cCUSHG>qKxo z7$U)szQ)G(_Nw~R>5?AhWw&?v^)pXL*KT$D%cXeqaU>{~a!A68!{RdLi5lB^)}%LT zRK^#vzWkn>xJRGt$Q~)c(+=V=v9NgI?CeY~;DfD!X%ADV?J_hq*UR|{W3k{5fV}0i#Q(%Qy6fqgHi?zA{X!<}-nVt|Sd}(?9=@zt|3KodG)|1G# z$U0{#`h9F>-w=i_IQVb zZjz)C`|5Slf&cSlckNre?aSb@Ll}>oqKmQF7_DM4gX2Z9I19V(*LLKhmN?m;k35-o z+a6zZb$4s0(1R7e{c`6$eNw4j9LUpBBB^A^yww(9^JDrf`An&Q_D87PxHG+aB3B7b zOGnGfqR^6PrRfISI(1Pe;+q&KN}TpjIC>f6B;^Fi2v(Hj0q5~J`>Q|bhM1YZ{AE-_ zdoQY@ErS@FeNS|l;FkNnguD~hFPg0id~FboiM>6hwi1SNHb15Uk|wwjK^c^wky7bp zmZ-m?J2W=fU3pOUgvK zE*zDS@rj?Gzk*!}lx<(IUT#Mv7ZG-L13bgH;nr+@W+{e=EPCf}4m#|O!_icIYb6X( zg9om<6M=zLB~k0;DuJilYrKZ$CP#~l_ZpaUpVneSGVf{1%63P}1Vi9p!$NO5qZcNv zz<*>D1q)R|6Q78vyT6}^(#}iV$^z3dMJ9P(-cPyN<2Tt)%Gv_vgtdi*+B;%9`b^}@ z0u&eZ>haLdRk~O;e1Z|$wio%c@0_P6+nvc?ep(ypdJQUx80p6jf&5A%)nVOLd=lQR$CkS+HVe`(FCoAHEB=A)jw^C7ye1A=XG5VL?ulwDv^gJza>Z zMHw6zWtsSlW$t3XOv=R&E8%f!&rJ3RUF5l3UL#r=O-@MHSx+#@T$9#!#zTv~zPVnM zO-*5-H&VG$YPzpmQNy)bXD%n6i0m0%H%^I#<#|7wD0I=I6SD{WZ(V;n`SG1jl!IjX zh9ay%rz_nsFrcerZ54+IFZ6_BIcTdWb)gf_@_b3S`_IYA*6#?Z^rxx25=g3I*lM_n z$xdHsgXc}4hVN|edOzAUgS6?`*jE+$4@ElGyxg)2pi4mCceF^*~Xq)npv&p`zVHw{9B z-$Npx2swT`31DUkN8N@{@VloTU%s>8Us^WyF+-q_p@cPL!!q!N7w;N-Ot~42Yq>X< zGBurT2r01EYw^Nk;j{0}P1y5j{$lK48yq>=&0+rOrSPi0=lNT3sY|lCsvXnQXh{aS z6*ZMe4W9@Zl227c{EY-ZqPe)5pU{ihkIo=^sWsPMaNIw<_4MBLZQ-@UZM)q79mCg`dBA2^<(*O9%~Eo!lN zCg{^Xq_`E@y;ar`C1rDFSY0_Z{spJ6-+x`e9f5aOdrDzSQ>EVrmZWBpRVbXmyvpWv zX*x18veAD413ehP8d~tW2k+w~b-Kq_oHpL7RnRn->DP!ev?&Y?RYLA5dl*i{4J2qB{F>c7V7W}?OvT6Tv5}+yef$iTJXcXs zk=5!hqDSil+DyWb{#e!i2S{%^iKa6B)<1~t0fLtr*B>Y-V&8Qj;2qs0edB<2#Cb-R zo9am(bxW$3`-^cz;!709ScYite?_#<2l}UXT$ZGd2`8(5`)IKP=>Lk*lwoft={7d| z^!FgV6WlQ=nrpqYy6&zNpZiLlcXVA2Cp0XdY;DXId~f-mmMRG9PYcg>`6kB6ru*eg zM=B(+BTGCk6u@iOn=JLl`c9+THV%}$vKszQx$&oW<;sZ#t36exM5bFkk)&xrhDLaN)m}kNmT+SvHD&*s zfRLvxKx(P(Q*1*DBRbUr65;M{%bk7nMRK|6R0ftS#S55@`C)iZM49Mf5}mLYrppKB zf~Q`}081G*00%Rmq3OS?=2j{! z%vhaAQ$g_ZjW;mN;Hym+O8@ug1w79F5MtA>ziu=zfpQnurFQzlSQQbaon(gerLvuw zQ3K=S!4WP|;L2rt!1Ke&{t~Spt|CsKaK1Y~GJ;Ombx&=thY!UDqikvxV~_a#V+Lk5 z7Vi{arXeD3Y(#SLU!1DX%ve1=FV&elqn|9p2j98KS>=e$(ZAd-&Q9X0tKQGAXBXv^ z+~#kf2UBUzel7M*Gggic?M`oDYAT5==0Q|yrRhW!NjgdifHoai>gwu_?l%FpQDf}Y z6>$8ooy!?VC~j}p5|>r8Wi%NkV6SNP7kz{KXAlJwCT+$Mn*75>)kaD`wVC7S2J`u8 zD>KW6-E{p*WYJFf?}do#s0FWvD^r6NKX1RjJzL)##YG=W8N2Y)*wGoXHOr@VA}rrK zP*l#PV`^+4YpOdZe82ee1JjA9Vt0NC`ELUJO^C#1wJGE+32=VE(1C*QlLI(+P0NO6 z!S4QPiqf>u4&bB;+=G?cT{vQ~QW0BTX{*S@^rk!P*c&@LCHkSuWbMK2bb*k|q(8?$ zj@2w%5Y)A8fl_wts@!#e&9>+LzmfiD+2Z9QQ}1HGr{AkZ|04@771#X7 z_H%i|6)sS9nr7$S`X!<}tI_k?>i$w~ahL^kblnJ#vGs^8yBTj^w=%wF-JEqVtSe;) z{f+kSDyXrMq`ZyC{G{vELfbQPK2K$S*k&=-+QbKG6@IT>I0LU!uD(M9PmUK-8_SgHslaixoBRQm zpmdWYtJpWMCvozR?oJHbbKi`Z;q53nR zaQ`_fkCA+#0xr;RO(*(j@YJPmMFq08(jGnc$L5F>4}8?3!hD5Ow+6Y0b0A-P?6q48 zw-*9^90iIyk>!81Leg}C8$*+iZ{e;ssBz%M27A<)$%@WurR@-ut!>~O2*SKk)%1`W zJia4wVf0i~zs_(%v*XgUvge2%_FzG+;@~u)2HWQZxS4y%j%+y-&?S4AddH;I) zIrSBeRa*AxTQ+yT7D01izuO0RY0MKWcg=1*VX>!LOilYW;~ERFEgW1|LlW&B*5|wl z`q%hmb;lN$Lh6k81A{Cb5rMw7#1ujxJd|C}kQasy{Rf(aVTjlj&TpqijYkcI?+uPu zFShU!;^Pz1#2i!_1P^Zr(V@&h6+bkc&tdC&6{(`i8DS=_*diqL$Lw*{id;<0r}uUJ zEBhhtY8)DYWk;e3=QhmQ&eyht4A{ua5R&2=c08&!J|bh|yXBq;&}M7~heo@p&ePd% zqFyby?(?I5zFnSQE|t<9@xOTGbG~-Czx0F{{Dy=T3_fqe*MZTwjCy|u^*qjIUac%n z!pgk*5$%mEtT-+{kI4r5oRmU5B)mEwzRTOSyJz3HqOz{4C9iy8>h`5 z&CDa;<7}pI^5PoP1h)K}r5Agw#S|-l3ZG2N%3P*n(R9B zwA{$cn$IN{pt|Gbe=I;Yh&Ak1K6^9$Y59kNa@ie?lFz|ROAd%{%RkV2LUe|Phc|b3 zF;Crmsj*REPx?yDe}FDcptKxZW+Nu}jXZa&tE`|5n<&fK>!S5$UXDqsT2lNk!4DI!zir8bN#g^AdE zw`?v+xCmaE??lg){yVq5JeiVEcwb~;*X8E(j}Bb5q3_uX6FEpDU9=b|l%goj3Y%>W za^)WFGb+SxvPvpyC#f|`` z1Lr-(RegS#hT(BKd|G+B&xD`&?eA{0`+V%}ZK?L{<*MdnksV9^Fk_j@Qs`s93YX6G zFHdAq54$Gip`7KAP?Pca1OT&4Yfgqnn+}3q{VO@D z6a0`9+_ndZ0Q3**I-rI%VMOb5v^XYm7~Nl0c1`+1CXxT%1a=_b{2nsnYuPtTRkDnuPP+L6C_R@&>lzhl_WM8Pg4PW5mQ z^o2RBJCe4MB`j|Xe(+&`MUQJ5h7nX6!&Bbo+F92ce!iBhKvH^saoy7y!$OUJaGiD+ z-I&eJdc(`b)!laGPu-!}Y`S?XO`AyT`HWMt@+AbxI?m%_`86X9mq|Vjk6D0(#(y(9 zyujMS)4RKi4xezY4#x6+f&fcx?Bo<_=hcZBrI(1}8&EG#o~9Hlh+|KqEi%_*R8AzO zG7`M97*s(&2ju@-TaweBDOrK$#dF)OZ0-F({~$SyoWuW|$DU)U>2p0+obtTOVzu6c z`1yJ?O%LDd z<)E9WR8qhvOx}905j*!tnD}jLV$gY^!56Cs7ex~O(fCc(R1+ABMuMPQHQ$_U_Khxs z_6x_)>|Dq=M3OVFo=l)A*@|3__BfM0iF{gMG6ITT`0@@;e^&JJ#j_r~&NZHnmeY^# z*|D0#T`gGaa@7{2{G8CbKZs|+=l8l3CVV;*B7AIt10Y5!MzJr-K}eUZh2QIC+w-Le zbV|Y)PLsZIy&OR-S!~IiBqaiez~7wfrKJ9OI$Q$Xxc7&7gV!NzzAMw8)cvV8jE5E; zih#UqaJ?{w4$@c{azF?ASya^dIOD=t)1soU_olOPcpeG}OICytZoRq}CnbsjO%D2F zM2~NxJEfro5w=${vhd42g7m@vBw8_}6pU`}(NE~W0uC0d`!n&2Wvi}zr z#!*CGuA!%g5HJ5dR~w2SNdGT4_IFr}9Ldl#@a02871vXInMc<}!?_u~-m^%x(KSmJ zJvWlcLr~tU1klO|6BA2+$2k{CoIV;FiuB(!Lv;HiQnkNmQI(?B408^vy$wZ_WOr_- zAtV4%7CU<c86d4-j=?965v4KA0Y<9%wg90M5unR_jEPf`qpal zdBT0<<3p7fe7Uv{C7I}UYD^eLZEH#k#`BHP0BoCEAR7h{z!s3S9sk_f z8TdAXiDYugu1L&Cz|*#ccwdFuQ`^-r4>R3fLiisNVo`HmAk*Z#!h5@e z<3zJj(q|qe6m2grOOG!`H$qEyv=0}giYe}vPKKYD`^K)dPwlB8D_9-;&j6wy%`m`%l{3 zpqutPN(Dc|7$%PR6n-0Ga*Ctc6EHl9F@cCPs#_y2VXkeL&##<=(6wu&w=zGv zFh9PQF3r38k#ql7)qapyJ(-IG5;gh>B_ulUrxC`sjbm@oOCf@UyfCB1Ds$4bm)OV! z2ujn?whfSe<^9>)zMwb^u)2vkD%iG6XeY}E3g?+)vZnr`UXq9qsGD%)yP^!Y%Z2m4 zsl_L#|Mo4>bRr~~IN62|3$r7Zr(K+pyFi2gsL}P5M#Ju1S1f!#u_nFM=fod~eVA0y z)_8e1zxTSKl2gv}h~J~@%OgPqq*LmEd~`vjX(lGio2%}GlE$j{wlOif!D)0KSNOmg zZ0VI8fd-mC(Q$Qq)aw<0!n@@4 z8yZ~g&4tvc=s5zym?<)TU|TZQS946-w?A(Rneg*{rudtzk7zv9qB(#+!N5_&QD36iB+I;bI+QB=fnYa(d z3df=@!9;6Hy(yx;i>NNI3Q+6ww|ut1W9pL`6zUw`Z|)aV6@juBg3<&pS;iiuU*Sf1@AqB+_KX#C%Mh zJj_9R;wmif-D8!R5G;aeXYf|=saWE5S>K!pQl-r_?{`a!i`{zl3+$0-ikQt!-$7AV zxK8Ot-+NxK%L9ygLVa7R4;nUODZjox>}M=L8;DPH?boJ8Hr-DqQY7|Te<3aw*VJ6Y z6kf+yPL(gW!)Ca2SZA2iGpqjCogyF14;sYF|3CT8C{z@H0lonB|K;8qqf#Chwj(9$ zO?cV9&t&;LfGaIDUTX%A=wJ~w zp2H6;b9oYgF*e$Rr9vBhV>ruR@WR0iVokI1+PuN(&(|<|@If3jWl7MkdMgA$vKN!z zoUN}9Co>@D!o{PdlTTp8j33?s)Xm&%_cy1`&12!I@ki-~q`WCnw)SU%*bLEes~Aa6U>7(v*QlziJLAU=crDEXhLj zT%Ddpj<@2=a|MG9+7p@wQCv)wH-8cjR`E2DCK$t`i}&hzE<+zTsw9{=|4V>*ogP` zt3IW5&`I0={bPG0W0p~ag4TPJ-5O^aS$sYe#Zj?s92L-@6XdGvW}|wW-+~BzL z!fI(_JP-vzlFsFDiQp@Vmwfb6apN2n6!Y0h z$?{gCNh#)9lR{#Y{sELRBM%RUVEIoC}7~y{WtP^fnnQ23&Uv zaZj07#Kn*y$w;C{Gt_V$h9fTu*8 zNJ;+nk)P^3auCX_n3)Ac2Q|Q{r^HkB3>H1Hvi(Flq`yA~6-Z8VQx;fmEFF8xkB`V2 zNZ?Qs;fo6F66M`mzlsFpR9H`cV|NPyOOptAe;rVLwp((7zJ!FtTy8@5or1#V$q8(` zGQ17d*7x^%klpSR8Il{WbHn_GCX8*XS90n~Ti;cKO>o|^V6Szuvl zReO?gI#YuF50J}91Vv2lqc_RuH6rlc&@>&kHX^I}9Ur)>sP?L>ENx9=U`3iuRI^X^ z=Uch{p)>4L)YZ8;+Ab1EI->>91sbS-z)o2f(hVdmKBD}ww3!`aoflj6N8(diQa^E{fSB|i|Hb7|5U@cm zk5*ve0<9nX4_N>XB<4IPkR`yA41@{C)9CD<){lz+6RRnDOCGKgUuk<60z6;PAD}9g zUenlmV+3gM1+iqIz>;op$=o9ajcRiUyY0VwxLj4g}&^I-d1t1M^&U`|l@k;~_T( zVG_Pg`QYni-M`XkGCE#fdIGnsqX;e8^U4mGjzFnn2O8V$y~jBSeWW2qB^#^#HITKH zl?mCtS6QD13xWZdBwSPHOH~Vkb=-+|mnMv5KSaVxqZm3? zUtbbf6UF%i?hP;7#?|KO=@b5U?*+6Ii0@(#5Sp+9*a7(^fXhuSD0L-k2~?>1z-~U` z_;Bj~JU#I;u;UH4(l+QdP(2uvTr59vO3pSO`O(Wowr6@*ChYYbFbU%uoWSdQS-yl+0(*I`XmjEaqeO=!_r7e@?D#^{H3(ybKHWa@Y)RO;EMTPaTwI^ z`Wxl~Jy0hiLN$9NqaQkifT{Wu9PW)OPo2a5-H;6mg)r@O{%$2O0U&8Scv=hrsz+uY z4(Wc}jbVD&nZc@J0cT8(VawH=u2#D*6?tngOe_L0D3%kvo;F?!vyG{vTsEb;%n0BH zmi1dPPaN_^*s5+(uGkIOzoWLwH`W6MzN39}z8HRL0?v(tBJqa6f^2Ti`^|9=y>{np zzV@+LOb_cREkGzbho*w~+CMdd8i97Mwo~?BuRg3jpd#SExcL*=0EvgH0c|uby#GE$kJ;&NSGyZZ0Y2P>8ERzm@OPN))@e|s;sT}A_vZ;! zm@ET*jU+^5XXOdUqphXYugLrHsBsY4Wz`?Is*oeFtZYVK|4(zrBHJZ}Dn3#A4@Q_T zNy2?KObL@E+FY25xX5Xc?GyNxo8Au(RTl7nQ9pZJy(vrDm7SFh?5R%KIaFE6vR-4o{HVW0N1H&emFS7S>#7c9`5Pu z2h6E7QrW|{)SJ4=6Or;L&`my-$nblmX%klc{ElxwrVNr9jY+h0GyPp%9`2Ze3lSN{iE^tvE~p%ws+ca6@DrMF(S;JaHrheP{Ff?Y7>l z{fEH!AKlCv&O;j+84YeiSA1_$U&P(e^wHx6PB~jRFzL-zbw-rY3KZK-iOm`9b(%I| z?vMa{bT)a&mg{h%4E-x`K^DHXK(jJ5eB}X}>!oSo(1M^ty5jnY3a_?1eieCpQm-C8 zR|8%(U~hb>c%Q)29I$qFWDAYf=i&yEa!ewq{O1Lxwd?Jtfp+FJ_OvYdb&pvqb#L%#yUEwOQa z^gCaY!2GkA1p#sQVjySWn%10NrZ^ECcGHVGWT!J!;WA^zch{B^^6ieu=H}+ukv zvw;eUFNp}GiGMdKW+4c)I+D`+$8;6;1_!J+GC#7dMBUzyqOJMJpyA-8d`V4!242AP zimSIK07F3v>9P+R(V1sfwDq&GF}rp7Q!c;IsA4NxBe9$`dfs23-LX0=GoOncoiQ}@ zj$crKCdZjSYlubpIyc#@@S0VzJsopYs1Xm;Ib*uF!SheWocZ-&))Mba`_ahZ zvxTYG)_Hm>1yt7mWf8guQIZ0yfWSuh+Mv%$Nj`w;y5zq5W&c*|-%d$#QP(p=Su zRsZL(FECri9SO`>WYrFPFU7aK?y5k6vvkny+1-L7wbW!vzzr~=sE{4 z(B6ofe&W#GzMO3;5yd6fKfH}CRae{pm$4#-Wll0tH;#G(rV@9WKe@LoiM@@~^uD^%ElHRZ5wRrdvbY`3+*OcJ!A+ox^OI9=U z!+6sS(UKz(G$kx$@7@iw?~MLyc%%-^-**WHkZH?bNBWKjyXIZ-oSiCtMQ~y!UB~R} z%Y&hDN`28v(r5DtGQ53Nr;qi9t44@T96XVxU*8gmH>&!(tq<~Q|56sxoPr z5GKZB=yNjrDy}-(`prer&y>=Bov#Eh&L$FJ`I;gOX2A@=Hdch^GY2E8qm&$1u6vluXYBryvmG@s<3ak0L%0R&$gXkUR*{<9>?TWO zV2C9ov^KM{Sp@D1ZrMtxwz!*k44VgM|DdS>4MtVDjRx{f9J>cRiLb)w zf7Z!@kxK_nSbii_tCSD+##M#XG!$1^~s_~XxhPkx! z$6-BGc>N}q3Y3~~IlOw*N$!|&|67Xt*sLj=Xdl|Lvc5(j&WgCejJ!1`lt9yK^dU(u zTMbEUO#siKWS{`;UDb!W{9J6!`N7qnp`LHTUQZnI2Ei|&UG53C2;GN`6)+AZ7HioK zq2b_BgeqrV7V7eJ-VTfm${ZbGsp=Ty9;#|N-)#|icsAs^USP+}?d=j6{cA!Pc{E}A zdP5~+K;uuhBUo=26SvzEQZAYj4B~N}I%d7;4nfxf?*9b+;?{etVt^bCRkRY;=Zvh4 zp4T1u>b}S$Iip%*ImU9i`#ylV+$RNJ9DX~QNQNy}EmmH{l$zQ{i z2ECyK+_9osCMP>?={)nW{-leo_<7PsuPGZDQUWENk9(8yVle;gbt_q5>~7 z-~eY{v50ldtATO|v9W47AQIVyOCKr6{9}w!@v~MiA8GOyISh3IEj#-cx&#DCDS+%f zc7j6z`JHxU%s3zXYKZ;&G>sbPEZhkjXr!3B$4!liZ*ug+$$0}`h zAmlt$`{=`M^RUH|6iqWB-t~kGAeSsx1)nd}Qa#_1(IMRc!Dk9rAt(!Y(@~lR(VfvK zlOT@uQp0}bbGkc~)#_{{j_(N&q1i^Sb4Z{%joN6e2Qs!zW46K)iUpiLh)e zR_F838Ncs2>egD?xW{VEdHxyjc5AS4By?vC`1KnhESQhnVrvHp^E{UUQ`O@sR>Ws}<}?0*X1mIP4ywHFw`z+_R}kC-8WytAUyk@rHRgmAs*xtG^P}!pAKoQ5Xty$6^Cu;&0a5<1M};jQuPt3oFf}fD^((U_7zNP2LqHRsG_12+N%v8cR=( zfk`{@jJG=;(xj4ZA6#;jpuRITbnLQV9q_HnEwl5vk5RnaEcB(PRP$ z>m%M|fWTb#vP7t?1a=qR4)?(X3=BbOde65Md4M7}M%g691_s7@J5acCRkaH3r3^~do_33! z;*Pm5imSLkg8*xmf*?^nqyPFU+`$BRX=BH@ibR$~L<>lDp{YLzpaZTdk7$b5@*xUnSH^}U& z^~D0UQ)+;i3~#p_Lzg7d83x*3aQ2vyLBM?m@?NXam?hs;Zd|Y9y!tuM!F|eQRuxiH z-(9TMXKHaod?e~a?r*nX<7g^@bb0g{aIo0j&Jnh`5BQDv!iZ48!@-sh>LUpp z`#nz^9%Az}h)I8c%M?iG4rS=3MEeJ-vxt;% zx$IvQD-uYcnxj?gOyrx#jYUPb5XD3xh}AxUB0`w6ozpKft#8@K8zkiI#lQ2I>cwFKz70lAfP5 zVGv{HmmOHy?LuUQ_2u0_R+Fq~FE5j#-A4h27%)f&Jyuy>dau3glf#gSnxO7G^t-dA zcsDdu3;J_1!u`F;rg!Ng{Uu7mAWH{&(OG~49Ew=8f73zfZ*FP*hyJk z*tfNi#B+PH?atE_(M{0#)OPDS*?dT9^Rl-%wNF=Lwnp3m@ z)4D{fO4W9BobhwlNTg|n$>1JF-}gVL;1{@zWbnTT=PU2YUiS?HYifT75jZ|YMe)Wv zeJ}eCp;pJ58v6cZ5ygv}WBdn^|Ca^m^jN(s74mc-eY-&fCTlbaFS5|wL(pwDA=C(O zxvQ_Q?F64WW*e;fIj_QMO*iA)RH3;U-7ArV;Gf6^%0@=izgPq)trgz0YFsO8sAhA_ zbEn%^ka&PQs^w0ia2R5XsB%3wnYM53eDzKzH$Y1d(a`V%tHMT@O(gzXZ%l{@i$#wS z)W62Z|iPbPJD z1C-ppVY%{gvz1GwGF79=ah4i<9Et24MpO`z=m%<#$@<;S|MF^tIycQ=iy8KQVQZC} zI?yFHZX86z0N=6IMN-b#q^1oj+TPm>|22fFPC!DMY`xI<@79`<00y35^MIW`a1H;P zexT5A^Co$0=Q3!ypA2lMim;c;KD)^i~ksBa7dz3SnTHi_o zCl!fc+|%^lp|Y$eKGs&s1``l%DT>TAEP$+mm+MW&1qfOLyqkaFK(h)&dIL^VE?dIy% zld>5MI@bBc-HaB$kRZE3z11SBvZXv8Iy~4VFp?^Y(_dc(7~1-z6@8i@5Q>0wymk5PI#!vd62uKjjr&Tw<~Fj$V$ytxY2{v zSCMR9(X`|$UDMvNxfiExxcwfhU>9VG%2pYKzO$mDrb2uqqH}@ZnQZRimZ!hiZ^=>v@8lEsl4&EnRt6_5NwRj859&0S&V+TOx(2D)~bS%p~c@ub&JCdxiG45 zfdR#%Tlg>&oG3bV8+BZ~oi2?|+nA_P3R;WE7?=Gi#!aJVjm`X~Kwx-ivY=zQ2ERHj z3}ZhAAUzkWX~{hjte{Qj^Ccy{CO=@*klEsZ`H}l0LNOc?j{|k8Kt|rY#(r_=iWp2l zkaU2BF(*iDfb5AE29S5G9~W7W4bXYsP)mwR7n*^>iu(&6hgmK;P+cbWIZLO$%_?{O64HQwlM zO_12LU8{cUAR3Q?sK;#W3-;f|kr5QUo=7xI%;irHREEz9sR@eKqI2wvpWf46_IR$f z_L{`o+BX)B#S*pR(ugB=l6R7;@Z|OEgvP`qX4gp#g`S#8nDHof1^!gqRyNc0nTZ2 zT-D=SVz&**CgF+*xoUifsAd%{6 ztxC$23}`ND{W2oMDLBY_j%=?e!c{n$i7o8y!~Wo<@bS|z7J@G(o+@X!rV<*pTD|rS z7l_(4_Id#vGbod7XyiABCQ5-jqRdu9t1jrJ3>5j|E3l6>DDj7%ojS=%AredA*!6RW zI80Wwj@rP>T6Y1QF?`14y^~+wMK=DjueLBCSb{{(XW!f)_3k&W2r`f+j{46d;K~Q2 zlByMvuK$#2YEvuiQqG4TKcfVyW)nQW<%sZnU=C70=<&=;y$)*S!uLIS|3`l$ZR+4fsr#-|LCZ;9E~O-QR7 zH)Ujb;+k@%?dY}RQRMoIBb&C4v$DBgq?i*srV~bV=qu#PRC977R*8;sL{|kqhmkea zIdnI@c>7r7-Xv{{PT)l~GkT(V9*v>F$t5x*McHX%4M~ zba$gPC`fmMba$5s5+WsC(%pUMeD~fT{?O%u_sl!9_fvZgoK1U2hXz|ET!p&+ze*>h zg_(gq%265K4Q6ZU-Z=yzToQ;OS5qzK=I@|#{TEnjYA8QMAaKYaO)8N)(e5qJgq;H% zBQm*u3T|%hi=97Ni5QKHW(ZP-AY1;k8D|P?HSB|NtpE)vLkqQ->A%r7jnHvg=s-0{ zu&z6a-ID!goU@3!tRWff8B4mf`ty)y7Mn+%!VGdqM@L5)ar)d%wWWufm99St;G?Aq zNXwkx3sJ@e6IkSo(3v6JxCkdCn6z%ziL5!gxXlbNo)4Z}xmq@eb$!Wj#BR<7EHyp; z`n3_i&6xn3j5JKv#dnat`(D|nj;b;R^*exFh2MsiJ>e!0TKuirN(`-fT-yddGEdi7 zfQjAo`dNw!CNMi&d^>+8^k34iNuDKb<8IPVR8?{QwnyuPiT9I;aMbB9uaW+|=|@4I zs*0xXar7E}o8z-%DhC52qML|hV0*r_rj$|5jfBB4EI z4icAvGWvZ#lRCA<&_3M}6ZX_wEw>ZDRdW*ls6vIuJYx0Mis{GYbyT2qv_{VCv$pLS zK0#y~@s8RT1rU|UXvS&Itxhp4(xv2vgSmg(dogPJa5+xUP=$l`$75D zavRe6^330~46AgM^^d6QxbehQwDT^9x#|1DllP&vP@y0F}IGER-~7Fw6HMmjEB+l z4b^6u42aWfe=Nu`EKV?%o4bh+TZO*4IaHm82bQUsqro85XSg~tIwGY%Zo`%=j zy8F|3cXRJ@Y878Nx$&})-g)O{ndpM5D2-y#p-=KDZ!bVMt^N%^z&LY@?Sp_lBC3kF zZ2tcE8a}g|SX(=(e1>q(+J(q(S-Mhv0xDWriRWil{CcP1fG&@GF9c`gg|xC}9nskt zo%os_gl4qu=YD!Fjc^Qpsle5j0GX=jYq5b(Ec~uuNN~|F<@4P9@kX{W0bsyNvuitS zXoxWfLtdUBL;mgJg~*!`2}N%PiULtH-=1iti<(=eg%q;G!;4xhjGhw|G_+vI-GLd7 zPTd4~?mUrQKC2i1CbuNt(j&=%q{qpH2NIL;jK*|sZTmMAS2)Y+CFwDDthUC9AzW&9 zrm7Mdp#8sgNvWtKh{$?>u>WBzdt`2bmvyMAwtiv^%M9*7$Q3SCFb?R;muJw?9{_Q7 z^VBCiE!RAd*v4#zf3b9foW03NB;}gPdf~v!Qao$oc{Lf&y8s%IOAQ9#KN^P32D0!U znE;{5Fzl2p*;{$KX%#UWn4a_W4FA&vtKWq1IfXqTGW(fE1*R`kr7*|ZD zuZ>gs?+feO*Yz0M?X^X?8Iv#h*u(^#??ixAFgkj%&2zho>h9xz>Eue*!+Cmf5vs`? zB*h+8ksr4jBSy>Ez z>q@Hx9)#|29e^?kdflEl&sGicdr%bY2_fWzSwvYkf9j2n1Q4wp2Rr_NV2;pQ^kakV-%58Z9tn=^uF#7yLASNn1dk7dVqQK; zmC|bnX+>WXbkvLKI`~+!f`Vx*{KPI2Ya8J)IP6cN7`EjCtNVJi!^a{88R$r=n=k<&l zU@$j7FI6H>8~vo)lzN)h?4*HRbAT%8nPt;-Y`V-Zz9;meqK3~@7#LsBz_(%8@Atrb zdo%vipP~18KP79pRWFsgdVj*H17`9wt zk;DY@y9XI5Jra9kV5g52Kp*MC!YuTFtY^mb>JRPN?p7~ z7gBOaTBL$N@;in^aDL(M1LJZw@5H-?uFfkbgRv2ns^!)wFha|%Pg`5t`;F`Fod5j` z&4>ZdeQ;mH*S!^^_w0H%eaAb08u7tsh8y`$7ZA>&DSVo%t$zXT%?N_zPPlmr(K^k- zwx5~30F=j#Bn-knRGYXDnA1`rJTmwkY9|*b5=JC-%WN^!*lE)or#$mtZ3dYp(nYS@ zk8EBAeVI}-@rpr!ee#EZaKHpm#94y;|NZ6#a$w(N)|7uZN!{_>E5k5}30Q!WL0ASl z|DW#$G?*=7A7Ogp`@hb za}9;Lp(m>9%LS~)XYlE+M`q3Dlh0jAhJY;t?r}&+i~-u*`!txKcMlJ~PPb3As&;6h zQsSJrTMfi6`NJ8rX3=mRT;D9FUIhhCdAll7hsDKVL6df_)+IbBpUW+!Qft5|9)46Y&hDmskx3#C*g`;@p=V5T*uJ z#<9@!FpBwJDeCG(O=mZMaHWBe7coujpSvOn4OsgqQ5Ob=g&{*f-;2E^@@%%p#Kf5C z^hO~5e-*MLke}iqcy3j+d_pby)T|HZ)PMj2cI5}nZ2}uZ`1?=$k;VpD#vCCI=4`Jc zk-U9Ry6{g+O20aNtOLga$~yBO`;rItF12;qqM zPqFa+*tUT?rNlEuCKnKrS>pWTUVgxS&&Y3(7J`BnMWBwFix-s_LMHSOyy z_v7}-Vl8YHYmL59CL|zH2{PY#B?aFmg@7#u3Kid-YU*4Q?+@YyFdgtqFX0WyhCQ4f z7JKH(a;qLp7XpIw=5C*{o$pu)(&80{n=W1f3Db~9lAx;%hOo=aU6~h%cngWQkG(hr zJwx?@m=sKuf)PSlFjpT8?~6mS8umpZ08FQd&bq9FEKbVZ72M1dbmqt_%D;ad@%ZF5 zsUI*UNG^Y<4}znmAd3~`A|fhEUG>!wP$&}8I_+ygEn^Bf>U9i-oVrI>jmGPTu6w+# z?%z)?no%qYNSQhK;HU*1Cs%#2+kUL-ln<=p*XPArqxxQ?!S;2%!ONJsDsaBs{sT|L z`?x$N09Z}T+01y5lZvc0l?vSYAI?*6k<7YO2bb~WuyLBfcpsRb%>lhPuGX2TqM@Ni zdqF@gv3Z-DRySD~>#g9vwSiRWBp?mK0qT^9m>%@^5lh>dHMG137@^lCDWVS?A&t`UznjOlZy2*scU1 z0Ab>EMCZI=hUqPE2HIA%O}9Q*WXy5%^Y?*xucKL%L`f9bFmz`2_xkF1g?rK&2a^1b zdja}o`v^A&PCi%xgfMAElq8*cRwUC}X3Z_T_Hi6No~WoN8=Il|`ZNROSY6#o_~PA5 ziBkkG6v42b?#ZEA#xGGyuIl6G`L^Q|rtj>S-Ce0mDz&fDm#L^xP=Yn_WwB)uUeUZs z&by$I-IYy4qcN0_^iGbA)Rn-wMZm8ylm5mmN=J>Vz&D(9`xG98{rhMvb15_RTukl7 zm(fhpgwe57@I60Zz&4f&h4cQl_h36J1*o9rE_Qqcg_d}!?g64~9dq~((W9)NI!W@} zh*R}`{21;1G-7M#FzWA*$h?yL@(-cz@b&rS*9PV$zj3kTI5s8*X1KC{osmBrjoSW1 zZtrh|v?Rz=zuFS&d^}A#IDHauitj7`qlS&}EiOVXG4j-_Z0)%sQb#phzGPHF7aJj( zc##x-u(S6=rM&+g{^5OG_u2fEdc#|(U1ZKT<3IXKbpEZbg74}eJ#UFs^Qm8cF-ZBfg3$xua*Ll$x6(+Z(KZj@*Cv&D}9O07ce z%bXu)*)0N9!v0KTjS#x*8`#}l+ufMZZ_`(z_a|rNvXH^Zh{*0Uy?0Jk!9IUpzpmrl zn-+vzO~HCSLT1@~Ge>ln`|X=(MQQ7PB;LkrpH11nR~PqM*A`=VH*9^4sK1Q=(AG7N z1#@B*w%nZIsWL7Q_vqR5H~P?;{JiZwEMo-f$72$ z@6JPOLNPGw*|H}5njUcn3Ffmi?;bxNa#-8nq4ikGAB*Lr*l#)37w5UzF%{knAGiza zUl2vR5VAWFkB`qHyD-LSzgN4vRnp;fTr9iU9u>4VKhnQt*!xp5XeZL(B1FIVV^l`} zF6LQ#hg*>~Lx)o|+k^C#l%g3Y5jN3kT>S-U?NFMy8@M*i>Zhspfoj$xq1rWtTk-qnUr)H@x?3P)ch&ICMTsGr`6U=jO$&&^5oyTz?W<{0+gwNAN&rFEI5EkzjCT(0p8j_N)NaGtcm|}D$RU4;Mkg`Z> z=-4--z4(HtYl&>wC|Z0M`)h6(5&Na`plq*M4YHYWLz7=0Tb zGTdb0QhBH7YW*p)FWnnQVqK ztn*%@MxQbuQzWEIHLGXArfKn^DW@AIC0Y)mrsT2DS5Qie^v+Qgj}VtUroYbCO-+%O z#0is#yMDfmhOlwEm8Uh|Tg9}MN6Tft=op>Cw_vw@(chQOuGZ9@5Xb9! z?-lW+S%Mvx{d}9epOV+3`zOzOjrk}IWAxnml>|pcIK+t(7eQn5FP4g5^%t^MJ8mpD~ZLd{%Abb4{>U2~~) z8KWkC&XA1kB3eK0x_XNlq9!QhGP>bI+%Fe%RqBRLW{0_T8=cyUi}S*fKdwaS$YGsc z@Pw=O4-NEKH#w2N!+ycV)XLjfX$3xu!rJn7Q-C^l^HmNfit1jF>f*oYN$Hb~8u2eF z8F@Qi&USo|X5Yk?7+i-TwJf>hp8OjBwfz!xv6*}q>LYU=5*!MWUI^Fxn(O*4A>+F6 zAlg_kj5_4l&)3g);-=?bL^LKnkEXZ9fj54{gfqts((j0Y1ckD2jfV$%1ZKr&s ztKOC3@wM*R6)$gQNMclMe|&1fs`+d1HyK7VGcyxB`%ZOdy=j7eVYAnUNW1zd6H0f3 ziHGLFR8{hFxm@&NnQ*S_e5TYro|ZFsuB5LqTlhNFUUy7`Dmn4t#H!rS1?js^t~XYJ z=g_m@FS3mLyPMV3v4)fL%UcJx&Yk-EKlQyVH(uE`P48eu3wgd9kMCcJ@dsR(#v$y$ zKK+Axwd>`O_;US=x)_06K7sx5H|j{ZW#12ELRci9y423Wl&6A)xHxMzw~G4+zm%?w zyu7rdkU$)Bb38?9%Qp{RqaH)Q__wy-Lt*S;g#z1YoVd8o%1m(IYP)^Z>?==}H~Uit zU><&xf}(=#b?!!u*%;5Cs&`XUQ`ANu2a3o?hg|*dhSLq0g5lt?hrX0hE4(b9pMRq= z-prlDQRHa!bbpWm`PZ_i(ucg~?TzN)dGjO`8B2*zk<LoWL?i!cn3a4TI7T19v%D9QR=AjiHLeB~AB~&nVs+pW?f6sRpn-hJziTs*`ne0oyB?P*JccV&-@VVlJ7 z{W6QYgzxc${pMwDU3qx)W@|;}m)FF+)r4bNUEv+bT~`;HiwunXgwhOS-J=m4x#l*< zuP9_i9H##nIttAjl^KYiGOe45CctiO@576)ILgR|a+6!u%{x>@2jrjp^qVZZ{b-9t z@ayJzki1t~nko|Rd|Y4hd7%N5OJn)^L~?(9WWZ$mC;#d1KY9Yb7mR9ZVG0mio}}@t z&mR+6yurpV1{W2X{`$#u)b|n+HLVP5ItiQlO2^^h`g)zfoEImYQ2rOJx3!|r9t}*O zu{!6hj!f7R5*SiVDS3l@8ra_9wh^SWZE~D!%M$kSpQ8}h(LjCA; zg#~8YL)qMv{MBK1{{G4gw4gR&;|%IbjIT*}%UKMI9-tR(KR2~z`)_$?cGw@tLlfiOb)!BI*jAP_N zU=v;a9GHLvcn5hDbO$3||V56)jj?3-*h>^qAl@ zK5uOC$0x$KQ@;%<%)uUN&Pt0-#Wf1;S=~Fr&$CF?({8_CmLDC$*qhf2nzxE$LaRnV z>V8QSc;ozG1(QnQC58P0uEMKXLop9C=g3*D?@4s1v+o;QUc5Nj<{_n#-{xa;G_D{? zd3|k1_Tk_ur@ncPNSR!aNQG2%XSWpF`JK#rym&i7&eYrKpV$~h>YRfv&53W1FMB-n z!n3jhd(o;gR!(F1h*X?J)U3vTN!qerS}-iH?fz4#{;*3{rHsz@1`ko$+X)7`LG6x5 zWo^H;lVG+1154V-Kl8iU{-2qpY?@4`0JpnE)626`H8g?hH%&#;zf+@pQhRs4+=@0`0ssO3+_=`kCId)eBcmt?&&% z^yc@qw>wh}q6m@_;FsANi(!F(93i=m>XV_r4QeAJ6G;?@+#Z7V+n)lq#(b35 zvz2SRyD&ctxYESjiNxls@!XC(wj1LH>#E=8(h~a%)rB*DngSzG+2iuy6GJ{#Ab`cu!qQ-KlaXQyY_gIuY z^%|fkE+-sTKTkB(#$I2sy+Js+Je3U7{xy-S#SN;{`iMhk-?p(Icw+$;>~ebFTCbNw zEMiD=Zu7D7o#EKdurI?SB7!uUTMpAlC>$m6Xqb&UeM8WnZTo6xC;+pxqRJ)kLOhOQpDJJ^|Pg z@AfclGko*dFJ5BU!CXu{oRE+n^-O-NF+)`I$4EsBRM?3Y6?9koDL6fCmd^WI{)fBm zm7DAJ4-gf_!AWEPu&G_vb59?BHtEDRW+nl1sc*QrxbQu%s)UC!L-Qh?@hVx0?x@=7 z^wB4jdL;ap+7d?w7zT(eUpHM;@C@+)JU=$ytC01tgdc}I{(g^mpS7694w?q}`4{dB!=~-fYG0nLxj= zLVV~}x;rQ3Y}-C}ebZFTQH8eN6_HPu$N?|xosPVJD6g==3=!{fOZt>;cpF$a&-S$t z@TX$k?z&-TRP&xL7!BbiepGDi=f0#qkBJ3BHKoWyMYKO!Y=>D#z1%xI zH)T|C$SX4ddh%EE24?`FL)WjQwm7Q4^PRA>R6y|2rk2b=bt3}vle|{l8enji*`vTJr&W>9`~sah(zOTnFmn$=a}w~TK&_RzrQjpHd{rr z10pt_Gm?1aK&jLGo^u~OkVaF3wDU(axJ1|0m8V>fc))LNTH-GrHVHmTW75Zg!*?7< z=0++Qu&o(c9`qF3q}cuZ9ZU8hU0veJ-`Ev+LN6`g(N=6Pte)`*I{0Aa^7m0CREtAV zxmWtp2+<;Oj?V$b5V$$KRvt=Gmb=*dt(r^xwU?dIsBez=e6sP{5wbPGY`1@;=JfAD z7L(gWMb)02pnQ(XhwSI(B*hGy*`MXFC8^-IMa$u4U<%JV{i0rL*Adpbj4JvJ(?M4Y z=aFCxvrVxhh=N}Hv0TQWohz=yZE8?g^jIt9@!@?8x8*L$sD5qQBQ?S)bET&J@x*uH zyx!7|#NYPs-?P*!7M*tpxbxZV1~hSsQSa}WxQhg}RJ*;(nx2NeOvq;9^(f5={BxsWo+ zZZS3k(&^_M)J_m-Ud*wo{in8E+iw07))mDUQPuaJOdoZs22JJq(>behrYKzVoN>Nt zRJ*X_F_Nf!Dq|$5T(A7u-Bw=jtmXJ2E{KXm1;Xz?@8W_@s^pgx(O6yS*>WDK*XFHd z>to4omcRKys^faszn#+wsn+EN8AnFXrm+(XSz3t}#%i(v=O~h+Y9jhVC7#aLdleg~ zOQE~y$+TK>T+Ov}*IiXy0k=X;A9{SRx*RwyclFuL8?0yg%kElm#WG$lT!s@&MEp&R ziuu$xc>OeN!c+5JFnNaC(5?PuPIAG?yQK600$KQ3VV*EHLMJEJDf#+=g{dwU#(wjm zv)d8~m(h#>a_19fhrF`c$2e(`eQ$lC#^d=B-^HA)O#Bp#+tXR`Nv{d37ujb>PaU4~ zcH4%X*2sfnDOEq1{lpaFtG!2ji1=>Z*k@%znATfj?F2@nJxOOMu{0+7Dg-8Lo14!T z;aw+9SU=)4%%!N>xcX^f%Y4-l^EOg*8;(UgJqt#V`ZI=$=wOydQ*E~k`BO^GVR#W{ z{44=z7a+X7))q1fq#j46W8P2_RU+$G+#>XNjQGOK3#qk}^K;8IIS1u|Xdp!&!>az7 z+mZS9U)vN;7wTnCAN(fQJ9ayRJSnfA%~LcHT=`+zV5J72oO_!z2R)b?iNpZkGWQt9 z5SvEvxxAKJB2RQj#wF$5qNr;V4!}P}0}eT-($^y-+f@mc6K*F&O_eY&-L-A__zoVv z+zRN6ZZqC`GZ+0bj?@-K+NgW>+t}TO)-O;QG49wEGk*|A498w-i15LHa{G(X?bD3eRHRUcWCcG`;|=|XqfGbS;m|0^&+e<2sC!7;-Gv^ z+cV`1(SV43vU|6E333FUXx@?F@6EUkQJ}rAZbGbduzPbt%p3=tI=)s5eQQ>e43yAX zL|q%55;X)Z?4KHW6t)ufe=STv;Z^AlpDUU6Xx3+-#;glS(_AE!`0ebdr?!-?d2T<~MA{~S`PCNWEw=MKKA)zPtXeN0&H9VsvJ zPUTg9+a(uhZ+xUM^E1l*{rx9o@z@;QY3r2}JVfDnfu*#_v?4qR=sI?;UKv2}zn~B# zjw)7@0WDf!?8}eS$)_sE-96qS^K~=xiM>;KytJ>4pd*7zM{ocQ8U&31P&s91XBQ{% zP|ydne=>MejW~&8%1ILQMp;qr>{7F-;UlSdJqO&wFMB~kC-Iq^j9`~MMDV0PYV>b0 z)0%?EeDQQ0^gF(#y>P)qc%pV_LwFeCl26R5X}^m z8j*8r&ZwvZ1WnDMHWV8twjm(A&J51y`VvqpFm{$$%9=$Gh zu!lH`G2Grt#Aw{Pkh&3 z>V-r0m^D|$l$${*AY2Z0Q+&(XQvj-BmZ16zbX2*a;w()oxxcQbiZq}(1uorVGP%b_ zo^EkoeG>CLoBRwDcoD5EJHD-Ot=WR^QXHL!|1QSdZ;n7T>FJ4+1gL)p*ccB| zN?kb<6QkeC_|+Rnt=uXZ@TFs5g_3pn^W!LI;hZp`e74UEQz2YuLh7dxkO)mt(fU_W zr%ZoYaF8TAjQ!?)qoC5)On4`S*Kxf6Cj>v;{WawjAQymZFmaL|DgX;cc)!W?F?Q)k z!#tj#JOC{mm-`Wx3k{)@p8I_7|Ai7dT|LN>-JgfjY+rr@h%V_@8d?B%VWSPX4WfrP zIki3x2?3hCJ*EtI*TnCgeH}*@XQzQKL)6g@v69)}`NBnI8CIOSo>_~gBZU|4c?us@ zoH)ug9=$!U5A{$mlCI0TKAy8Hr`#5el%4jwi9h?3tx(=)?h*k)ASzU^0haNrO`Yjs zBi2N{i*fm4`@65Ji?c(>93m_D#z(p#S>y|g1R2`_51D%Ju<>&?i9AzjR#Yazg0Wsq$im7ll`8I9vrBu#ydo~ply1QV}$bJgyYI3zqha2Y^?sJxV(ymswd9n z{+|mVoTgWcO%&m~=HU}WA*v#;d_tGxX(q`j%OZfgSnx?tJ}r%)iiC9S0%0RJ7cU3* z&{Spqd=T$Cm>G0EKtoI3)&!S3Vfy;v`N^rudCM^rr+$sk5b~k8$09cs8noicbC|tC z`}O9rQ~XL;2!rfXa?u#@`*gs2-UvGy%5rlspBbUW!Nu1Ag;u*P_!8YXIrDH`0jL*s zj4=gyjzWD#bgJl0YoRdI)YPE;ooWXj?Zp&&tb9q5DAW1;HpER5ucay{?6dRIj4IfJ zijh8&TpBoYt*)4R%RX`CPEeg1sHOzqOX@N#B1nk?%X-i^Vb@tsH@}p`3Zor+@7mBuJWD zZkA8O<#A?pV02DEQEIFYn+DomII?=A@MPJ< zggWBe#Q}+G#7(K(>+gkOFdaXN*@BrI4UY)uQFH5&Gp)W5d~YTkvc2kyoS!;zJ!hyL zYynmmV1psz&te0XW}AFAjUD5VZ^sexBstClo}VlV*g?-;)^8(LX}jqAhb0!&H=Oj@ zfFKC=iRfO6(znx%{%@0au)!+Ms>9&#)OVZ(vvrWccfWDtc)DY^(6No#2dCaqQ>?%D z?a`dtr>CZmK*7?Xk>DUIL;dtrzH3au+o+eYVX-GXgzpLqBST#!0Y{yd-vjm=(D0zm z5X$Ec9wxS&;;V}D?yFCAxqL_{%5|bPUR<&r${{r#E&o5zH+wqw6g*0RLilsmVN>z(@3_-S9Sftdnzf?Sd+ z2gEJMUb$y!tB{%lJn*+)f50#iN9gP= zM%dNS=ZP;S%IQu0TkD=Je59XM(}HG)y28io^c}MbJKt|_nk`)|flhZ&y3(=Tl`RmV z=TO!A6>0;L0eL4VqVH~my>cZ zjmDWi-%C5E*Y=be+hz3B9<|^BZ~M3SQG>BVe+Q_X>FnQ@|Mfv#LfXN`?sgFv-pzr@ zw2B|(UOb+7Or1e#Krr1bb4k4x-3HdLvadPL+qY9(0O~0ExJ_27iODN|B$?vUVxi9& z?z@DpW~<{ZGeNm7Q~)WN69iNs&Pn<%Pj3T>;yD%bgnwheUv#45@!eeQJ+AGuBPHN; z?=CVVgJ7+u4!AD%7PZ~eX@tCDE|b&3It`6VOvq01R9Ny$)oT2tNVi$A<8%9Dt^ z%bXo3g>aXeP8yPC&~{UwZmCqJ|iKKr3!V~T%# z{=j}sEo3e)P;5HEp713U`Sf%-EjZ6aVNGQd5$HSp^8cw za4J4(+(|*mZmhLQmdBK1zR$>&7oa91{}~j8!i+Y@)ZKHSR-i%a0d~}E6A?ywtOT3?oQ)(2L)ZVBH;1 zP8him7o*}~#t!Tma9MV`Ow3Sy^Kx}xiN##TXYSpimeZm6OLF4aisR8l!-l&d<7b)w zNZ_|oYm2}2zEhb0%mG;C8MUYsPHrC@u6s6HZPuCaoAZ3QniY@C$OkWJuG)%0dprPR znpsD4lkCXx2+knzsFJ`*hOz`pXtE3pzii^IX!K3v+a~mE?tg68{<7yk*)AxNoIa+` znhk?K`)ggbnB1aHFChq(`uhm_+c#h#NC|)S=VKft^NvNlvz+{JLX;soPVi=D07#V~ z4gn&AuF=_5SXsx5+PTDDs%Fk;48M$`XU01M!ODVn2lccA_K19|y}3xl)OEhPG)M6Y zBkNSvh(0KWM`>B{$;8nO(l}`jWLkY1ejhyfo>g}^6TK@3+emF$3%{WB@+Z}PK<(sg zRr5F0WPw9>1O(^9zjEOpt#2h0|Cb2n0`m_L!L>6jS3lDiPY?Ha*%8*^EM?n#^;NHZ3CS=!>FRPH>VbC%tWgWasV+% z)lqx*Kec^-S`n5yyS=~f+g)8y>E~dgi$29xd3bBxmZr+}f`PIVwzV%d5T;W40yO@Qa5@PA;H3JHNKEy+U)omr9g(nF>L8P=YlFT`?dR@H5Dn6C6xrN#n35o~y) zT;i7GzO`<^S^Dy((;eAvTWPkzkMXQDCw*~v$tuNjp$_lJ)?qk;g%@$pRorZ|+CxNr z3kL_cTEAe*dAe|Bb8-3$t2**dB>-6hDI2n}CQYly!_{C$C3y zCWWm_-)HUmd%+b<2kVjNUz$jyO4!y-M|DIGsi*v8QcRG)05}8qVkUd-^z2RfBMtL_ zckicg9m%>*dg7nOLzFsWuf^uaeHQ~MGVxMk?jO7#9Dv3~A|LRiQsV;bXk6USm(rOe z(|E#R{3b?{9BTLDsK%Ofu{(O;4$arK0?0dqFA25I%|)h>)(0k~1C3Is!jX<%9f8?- zkubV`8_uCjp|-W1D`lHdBq%=;ab?0ZRP*%02cc>M0R_0T!^;-Vlnv+fLD$0R7unA=+o6^bOf${OYO+ zq`jv}3B!D}DAmMp1lD^k@f-+KGG7A%DHMUO!Jt4oD5g|ZsBxO5m^<{QvI3a=AFw45I# zuj$|k599%rhyIjmU|jCc0QUN@wfWC%V@wp-qb$IY#TN{lA18clbCY>KA_o9ddy{OL z8A!>6Wf96l6BMq!q&9=8OcQ8Ald%B%9%(H;8)!~1WfqDZJ)z+seAVG$g9+SprDBb4 zK!>5;>oyuN^q8GY|G4DB-^h_2XT;GFt)x@cA~J^TgGI$A3J=7J(D^uHUQLH@pzSR+ zVx`29K0pYy3hab4UtS%Eha-;6Zmi=s!qk?_Xh;B)^5kt71&G4vfX6!O-6~UNs|5Kx zY+}`_g;0*-1Up1S#AHsXpRCFeKqYfa%_|?0_Xws!fskgC$Oc9BL&+Ec(Zr#3`ijpEyh} z%3Sb4Q*pSV5?ijutBMQIXzCH{&RRCg^)0V#{EB^T;!syKwBVShm7AN3Ex5vsmWPd& z*`NzwPn?tdgt1AOqXa|sMip%W^)`+~n>UdFbPqPA?Hmv-s~!ALy0rVDOUH1^*1FC{ zrpl<@*_LqI{In$O?dEtnp6aqAZb6de<3t1Em~X$jKrsMc2QNCyb|=lf=@$Z^Dy(Cq zaF6X=##@CCm`MgDTd<2S%9iKsuP4hX!FnsKR4?2Wq6c@gq>Yhcy$lX+cDJYPx2YC; zQAipqLY+iqt9v6vVRI5#?(`()hiQlu*E4@^%M$t#>aYp8Jkd-6&bMYYyYBSKf=!!g*;hwrABEcgKMPRFo&H$ud!lF}_uDA|Av9lx-<345UAHT$sv7%L6{NiHIbPpIH##Q2maA2X`(;BeL){i>O*8 z;rq#{4EE{_+6#d7DhPVPMHeBS@c7iPbd!sm zZ5%?<{5iq;?ls5N2l~e4HW0`8CgC#?kp*CozyaS_K0!+fG`$1)UQ7b-daJ_?D@OLu zDS?eY49+!A@7vl~7*Ozj@9Tl6wfSCqlc8!zV|oq=;!p%2;fHV>xX zHSH9a7z3`ihnHL~apF>qxSGk#LfPqK%?iHoP{`#+P$&I?&-vYKdm8>~rfUB#;L%FCo||IK~!Ieq<) z%^*w-lkDvQ8PxB8_~P%`Zt6GfrzRTFGN9i=M8wpP!W4Mf!}6Gg%T}Yy`s3H|ns5o# z%^A5m`5){YLb_{31|sE7Bp4*ZxUTb`ED8W$<6!5Eu)UN)p3_0VOAG&8Z~Ggi=e*c_ z;%4^ChlW;>vGx!9UwlO|aKkQjR3@v@ldD!YIG%=FqnXflRw_cIxS91n>I*F!H6en= zLFC?MgQcm6OH2`o^O!ANT%6Wt;&{2G&^5-@sGE;=B=hR!MqZ|VLIE;LX6t}}LCx{LEVxlC7GhIN*nsCWuiT$~&Kjw(%7YccWkX@hEXzv~LqLUSJ#53jeYUwe?~8i$UX8LV zgSy>lV}>&LixEvh^}@EXdG9EK|fB^LD^v}7oEUe zw?fQh>U+i2n39*Ql*jdC5gM)#>{H&-O-6s0mg}!XxhJ1%q*A%Z_RrIcyMQ z;XCfSmhQVNCJ9Ry9bYeK(!ygUk;*0mim8lfjpRVIRF!+fp>GW9Yi6IeL=liTo166U zKUui8L7B+m9p+HV?m3_x>3rTO+4hjnyXIjUj$^3cq&xJaIm!WwWdjEXzv_DOOMv?> zB@wM&5d`D)^qXIQ+X^`NdF)pel#R@99K%>X^1f> z_7LNUn)`JW+{wz=1hYy$z`KTMc$EJ9*!db|pq=Aui9{d;8Ee%KTxxwO7Pw08`&+Zy zgHo&O%?%)|dD7z;BFFU{GlEo0stAY)mo;^c`)0gl+XPZkHGt6~lMR&az89$@qPt2j z$?(DzI54{{4U+Of=(R+@PD)p2d<0zU`~J7#E%`dbD6CM2$;%jU^dI0a3~Im)nx>FQ zoQ{Yiqe2kfy~C4pp2MN3L*u44ig8|C`f0^ucJz%41*66UC_C(N2_P#+(Kl#*dteRi zhq2u6n=GFtAqvW7LPb)yy7gAS!}mo%I3LJqKz3S|1v<-Y&3P)+4PV5B%HBPatv)-) z?xTq7&<=`y-X{i{!C>g;P^s3GUbj)2+UySZV*w8D7Zd+!vu|@L^9;+^1o0yh)c%WF z0qP*l8F1_Uf7GF57)l-LJ)<3}4Ya`_`p+Za&+(Bb5-1E%j1L{}yhCzX(Tl3vo=1zU zfi5VK;E7lNfEJWkrA!k#Dn*lwqmY8nQw$07&s`a$Fn& zkZeeI5_}%-q8uuxFFW0+3UDT_V!}8oi$U$X%P&g*{wu+NNrG`XwBZezmJ_2sE&&Nz zai&k85vP_On2CU`yw<(e*GHWgp};{gLm9`7f;p6AOdD)1jy;(Ml`0eg*|fhN+8BH$ zp(+=!@Bu6)0!UM~j*L#B)$RcrQi+>v8{s~={5mUrx%f#brOlT7%HK(Ed67_WaGrZ1nu(R9GUmO#y;Oqaw*gx(MbIf#*90ILC71#dgRRBqJdCCFBsjxF*QXwx$Xn3K6MaCZTUX;#gMFp%X-)L1`F=`jHcQh{qc-5M*XLL5?{rwW6fO1oV_8r;o)uZK}j zkdv&4jbP+6K@Ss5B?ziQ0Zi+f`e5JnY|lUXx=D{eczTFqGxql|uS$1Q9?wvSVm<_* z0&j5esc*&fIoILzFm6Z@@@sr-cmQ|~kTl~aOZ~o=MBTm+cUAToyJr}nugS|%%S0{NG9}hYAakzc7zUVk-H=zEp2U7JB?Ug$+YQixai}k&lsL=)quGns3rTHA-H`e0M(#7 z{YY6h%KE(!QJXR9_a9v)NEk*~(^ekaD($2SgmWcded4Vvh3RRnIr)dyy~A|GxN`{|<7Yhdhruyj}j;y})8V2aUfI}#Bu z!$%N23>3!>+pAY_}jYCO-(X0Wyr4SZqo_>=l$9LA?vNfqU_qf zQ9@E0h7Rd&=|;L!KpG?jBxH~V=>};~8YyWIX^`%cRB4bI1nCChTk|~o{ocKg{nvdT zcZ@UFTI)Q2b*^h4s`pOoOF}0{wLCGsHyEI^`BBAAF5^l6_E2K|L=+@@iUPYct(t!& z=YqGcM(%_01%$i+7!fHzZBac|-xA_AxYoX)A|_CB%=Dd^Pkp7r{?CL zX|*N$nn<0&$D|EdFeQSp$k%P|7jF`i-TumDdWKbeUN=ulW`;qa7zq7Wf8w`Bw}S4s zu|A9^ATj_J{qzjla=jB}c{G9F%_i{m2_}Nt#ZxXl1_~fV3`1Az#SQNA@bF7UFGM+>T_v-g#(I#NeUu3y7j#9)HioL!Ve3d72YY zy7Z*Ay0NbkX-)tsk&HO<;#tDybSWvwW|3z+_X5!2*WH9UpHj)6sDKA{PUuWPqw9#@ zc7VdY64+A!fy$>TUQ*Hie+u}1US6V61+e14haud}VhmLdWwgy`5u2a_O@Oa#Pe{32 zc?piVkE&7pmhXDco!^Rs#_?0haCyEAFr~V;Jvfi9W@G7*K;V8WA%?LI1al>St_NXH z3cW+r_3bp{UsW?r(T?gCvF%~Ebq}436TI>FDA15oY;mBPQ7W?^{Fz(t`nhy>fdJ6J zq@*PVMqGKw)D{94w@#$;>BzB66o3pYRlO@W5n3Ay;p-7~4_G^fIa?4~XN%Lp=dwP| zux~<|q0gtWT50}PoYEpN)8DZjMjqjxv-%#K|1r^it$(|iM=-6de*scb%)JyPEyRZk ziks10>|n36ABcZDcg|p91&gb>wKkd3g2?s)zmoPpfoOx}&5kbtngLtjNyDO@R9C{T+xpPt`n(y33;xkdsVX>Jp{KO#R{v zN}_wY>d$9wEF-CNYoVg%VI``u)-4+0&afVb8Jf+Vqd&rAm&w(zz zEliT{U$$&URa3UMF6}zuWH?=Q+*fXSX`!I3@Z@QKC@4NLs_a*L+Z2dEEFRrI3gDDo zdZPMy`4)vsSTFAyG{YndACU~q~U%VFPUFtkQI1pdn~T-#?qof zYrNg@+H>`mV@i(?9aJT)$1w7ru(D?U^1)xT!~n9fVzvK4*OqOMTu5|6tO5`r5d;Qk zbsK-1OzW=0w5^&?U;VS^Bj?*4K!z{W2x+jiq3>apG!wfq^Vd*+XH+Z_0)Yc9j7t)4 zqaedaY}1Dm=3lN9Gy$$6VHVzQG~+xXF`rW~!7S-Mk< zy%eyS+|~tZzkPC#uWqk=D8JXX6?mH>X|sVXFt9N87K+x*q9*xk3iQ#uH+ib28qr?J zu~HTTq3w{&ueSESri?Sp>f{u5gPV~^(t5xp|ntQe3xYrl2|w-q8MWg3aK+=T zu0@WMW}*5e0R?(~d&hYlvJda+oH+_1Jup2(Ct0x4J!EHvZ;E`4(`QZB)^9hu;QEn7l)V}=Qk{l_+U=C#+& zXEaj)x}T9;ILdJq?HB_+&SdDLh7v;I*J^Av2i7I!DlhMAi-Sewxq)<2XQ(E_K`*HG zLBcT?%Ri$gJv3}%v`;&`I3zf$AHnTzN~0OpaJN#nKOyD5mxo98wKK7l42$1y-0nU3 zwl@As*xPBLC8TPrR-jaZ*sB=SsE_=Ia%G@)hv6vQ|7QYWrF8!<)XRu{$FmcNScX4|e&nJ;+MD z@34U18BL4vHu#AJqQMysk-&+@Vvh$;CT^Dfko~RIJDIXmh-Swx$Md($?eu{t- zQRxDc(29?e{@7A((ePVI2~y`=CG{Z$szRg@Akj>?8OYXWK7SYR*qg;VHLYkL+pA$5 z5+q}3sU=9i$^*ph-wI#5F6V3#T8II|dF1Mpzc~yYj1%KC1 zUN{^3&O7;|e9-R?4Tj%;C(_YWxL`{kBWzDQ?05f>qInKs`2?ikzkd&4YKQ)E+(_tx z+4)5PB680ZUDQ$XNuFsWCZ+P8xair34uj8`%Tn7iw703V8nG9B^)fGMYR_nWH>Hec ze{rTIl|a-sE#mpH5L-X386(#-w*5)nBeT!lM|*ptPcWA&TRxr{p69~}3_XmR*|IsK z!HDG`fZ?JOJ6a$eln*7o52C2Tiwr&J*% z>%B`=pb#qoSksFkAleHqDr!{{Gh-G2EdYa}=EpDzmdY!DGQYjp&Bd^M4y1q^g9 z+b00rfu0?&q!NElt~T&Bw8l@oUEt{7&Q3`S@NQM)zLZV28&r_4=VpBOW5ye-B_#-|f@aX9Ss4JW zdPq6&R~FaZMMv+hL6@nYNyeUxelJmPK?NH1i%%*L@5x_jow*h$XOcPk%crsZyMJI2 zZ~|vK=w=`QQSQLcHXHPF=o7}tJEE*%YB=Ye8krdQer`JBHf{hQT$&Ug-5qHo#;=<|kN4CI10hH#%8A8&NaqW0pl9Ct#r*WrssG7dRIb>mZv~uhR;maXEt9;8AH0cI<4L^dqnV+{K z*4kW?w|q#8@7B&8NX`%5N}04+T8Fi{)1~^b%p67GOV!5cha>Pp0hFDil!J5(c2f1wRJ-L$}LkqtwWA zFo^2!N7+E0;EPWg-GvBrqJuw(;M?M2rhjbv>P5jG_=&3+E4$(N0HD30dO>)k1x9vm zlJXG5AB>YTgEs*Y7Jj)j)6UU~5tG$s)8>Tt|3mlz07)^}=`CA_CuY2ZLJGn>)w&;H zNq2Q2JkUKIi1+ze!wW#m4O|sBC3p8D)B$_K;jvIX1EI8!KrfK5nRvc4B@)drI;6lZ z$|xT@NSUgWELx<T!+P@R$>+@jsgtnN!=!%)yA|%4KnTn0W3?Gl2D99dB0eA`&4qeR=n#0l zrP6}Zi?Cv}nos}%<&8cYQX9uj$pUAX4m|J&9#IRBvXEp+9(~>fJMnW%Woky)X~5fd z8satMaEiE$z72ODKXC%=k1(obwdQo0*JL(Et#E%0^d!*fuD0ms`FB6xCN*og`fPK##@2Fd%mTtv& zVt$nIu7QkU2B`@hu2*T1YUH*!CJSW0RYwA=<~@$BP&fgoWy*+0ZhJ5D8#iZJ60^DGZp0?1M;u_s>0`wc~X=c}3GNvbPC43UBQM2#E zeK^&A=!bpmx#q3GfFa-8Bkq1kY<$y=n5h=A=Kuz9{vTFHSv@rlFz{`69{?_T09gQ_ zvFb@KIOBn>DIZ%@i$p`T_}f*E;JrFCz6uYi+_IVFZFK-KBDRhuLbCihjUbBG zyGm{<@%8kVnP*E)o0>eZmGco8Tr2~nGO%@sD zjc2Q?Gi(1|9R?gM3{OYsY13m@G}twm;oK`ts6Sl!ZOr$Y8jPk@7>nJYLRkJvD=KSFCMhn*HHEfI2uNeH<2fgb0-q9-J$7c6 z*qt@zlopDK$jnU?<9Hw1HrW@0cM8X1z#<|d9u?2(Pax(t-9>Xn0}mu8E!$%IKfMIV zZ{0~xpuzLa22}ibB;=X9D777}|Iko=p=C2(v(!4cz9UQg4c}+On&^tt488;-W1!eY zYWt%0Y3KI=5v*J^Rjsb9Wfq__YT&Koi%U(jgp(*5A&WD$1bG{Q^dpIPQQ$bcKeVrq zO&bjsL7_kh43l^5hiYsmTSaU(mtClKw1*&xB6PM{}z(@KqV_5WDw~3_V zPa?1Pv^5csjV&bI6#ujAapLZRd6~K3eC7R^1f;p)Tw27?>cu~cUi|KRdVj8>c+dFT zDaO8MphF;}4Yi@0H|zl5(tpAPKS3n`^{fK|@kQf|TUAG>`vJ}* zvMlhjTxWB3vj8*Br_xMDR0g(kRG1=nS@IM%%a20+dLh)WYNHn8UAHWC}yjb*#x&Sm0A4a%}Tt!UpfRHVK9 z095HO`0_kFByqpak70KA%OB=HuOm|9K$YA%C3$-VAc@B}%p7rViwk3gE>E&06ewWO zd4rS%VE=*&uE0^u1)x{AKsg5=bi^Q{#3h#^VNv>?lK$!QFAT#f{l zLQlb5u8V~L)zlZ4QSnX*FkOU|i=NmE23FIgNRy)g82AZL0_KLC5eP{^-*C6)Wo~M{ zUWopx3-P{e081LY&uJEVdh5KnE-JVPu5WQ%4CQv$($MNLTB}DJ?vj?ylJI>xi2s-K zw)9d-i3Q-nSRvE3vixBD*5u?EU{m`CrdH&f<3!#X%3Nss|O9A6x-t{Kbj*)Iz^^hs)5Nm81VgG8qJrK)X%ne3s1< zqs6-R+ZA+oKUwQ&0RWa5Wk&EP>B<9nhqBqrX7%@_X1oK=C^9`|e$_yPc|OFvw~E`Z zM+^n@u}&#u%#T{ze`4F0nr0u!^`Ui!c>CpPf==-qe zgP+aB!YoJwV!{2Kbu|T#{aSEY!|U{J(+jII<*|@*a!zN!0`yIa?64~QWs~I1wg~fl zQfuQeRJQb@#?IcP{&K8uc?bNFVL;a`2J!HQp&KCd0YpiJm=?hkWW2ubghuS1qN3gr zj?xQ;610L89*_&bRtIX1x(-|A!YkM>VlZ+qD#|-by!jfC2$_X_>K{F=Kc=+PK{Ws) zB7zPk`&U`oAN;$3+LAGu6H4EimoD`jc&UDP`O!3Vf4BGqQCjqRI;rgr2x?^mr?KcI zeQe*=kVmZyiVc{DhXHFY!4_|NSE*G6d^QfbgyviKu8WD?&$!^3nL(LAf_n%$K9e78 zi}zFQf9vHpGxILK_LamKH?H1z#j)K&Zj36(vhP_tYdFTjqWXXPb`1*DKT#+X<^!&r z>RHkYBd9J;uaeMp50Y5OgCo_QZcRb5u#V=4lWcx9_yX%EQ)&U^EN0x!3_$REolo$e z_|UQq(8)GwmVTvt2a_DzT7Cckn!Y7nlY$o^t$M*QkA>6LdGOI-2w4XiXn@&?Kh8&j z256%ffG2iXYY`5HYes1IjxJ@2x84zodL2kcW$&hP0^;R^3Q}nFlEA^u#O_?VkzL(+ zVsv;E+Y*cYo+(C;GNyC}H)@Yfl=nkz5d_kd;y78wU7c?cf%TSfll755#idR z|5t6?2H)8lcbXG8EFIyg$Mg)K1p&a2WQ1PxI264&`9(FM9#RC%7kq3s=c@yW3pUf} z2{7aZuB02hDh#xfacl#{@7}h|W@6#8VwxcgTvwJ^V__>EiBRS@K4JU>Xpc=cbL2^E z-7z}#dNPm2 zOI+n3_j}-Wn$a@Kh}K$`u?%JV=JULM!57%IavywgAi)#s9EW=4_BJyD?a`+nwh5F8 zosazcwC0xlZ4L)X)m?Op2Uq4$^;K}=<^vg}INGpd`0iu$?2*iA#)Wb@YJOJv%Ys=kc=-ExW9yJf!N2fQ9la2( z?SzaLs>oQ+4YQnvLb>YCp@Wiv;NHG`$yB!Dsa8?DzMo>LGbQs$MYd=W;f1f)Hbme2 z%#^b~QJ`6lVJ5zLtE#z)Nl#JVWrUu0OysR4r@kCBj`iA)QJ2y_KK8U~?0YsGBT4W%>i1cdjZWR&qj^(sgpoa`oXa$9A#J%75B-_~JXFI6_9Jcf#+=4KH}@w%h0V6Opy zV(AcwCceddfL)Se4-%HqP24}!!3=A@ZfZXn%(JQ%IEoyQQ3h{3d^y{Te9<_7kz)i# z&2D!R>RHh)-!({SNs*=H z4JPavyub8Ic^<}{s*4=F6dR1%?5H}2z>o@b+#Od8mbm=P0#Fk3+u3xLET6ZUvG1D; z(hXpf5zy={wZ=LA@_w|69s%Aph_0uvPk6**JWb9q9V15Afsy+G^auefFEsI~Hr1Ta zV&(&dg-75*+XnljSkJdFgsOR4TG#Oyc|9MDSIxxg1Fxxl7LSN%_C`*FkM)x*J+@Y# zp=XB-DRxfS$A-4?beIaA<*OE66%NEe8=yFG}-_XInv3;NYo9O2g9?O~>9lca;8zne3 zR37v3^Q*~0L5oc-LAb)IW6W(?xoD=+UgQ$9jF|h>QOPi@w+7SxDafe9AG7I8Y)_2KC7<@rhDX zX1vc{CJ(f7Ltqq+I+Ywb)HIJ0z{fK|Q7!}2dWPCbzw&&H0PiF%vaMe0!k3EFmW8@d zhmCW^b+4m)%=P4EQH2P?fxb+Tg6zyT9rDF!{L6z+UG9eh7LV`%`5HkKu!?buZVqBf zFFd3pVo!0FKF>QY)Fl@1%h6l6_;Bw%1lJjSzG_}-v_~FIV`C9th}dhM`MgNb;d34- zXP*%^Da)Fn<(?|~XHyGvbBnRei$f$?e4^K ztJ@bS7Pl4IUUy?D?5*~>-;Zj7WkcU^D9{hl8hqvRDL)s;Vm2 zGa{Sk;RkY=zr^4MIaJysHi}0p%@L0h#60c=7>aF~MpZ;jn<&BP_fR?VisD+p(BMEZ z%#FD2?H;YkMd-ROZSoAi&&i!-PWv0wd$(0=N^S5BTMNN60CIJy*0)C~6ayQ`?m6-? zOH0N|^jP%)Z`#&W)E4wSTwlHpptL&a_>KM$;N-*sUd`+WjlrR$I*MBjTn$COCW`)(crmz)|B@DtlclEug4 z=id?Ze}?HPkkcxtpw~bOGO$GEIknlExEtY)3k7(kycXQ$?!P>a$b(#G$M;>|I)l=g z%LzjSyo-{;e|cR!vgpG5_Wjk?`bI{sZshlw-SZZ&2STkIi=LR%%xt=tp;O5Px3#GA zUza_DN)e!5d}~*N_!vDP=N)W*JSR+ngns<2mnsSh?e^FHT6j|4!%f#~5o)fu)6w5*{Noz;|EZJ{pi&~9NM9K*Sf?BYw62~5!&99Sd5W2OR~eu9 ze82lxW&0a{O^~apcx=Sy_fyj68mbU=&se{czmk$~l%J9kdurrr(_1xA{I+gsGrFzNe?MoMHKj3WhMbX^sT$_*XlWd`(;454-^ z^3gFm9X4Y=Z##U#P$4c_ERNy)xIvQsP3v)-%=y7Jt9!j`V4Tc48BME*2LoV4oR z^eCQ2eWu7y7GEjls;I%&cp~Hz z!3;A&ebqsF$l_jhjj|D&VRQjX?r>HU)T3;3Ie-m<{l!Voayo0N#fMtPTeT>D>D5{X zzc6XR`OOU;ZHdSD{bIVMx@M6KZV5mO6Oy@HJL=n_i-zlO)5n~9f(m}guGbj1E zW+$kM9@7Dtt-)1qTJ@IN?WJQOJWs?I>OIM3z8+$B;9?WzFBt(Qzc2O%8|=VdOZ9~( z;u*WYDs;^{1M#{2@p{&eXPMWiw5#y{Tg_7*L#0!bEI%#oWlbTjeUaxfLYxW;2uvo8 zbAnHBFGIvg%b?o$`E=Hp$RWeJ`FjP5`gHKmz=dWQt3n+LLw=wl+|6wnEw^00m$Rp6 zza7TsZo?gP3!ap-axZ_m$e+> z3uQ&N=Z~IkiJCiM-=aumU_%+S-yD=F476T5gU-+(CXPwjcsh+0_h+eE$DMqkopVQ< z63w*fg+bNaoI!jxpb0$2$hlgq;?194a)Ur(gvr=K_7{rWIg1Xzu;-nTo4rk@rCJfj zqCMaz;fd2Tp}t|8Mw=;NYUG|aNig+oVJMHkUg;Sm6SCocuxRlx(emo z!_vZ7t>DX-l2)a- zHj}DI26NugDBWCEQ6uG!-&DlLru4kKV^&Z!-C1DN7BO-$5kTdpoQKeiJ!n38aY-8q z3KgZ~&iaU_tmA6)eL@FSv8VHm6`~>#P=tII%NZQUw;Xtn zrw>~dC@8f5a-`RJ{x%CpWzB>ex8vo@!sI|w?D$oW@5aq*jqGkS=v~#iC?2ir58Vc1 z!nx|_6n{U8C_Uu=Dprol04-5Ch|P!+?eurZ;N&FJHCo5x!FOwA-}9h01cis$h!&ed zXsu5q(1RMoHHMj*5U5SnL+Pk;?0_P{^bkIH1+NvD6bx_RGY zh*@2JD25v4&RDX7 zM$6SI3rn8KJK}w~3(h~r;P{hl{CmGzFL#NrZ{w(zU0mH9fYbwRf835|^azxJoH3fWI z8Y#3cBiuuaTv`ZhN3lYuz>wHY&empg)8lTLIYvN0I$bRSjQ?*;C5PeUc};47g3eer z**CU`9N%zj781}}e>Jt{VLhd!LCKFa&zU*(#v?D;ERPnxJc>cJqdhRt`Ej~6Jqa$8 z$(!BflU}|^!rvHmMU6b^&^xjpWQ{5_eWc{)eux;_e+P!;s|2j`sl;9h1 zY#kPHzULJo)uaeBuiPmFeRO;afpibcM?fgqp7x`$aL-{Tw%BSYvAl8JpbIO&EP?73k@qYF4!{`zc6{UUbxda(&^%cE?U8Cs1Alc#>l>Tf6S1S34ZA-EN9M`$ zqHVrn=$G(E82$+rvvS!)19iSLmRV12kkaBG7iQL?@_GMOD&>#)J^NVFX2R@iIHCM_ zk`O6;-8YbF%m)DJ=xEFgdMtVrP)wvK7itn+67fO@_a&j!ew|mu;uFbXo#^Ui3CiHK ze&mW$YO1upJ^3-5Iy?JP>}B|tDD1ClQI_#Tesy_x_dX2>_MgsO}KM>XreJ= z_{&}nOB$cfyj`3&`3iXjrr8hq1gBQWnw#aK%{-u4+`-M&r?UVTH0$zJE{fOC{=Zyo z6i%~;;k6eXp&t~bWc$H$6nDe0>*?Ftyd)qE@W)lm?(#YOMz=qX#?b*-7nAV~&-Cn} z;=_?x?V{k{%^HAkC@2O5nCR_$mXl11H7|kyKwt|sfDVQx9sdkE%2N1|Mfbl%F8jWH zf4T@uyvb#hE00}Ne93mcN+wGv@ne$<4HRYS8_P*C*_F4f92)2`#2FR^4lz86V*xS# z0g}KSevi|^J2_=J;^*O7S-NS4*B~K*C2g@kGfU=kb{3&Pkxd7hT5%xf_UJ|rlf~~h zC43%^mL}tO;6wsLHZcN7FEo3*V@6Bf`%lBFq7{id`d2vIda&rx>*kCwbg8=ZQd5^m z;T(|7txc0irhYEWe7Q_E!aB}LqluzTGoJ9g7(65i{M`3Xh)=zC2VXw|qDNvXfS+91 z;?Ivhqj~OtUB`m+cZ_MFt=j(;Z(BO?GLsfMejDifd@z)Mjh$O4L-uM^Q*Wi(I5Ih@mBuk789;x!+b%~jqA@)%%jh0a}WsQCn-NaKZ3}=DRm{vteP)+$daiLWzBY)?>9Xn zcNQh4L8@8teMgS|t5)g4;g{p&avH}y_lJc_cJWE9wK1Fq`V2M(amq3tY=2osSg?LL zfyZ`3c6^jIOyXZ~WG*bV$K#@kNat561Wrrq^5K}k2JaCW9H;hQm#7RVRT;KA9z4O< zr#nhusonox1cnWnbp%nlg~`8XEh`Jp&Zdo{SfSfn9K0NeeI|+& zV?f)(_h7*oJO083U4Vk>ePUu%TipK%^Q^RlMQP_VKH)Q-z6$SW8aHnxZ0g`B+P@qq z9Jk4Q@qFNVG@H0Wv>D}fASE`(v~S+f0V6Aaxv4T%qX2gv%ww~og~A;4$&J7^0dP12 zQ(4KtLWd?uT*k$Ee!s+S`*M@4`@G*Qr_CMmc+n+tZ7ewX!-sjAlzcUy2>ytywyv!Y zGl~$n3bf)S8P5Eu>LMR)m+BdE4+%gSyOu5)jl_o9B=<5FyWeaI<%kATkkzh{&dYKd zmi2wdHLZvCJ#T3fEw=FDovYoA_zW2XWZ<<9PR4+5liKeF>M-NPNKni-bC{#G`8rHs zHP2Z2)?s+ybsjfBWbJs21%VVNXrpdVq^E+7+xH76ICaqUpOzU2+ii8skyk|% zuP2wB+5!{?&L4o%5wsu9KMUJB8>rN1H&s?pv>ocPg-g95;t+b3+YmpiD+(sVlOop(>mo4uN+SlP&=W4{7B1`fx*GS%=*mg^P9my;X0uGlsl=4UOW zp>ZCW|J@Pw+X?+N;Olpc6_eHFBQ!earYMDrS#R^)wBU3-o3;r(A{0DE!UO4(XJvB5 z$79nTqTatFbteyi%+b3Ls65@`X&IkePe5@VYYbVwdRp*UP?0%uXUhk$-Os7WXtWlmp}$ZW8iP zYVC86;MeM@zvU41o?}|3THYtmP-vp;A3g-$4=$3#><2s=2zWYjw_YXy$h-UsCh_`p z@ohPsijXWHY5if~+JsQ#>sKeC=b&{rsRbL6tdWlMI*!i>k`dBSvFa+7roPXLW}SKf zE2-5qs>6{UFVH}}Iv-3xvvm>1iX%Wjcm`;p%oX(8w(nShrYgUeI9+&za?y_|)EVD( zM|iwwsx~G+H~4ZPNgoD}CFv#v>S%#hk;VL44SNS%CWuaRyMFY_Qojrp321OOyOGu9 zv!xOj)KUXgqP1EBt>A7-ts|~BVP-Up|F9uqzl%fX8BW^{XCMC2!3LkU_Ck#qn<5*a zSU9BO@W(Qi@fO&RSrX8WoPB*?!P$IR7*PBbGcNk67e_b&V_hVQ)E3WypVX|8n3Sl3 zl43oMYP4fdAsF}fegr1V?K8C37>jL>ex->S0;sXTd1Zp(rX`F`Ck?@_DiS zZ|wMnddYL=Sks-n8B$uCyizXX5TMyp*i~j4gB^m9t$5bb+zxT%RVYCd7VJHh{Dop( zXh6>(zpP0}&$SY`9hL8Q7kjInmn{w%(ecod-ubhMbNHv%K8UVGN<{X5vH(|7L$=v} zk4a3Q-0O6aJf)NXdm~TWkTZ^wj_U*&i$75~Fw(Z~BCu5J89}E-5>MEW6?lAr)e|t# zx01rM^Mda;FwXo+sqg{IW?+1^OURFZo0P8z)HXsQo;4~(j!9Le7q@d{lJ>A3VxpHe z;x>=_L$6N+M*9VRPjMb_{R!_^kW;=V-1@!?Mf@zF;JN%UXmB|gO(2(kl~FPKBwR%S z4^8}GW{8*ccRtSdy=>6xIj3L6Nbq+K?A`a&sR~Yfp22lSY_Rbx*#WU@jR`uAZ?h|! z(^-K-T4R6K;+80&+TKP=*~Tmqrb0Q5VzIG=8e_{7&;Ks0ysXEyUON^f7x7H~&mSd= zhY(`e0qW#9r8r{)5l9V}AA_&6y8TisX5Y^NXX1^oewqCEd%X&UvBC342{ExT1MKLq z$d8ZfIUOWds@i2Sknod((F+AEI$w^o;ZTNo(_5Eng=JUYCR$x?q=LUC=*`N(hRV@M zpNZ4VQb0=*D8UUEpp!8SgCoJ`Fo3RKM$gVM8AJa<1QNt@^Oiy=j`$bTB3*5Ke2f9 zE6_>>h7ju8e-y`6)%DQAF??d_YQS;ZS-?+Lv(np6;4AqO7Z1`LVC3S#fnh_ZH*Ag7 zl#|m6#RUV0f?kv%m>ep&%o^VLw+0J}gqb9wJ9-0orY!B|sP$=QPo8FDNcnzpP5Q?dYakA_Fj zcicWHzI!OFZ&bYRcvb05IbV@@BUD)cPWkZfUE~ry_UrSoXMOz6Kg36BpJ68Fjm}|3 ze`73`|511N?~;NJH_`U%4=vlnXmGjB_9XW~G^spJ(@p+Li|=9b_M$Ea$&tIaBA&NM zi=DU9XRWB|I+aIJ5sVBRFHZL8Bz^H@nqMUfFvqF}aWmjkCeR>I{;&ID^du}FvT$eb zgTBguS6G6n8KGMRU+W3y)1|oth*~A3$nEWXAQ$Sztxu5hbtNf zhVXoy$y;JR2~XHa{gDru^q>xMGQbZ5uQ31?91dl%0SAISb&O^XF7ezvyNb6Q0?aE$bg-4GLd^aj*G zc`gv}h*4D?-x97cMI92Z{Z^Qu&i~1QEWol#rF1~-{X$1|sS%pS{p%+@`zzt+r}qlL z2FikY!8VAgCA?#N%@`~ZPj&<48u&tfJ19U^U>+S7m0W3zqvZW6nvPl@j9wv51At9I zamfKoqxFz9z-@d9CR~3 z*TM<5Qf_f>$UxH?e8ZzP#0i{c@&O=EggT&imjXggE>(a5TISO+eiCdvAW$gJ$NqMQ z&xwtj)Q9Yz^a91cr~L+Br=senB#u0KOZ3b6tLWW0BPvN2lgfdfRM>RAA~9kwEwQ-G zg_zyt_k3y{<9l@=;7*OW%3kq{-{voUnjqzkw!&OcigAY2VH z)jWKZb&+t#$qjNEWui^)-of3o*=g{a-o-h@YCB!`h~t?a;Hky?dO`v1%u`ko{fPEf za*B~d99kwzMrCgx<*GXfu1O~TC`Yp&}HF+U@-9?PT-Bn^#itVb5fVRE#re}H?G75e@t2d&{8sIUBzp(<9_#M1eJEfEP* zH*hlT@V`tnk(3u`@PHw+c+3e4FMV+rAI;#JWU{bN!$woOIK=Z_+|T;zm=5`5Y?*g zAUY0TkNbMpzc1E*bl28xt$WPW!qlxnybJt=YxsN64Adh8SQcEQy|7$bdb}0tX z;6WtB=bA&-Jxr>V09<_f{XgVO8o3q)hZ9b-FSLt&9q+Ka_V9CZ;R~8n97Yck!h?TW zZkP^iWN#7o_@GnPL-Xo7GL9I_sDQ$fLMZN2xNRuY*sU5i|geSxMf8VP9zf z`8R@VJ&tt8A4^o6_p8=NS>jlxGS@|K^6h%C(0cn&A>-9 zNYfL#q2NlCDA_t>s)A#2J>D57_%wbh9`M&lI60!Yb=UkQf617Wkbv#U693M--2x%< z4}1VjFGGuNh)qyFy53kmV!vGkcjk-iVXZ~se#0pGC#>c8B;cV>^Ryp3Cdz}giB9TjpQl&fb^_)`xRzW99t zLOLR2{0N$+;u8-4x1SL?;LJtH!p}|tq=6%0w*G?rX2VLEAB+#jtJlun{oIc+-u(nG zQ318SXe)ZYOx+Ygpnz3tk_a5y=>C2MN5>`#deQ-?_wL}3!=0h@hu@0(Pw}9n;>rF0 zShW@NCrq1cOblwx@^qC<7Hgd)M8(9TV?6-Jl~Z;g{Qk2n1fiDs?n}SXD{}c{*sTPa z;ny-TsUJP<*uTsllLJ)Io4ydCNOT#w*&NQy8n=7l+k?9_fb$faxCT5%oCcC9v5$=6 zO=pBO4r3O_xG+rmLFQ(_av1JT4}%@ahr*I3CyNN)b1JV zxeP$tG*nS#4_!8Cg!Sl}f1Z;qH(L$$Y)$WVUo6-JIT=+yDiPp}>$`V5&3iVzdmb+! z5DcqXmi;EtcVR;8d*VLkI=53{Is0BNwM~$$q6~#TL&+7*Pf2=j^?uho8v=i|sKZ7` zqTqHE-Z=zVq>yxbBQZzDb)K&9W_`;sQ0LIXG@_g879FR*SZK=Gu0BHF7&Je|ABvwC znL)PrtsWP9ynWrh6ugg996$b1t9EF-#91>Jou40YUFRWpXfv0gDn|ZaXq;VR{-{vykUvMdP zlxWDK+-M8qu5-@{fw^YtBNejVtdS{i++81S&QpaAQA>Fu6GvS<6HX2!j-P0cBx9K{ zXWLbn#B{ul8x_*Q$Ug-~Z7p+Isp~p9YAs*CUG{JVZzcNdPIPaAl>EKw64_ zGmFyyvfi`ZlWV4Ufj}0Y7j{1T3%2fZz))4=1?a=cb?(>)~-FO z!%@XVdcwq|H+Kd6&pOrc!p(@sv6OT~T4>^gkpRM6R3uTT<5*7Sq*VceKbd~LA= zZFw`xFuHi3Kf=Gui;Hb^=@b5P{0bAu`SAjRyi{-ZZ5t@df+nWuLY?+ql3B}GPqxpV zvMK2`Ts%9ze??Dst_m=L^D&mebmMlORC|T~ReV`{ODc(;USrTFcKZIO+ZF}E0e3GV z{b#%?*pWF*-wtV)&wa(jdHLd$IP@x9VMdUX*51b~rL6s9`SH^*t%f4SKEJF^m(Buo zM+DYwL7`FkI1e!`80sIe-S{w(#rK7`xN2Nk#pe;2zT**3%&n#r3NHV~q;)_|JDl5B z_g7}*1vf*nO_$#A!-FTOL-<&FWt^ak%lP3}buP~>y%4GZnCC(1^RUSmAnz5sjBFxY&5!-#vY-lpSv5ZP7axVnQGw=hA7~f7~7ov-KP6${l8`49u~=9A251JY@)1 zQPu*k!|GH{uw?4J+-KpKU79Yi>>GqnE0vej)YM3YR#)clGX5gJibx^1c`%DUclsZ~ zfKM}Y80M#%mi$z5xuH1lR0+_<4iWpC03a$-m2`8CJ`tSV^rh{7Xd(cFASSUyuVNbX zPIMF1sX-+)ZEuk<2RnTb0VJeJRi&ppEqovR&;*cFOfbgx7;P1>IVob}M5a1`9G(os zNe|t;nM)remDmKlv7O|oABz7Ei)Cg;6BZU8-z3@_jFG%xUe%z&ABb6&so*QFIqPqj zJNb<1ZA2EXNFMZkCy%l0$aKxsz7^*}9UT}zD^c1pt1PKNiUtN6BH#ALC))I_vs2~Q z{oXFyvh4mpOGQ{+BdKw!T%N^x73;e@*xIPgD!Wi|1*IW-aYj1A^R@AR!Il6CqD?sj z5!LWVge!-_eBE=dsThD8N1x-8K;>x zA4J(i19v$n7e2FC+wZs9dCS#mRo7XauNB#XKfmA*K62%-%eD05!`fGhXE|Lykj9K^ zTcWWZi?EOtalRO447Cy>;9#QjjxFq-gTAe5G^`A8UN`SSv5if^qPqTcS!pQ)2Mg(s z++3!Zd_$WxRzr?RWeA~sd@sn{JlSF}SJ}uDPMtiRSr@gZ`2w07CLUfXN-p2lhZPF7 z2zed-%A}GBCxwqIv=a6Hdjkj7tP9nKvo`=jAT9YGg%3dBNYlmtw3j+=3ko2p*{u)T z6p@-AVp@rnUzjBaovt$CWQ(T$sCs>`zt=+1Ta~d@?R577hu0L=4{h#NUh@P28bj1Dyp#C;TPy z$Rf#&1IUNthlek%bfU|TX@LVwhz*;HIw|QQe!8=qzK4kixwIM~*%tz0^Gvo$#}*vWL5!ExFMa8nQ-s`ZbQ1hUF~J)OwMxUH?>FYEm(@O0A84~)+xkCby=7R`-4`{C z1xSa4q#yzk4&9-oNQtz-0MgRZE!`j?-Q09{gEZ2JbTdfDAPocaobi4C*Yn}|>ZS1W z#NKPKwe~(BCyJoiy(97S^CJ&rV2GTZTgRTU;T#M|Khf-6a@`8zR=VTU$nd zMs5Mapv*_04rCdKIg4r@ih75UiUzIT#hDF%diSPa#%MlAom|v9W83DOmU1zd7_fvu z&2(kSYYfbmpp<>b&LcwPLL){<(jBScO7O{k<9!yT-`K`UEd(wysdOj=eZ##SAXsIV zogv_ptiosoPW$R+TX4>&kc0cmZ{wPIv#N+Sj1L4{7p*9C9%p|j;>cNnC>R9+r;k_1 zirs3DcD}uKXlS@>#R}sm;Ac{Rk&b5KgYV~vlMiTo>PM#n&_#Q=a13P8@U ziI~~Duid9QKf8XGiU#y;!@o~F0T+bBMHs#1Hqitsf}?N}LjasiB@&w+Sk!DMfFfUk zQuHApgp&H99bUA%wTD5x$bFe=jUkct?2LBLz~$%2*TMImAOGdOxmdr~Q7fBQy}}(W z-$OZ7(XverOg(SjHa3p#uu%!ZSlw?z-W5q@Bi3mSi6tVU!HsJE{UrZr6&&*W50a-5 z0a@;OU)~q>98~C>jM0El!ZpaehjMt9-9$_G7QQcj2t1jbgCSZqr~}{1e>3n@9~4k; z<6~+U_4Fz~^*uD-w@U7hii+$8+KEbs7i3@5{bTj>DlVcYL_t7O>E7D96Yx4tVVFVL zkR0263+_~5U@+OZ3{?aZIWf;(DiJW7QNo$zQjk% zQdTsa@71%&%@+m74CF4gqW3at5k3Dg00t--fa2WAouoxql(!rFySJ(8Htcrd_NWew zbRmd}%r918N&(%6ue1?B-H%A(q8w?#?K*$ZpG0+(KnU)~0Y)^Z)7rb=mNUd4(I@U_ zzdoja#OZ;sn@H~pt!=-l|F%uOa6wD5l%^N~{C7W6Umv$XFr1DCo>7AG3Ai|wJ60CQ zUCe0EGGpU^06Ez>U?)+Q@XAmn-UdMZ3mS2gZ;I2UOZ6BKXd5AQu<6)id2!xyj68{1 zot(T^4n7qs>AU2MZE^q2xB}hP8)Y3NeDv1XO1|8hZYG~zGKN3L`wo6zDx__&*t6l ztgo}*1Ku}0jF^-#P%M|pXz!PHtQE%3kQHnn6#W#Z)#UKUfGC*Yljj%K@kz4vBeP%J zETiJX)%_1U@Gh9uBru+_vTF?x|+Wo7NZM@?ip&~UF z#P7z8EKWj|iC8Bb{`|Cz!`W(A^f+{#FFyd!yf=gE@A0-pHnWn9=4oIDX_+C#39!wf z?B8Dfvl$8mWSL((5=v3F;F$Q~^5CvTaT%^~U~>@zLRZ(Z$Yf1{KwcPd$vy^-l5Th8 zFxxUVlHYvJ0W&J?{LxrV%P~q^1kit*`*XF*ML3F7toI5ATxl|+1zeI%CpEvzOx}g2 zdf(Lk=+CKR|G7!cM4>aUYQd)ufRF^@)mO3fg|Dzeqn12S1_LznY`5Vka7k8)E1DL3 z+ghAiu5@%~qw8&bp%w^-vyBeoyY&aYz*)^X$f1ab&;PsVW3q*UM2NkK$yi;H{e3a- z9r51&4(Fe$g<=KopO}6(`lP_{E|EEGcdCRNOKt#3!mftK=nWt(P$b$eO9RSFWKlO}WMZuZ1_&9@4%NLW8q8s{NlztUPZ}!s zbNFPT-4kz7FVK35E+9`n@zvUTU23JnmyzuSZTH=udrl3x_mQF)ucITPM@P3AAlU^T z$+%6tq1;k39uu8=XPs=cns5{b@EUscjE+`?Ss-G61$QYZ(v0F_w3}&r+=ro9gDsrV z$ubLg5?mWikh=mITgQt?UZu2-2viqYv!-$g=yw{{Z+i?9LihGPQSg6tN+Eo%Kh;-o z&qkcXGc^D@W^@swy1kHB7NGq!8t~mS8R;su@4XS{TU7b-wj@(OiwNKJ8sZsj>J%M_c3Tod4JuKL#xC9cXSEldqF~nOqYPaV!#0g0+afF z5$@jbCsKe)W@tmFlX6dREnqR;)IAQ29*h z9kK;6Yz(<($Tnod?A~mAXo0K=;GyV1;Qsn$BebZywssg6A0JHyi2c9AwV&DwsaE$>#o`Clj1g6_07 z8UJHR_gtq*^lFbrdQH?R1u4-EF#F&(Yk=4%-zx}wI~R=h=(HpGGkILrLvnV9K=Owm`eEfZwsv_U|GaH@N=Op8Cnh26}_}E(*I4&7qqVe5py6{Th|?!k*hvW z)1sVzf44@gcO8>}Lz$h@12&uR#~e2K4Y>ITNQlE9*O2C#jM1s36-)wS_3sLm-rp8L zsEq+VU{fZKGxw#H6_t#ey_NIoCC%+PCd+37jQ_J=q9BL9Yvui)7hq8@L-yXw@9&0_ z;gq`?Mk_IVe6MI!$;zcB%O9+IoH3qU_Ef90=@C8p`*Q7E z!H1E&88;n#PAm$Fz_|-@=_*Q4syDV50Z|ud%=t4R5mBA(MrQCIM^D=!ckH|&^k~1Z zegT7&ZnJ&=DrZrV(8gFQ_KR@R7!K~q4=g0idO6HOcfX(Tv5*{!yP0y9yhnK=9hjne zzUt3+FP-g;Ktgv!z0Zjr^egt}>tTG0A8v;=WQ$aF!VNoTF%g(U$c*_en}l?XfKjK2ikKJ-%yNRkCxpa-NvRM=?w zznFZbKP4aoV`DQ$_m!)k00FhOXp#;+Br?1oM34!PM;4oHFGI0{-ZKjf7|QzR`iqVp z&71G?VA2s)Zrm4bgOKd$vu?Qkch((dkc1y!Pl32O>Hvm>*q4!gc$TKhG60Jyq=%V{ zE!S}vzRetKFaJ;kmtWWvsI%q;Rx$cU*XtC}5>mQcjSU!oLtu>>-(x?_W;GlDPH^Bw zdraYQ(`nQS=Z`i*k6c@e+sap>lcW$9<|)?09YUsjCDzf*wrEQk)`wtvh>RHl4!Uq9 zn~d*paSXxRxOlN*xH2ydI(+EVSmbr3QWz5pgv+TH(d*{F_}~Y88~$1JnqTTV`9xX& z%FT;;Xm4Ba1z_q60f~e{dWCA|9;yYgCQI|T0fNLbuZxBeeceELiu0ii@!BK(XL@$P zjE?9^+Q9};r2c3e=9!H}Fgqe;{o4 z;QL^&6cX|CSdaAo zEjVwgdqYCQ``h}x8Ar11?mV}big=w%ll6W7I}26oxU6;>Uxow2)>n&gjqEwd z1N+;<2l-WkQIZ9jDeD{cQ|3#xcT6SBRMZFdw{Q)B0OEIe^LT1CHA|C4=TNbR!IXU~ z%ZII7bQ=vA$d;K6y7wjc>d)aPx%bn_Gl9b76Gav9DG=LW*Y7)kH~C6C;ktThRgTw< zZ0U3(_Eabj#=JVK(TI2p=p=AvV63ucbOg0Oa11{7YOa+Ay^)4y^8Co@F3?Lz8o7&N z0)S-#?A+WCKkz=tcMU5X4UV+#F8?$u-g1HFc*a@3XiKwYEIh{NDBIty=*WviO zgz*gJKG_%c4pIrS0F8WFmDjfW0(Lk?=;u;^5!%@|W}WB*+RlA2ri4o5)y@4|kfHs& z+sFCcI_CdVESQljQS_DQoM3B=XoLIsi*LT_{gdjF-0y5Z7_@TjBuSYWgnmH{4ivx8 z?S?;UXi|D|o2EvY7W&@iodtZ5OCsb?9E`|C(yJarl=tNt$q;s-6)%`_lEW<=DyLrb z9$l7?9o4X!U2oVRA;kuImlUXZ$y3S344Oqm0dKsifWTcy9D7r=zQPrL12wQ?Ms>JE zJ&;{Hu1Oq*5ucoZPFJwBNm-m`5WP5Kjqx;H0OmL@BGhm!HTfVG-^w_+8om`C)3M%aI=DAW<5z zh~+5RTxZ5Y$D%My_baoFm^uDk;Z!{)78Vg<0s*K&gbaRvJrroN=KaWb&bKpM0a^%v zL8iCJx}?UD*rX6J8r>kC9?u*}t{v`niQEApdc1VuSww0RCa5t`{|EY7?KB`5f#%H@ zgMFv>mmjUEzs}0yoMN5)t83YNA`+F+76ROd27flwffH2$mI$Cki^fRzZxw%Oe(w@! z(|sG-1>c{~(SJ-oTu2sKTCy{TeW1GXc)F-pLwS20KrmU;b6=EoE7Pp`2$6eq%t?1o zW%cT9%#~NyGAAWyu`+!QTJVRd_;EnKm09}yJ<{D8Wk9u=q%w0Zl?KfalDUQr=?vUh zkAkNa_h1{-Q>eSI#!}zn4$e97jlQqYQ!ZVo$9VbjuPu&g8So-KJ`}A4hKsrKtY$mK z+5INa41oV<8|RDV29l8g;N<=vRjSFhbziZ?@R_ebN4fK#dXZtAhp9<$vqUE)jB710K!LUrZeJk6!;# z<9*I*AD7zODnih%90|Y*M0P!w(XhwO9W5H zdQLn!1fCcZWIjNnF6bFbtX2M=RB-?5i;>-h5}aPxENzP-NgQr;1V( z9{6fP&{O(;s3b>w|Bpun0N7fbM)zOowgkS!)>s9-%K69o?Rc**)?g?b4MMDu3~O_! zn@5bZj8Bmg5DWJVwz6T>tm97ZqOVpOpPNU}-He5bfEH1(MxO=|e_Sb_bcuMQm@JD+ zv^Yddu}0Nmu+na5Xy~lh#*;&l)9$?=E+{jff)y1|{>0hV8md$}p}D@{4tyJb?PTvf zn^aDM!wU8C=nq(#0*nV!uuo52(L{jz#}11Tk|Kf@r8>8M9LL1APDo!QA}BfmJROeK zOE|!-A>wg`<=dHUAxjr1>nVW#lJC_$szhg=k0_p}v57u7m=)XvxMGIxKqgaz@y(!i z5oig(v)1w(@xTL97dn8WWQ^wygoRa)15$9-aUS^W7--jkr$Ea45%+Y4Yh_ts% zCihK2g4p)&U*Kss0tw^36l_PDr^7jWPR*KFBrQraEIPOu;$|I=Ndzy8tgYUI#2$|r zysAo2$osIi#Wylh`i6Q~zwR+|UzqJuVGAOssMrfU1V&>qs^k+FWVN3^(!P6q!9lcR zulrHiUyzlLTm;wy9tSI3VcBq*jRw$EYyvkC@CUvF--#jj^J6K(12w@D5130%E=MS* zd%;YCwVlmD5k9(rBuc>*_P;w~6sI-K@f!tfag|k*t7n$^1r3A}b+&h^6;_V5isp6zjL zAc%n1K)6mWrQFMEDs{cK-nb3t=(joO+dcUCxfZ-g47${{nhjYgoOb==+O3p((7xuM zeO~VoXPwBEl;4y!B9aJs@eNg8Dds*UJvb)pJl-FZaLEBueAP41FLsJ-5>>L%iv&J4 zuINmlWOwnVPE;D%Qi&a~F4R>2DTdb3ep{N88&3iRkLi{1LkD_Cq#Ix@2Qv8+K@>7- zu{$75aoh<8ZUOq2+Cx0fK)|oG@8n@i5}^Db|RExdF(G}l4; zK;)7m!Ofn97jb+0G>{>HTpq0Sa5BezVU6K8J4dtpO;|X1y(q&zfU0ufeWzcQRVvxi zx$b^_0n$=yh^bVt6Cx59nVKbPcvNP~1w!8{JjjT`e2og$6SHBf$Ue9#4i50m_S)Vy zudN2X0Ap|1{_RER#)mBIv)-KanUl_l^6q=Dv7P{n3V7)ah2OUZ-I6$+nE`%I>hJKr zxR>HW8&SngN-x3{=H}T2)o8A^6-P}`h+qPI?${m4bbg+@$;V|IU^MzrwSGixKAz1F zQt5z*ckcX@oz>90)15_hKEB$tbOH%9H?r;Ik^jti!tZ|Kh>Y!NJDsfEd!1L`o!cLc zT7o1$iOy{GxNCtXr#c4yI8a{zeWh@woN3x-$v^(dkUk!}nKbqvvex4D;a*EjT(f5X z!NOP2j_2E30R2v3nJ^3ny*>Cl(gMFSK{I97>2KASxod5zavpucmLWviaUa|NP_JsC!zyL@oqA21~76}C%7f{e%*~?@AT7*#+~fpp*XT#i?9*QqgGacfaQ>69DSYGX$0>=;!e&2lY7wlu3vX* zLJsh*=2tzYlX?Z53)q6#x3^=*MIY(N5_lu$YzN(yUp z7Ok>Is(?We`Nwk8b+;<6HI3Ayu8hs&uqhBQnDuvsL#ydZf%5gKCw^|5!+;^9-B^hK z9Vx#9W)YK?NgXiIB9Pb+5-1WNt>qZ=62ps&ToR%9hWxb8qxUJ)1qEX_R-sxQw_t!-LLOcUq|;;5Z_4vXbvh~yZ;X&VpE{H zah?M~CZ5m(I8@44njq#1XYXoTmvon!k>u>4tK{cN!t+;Rz83pn{z#?OwQFgH=wr|c zXG)PuAW<6lf^0kUfZB}U2-&fEc0}G6gooAY`X+txaTO_GiVVv>3)GuD3c9#@3K)RR z83Democz(7krZgKQb@^WxhR|O0gD4c0T=v4UjQNL5}XP0~7_?^QEG4LNvOm3ov zVYwpqUrf#dvFEnAzPoCK^?ipaNhgv9lP&;}3BKUN<@?hUcT=k(|sSY zPr+%#K-+dIQkcnIn6&`5ZUWYX?rz+g{^%d0-yKx)r8qZ_R{{f2gB4JeGmvq>jqub4 z8UYyd5u2qI>vzO!*k7Vvrj}s(ex#?ZUwNW==Dk8%+e6L>Wna({93-vUXK>ppuCkrl z`tSJh)&$+Zg?ViUy$at_t&_7FlW3TF_FB!sRU(8co?V*?q<~()$f1VyxFIMnXmX^Z z^^b4#u?c8i?rX8dI-PxX?d<)Rkb;#Z3MS>^2`K?9?Ru&<+if!MW89Vrwnt!4%s1{j#rL2Q*^nh9a3+Sg=AGRov7bc4|uh zvCk@GW5No95k8DB8X!u}slLds9bX!DSQZyDm;c2$k{)$>aqIc%*GAf2`-jh|dyCl5 zk0>HYPRz2APNJ@yK_PD|U$c#iQm^dTNW0*oSqW-Olvt$GVG7R84U`zNUJ%8&R?SRmViy>;kb+1w6_;%ZvFRPdVh*| z{q@V|oP1VuYiG5g<1BG{PA1M<09-M~V+^JVvpL@LI4GiJN_5I?X@% zDoG_4CMJE2&R6)cb<`e~kGqE*?Q?l47vZ}3LgeyPib`a#i0|%Kj+|tz&BX5#2aU1? zHR}R;^OT^o)V5Tg<;d;@Ry`RFKB)Vi$(#_<|^Y(VZ8YC6*}(^gP6Y9@)e(9!o;?-Rolou)He#=OS!st_WTqtIn^6M(|ya znm`D-^c6b(-*U309mn;4eT|!!lq*z%_E-g@?k?%g7!8^wJjKOpH+ih%Tca_TyTQF( z!8Q7Gn_O&&Q?CdgPX-A^I@J2dc+_RTc9HepTRzF@Psz_9nk7y9R^`(%+xszuxso}| z&#+ft zk2cW_%R_4i?rnI~6^)C^bMNgv@TmI6Wixtxpk5eTliUG)QN_f*MG&#bE86x@FufEj zQc+6kPYL^@W{utDI2iAQNA{jy#B7b`_BveZNfv$AND_}Tj`#Kc1IL|l4Ohg;&Qo$^ zpGV`BZ-13rzjzmHMq~3m@wMKv zHAq&x{`Sw5;F4hLk}Z#7ch{eeoFlzl_?%y0mu$PPy*4)D^4P=GV!xXsI3=Kuk)HnO zp}Q{>8r@Vf6Q1Fq)q5CNj*rz@6vreT#E|pxbu7baQ!{qLNUE=y%nH7dT_v0^p&T0C zE-7m`p9YCBtHO%bPX#xuZ!i31xMukqXhyH{Q@5iEy_;`wdrS3M;5416^3^Teb<5gc z7>%v%{8Y7nb>KHX>jW0}FCtEh1IAwad0NZdik`kW={010$-V)@J+z{1?x{qgu*NC+ ztd)kbiAgAqyi}dkx6ZE<-9ZLZ{8y6irEBJ`T#=J*+uV)}q!qfV>|4?^53AV>;XlNn z>2YzX!TR1hM+FhB4c;{_Cu7ft4cXuihklN9$L~0BY`4oEZ=H7p_9ZYpc3BcZV{Olf zT);RZX`g;XNT{xB{c?OL#sBb&uK?P|`6@4_d$X*w`9mGfj1B^tUzq4Kdt_t{cf*xo zH*-f>)+L)=uuM6*-Z)5`uW-LexX(Ea0Zj*Aqtk2KiY?INrRx>cRB`gfqwbX^^qzD% zJMBw^{3H*X_L=ZC4s~Gk780#s@+FV=9;xE-?Y;~AZ%s6P7ZoE9A0gq@D}uWe_Znmq zll{BCU$rOqKap`h47P(f(i7!?Uwi4ixo~+DU`9Ym@>1k(I=#hi$X|K&>gD7&_jdQg zDLuWZ$nax#rSnZ{Wr!4M8B z8-KLnD^D{GSKFdpMcaN5H{dtZpmrgfAAj{N27S)w@_J-~a|6EnghNU`R(kMZyyI-m zOiRXN`kcQ>5)rPZr?*;Swxrk4Np*lG(sUJ)#V~GzBl{{S?=}#Q_@{>xb9;0>D-gYx zo^NX!rrork@x3h%@43_xHzA${*P@ztZ{ngnn8WDsz5vxH$k#fndCZkjPi)l;pZhU{ zYyV=D&%-aihli871s*wM`+$7ovxKaNTU2Cg=U#Wg zXa&8oo@b^9U}PqT_{#=DJ8%Th+i3Xpe9}?LD&MUQ*=WAkmgciu_B^;jvnK{t0AJ-M zJ|4iXSa%#01nV!M_%GZbHbiS%TJy$drKC3WeF3fdpN_15s^E5UxBYvm4}mz0+~@nt zxax44d?~43r?$UXh|@Vo1qxyGHN)&K81k-P1BaXsy`r5TJ9$p93x*Na>EEgYMq;*I ze7(X=F)5x7@e~c-1P?ym1>3HVkoD6GaY_6O5F)-Gvoxi4ppLj`T&hZ#nH)4vKKD(R ztyiQF6E+bM+VsgA(e^24`g|?dgwl!J1x6^eUT)qrx?RG$E-djLO1A2^3@#z0#i`GU%>tvM)EN1FiMq(AV*#@vt6HhIa+x%p*BSA z>a(gZw6$Szs>|+G^q8D*T$#l@ov+}JqKAf)jH8lFIfGNBDqfy;YLKys#cPdM4rYmd4!)eqnGePrO!c$4TH;7%hRVa9&Y6rIA-gK3C@R%XhH zpT>p^Jdb6_9-GpG4{374hqrGGaqvi&`^HLUa*oDTlK8gd!OaWkudwLqmaxCATWS?D zL$2k{HhE-ba(%I$Y4?9SHvD&&%BEs-8DOg{q$s`-2=j(@a{+xei_f0wwsPtM^3T24%TV4hNDYeu}5fs%I*`PVNqtDH0)kNmG4+w zs%hw7YI-+Vqg8cwqz6r(yk)_&h17bVIODXs;M@trxV1_@1=sK^DD{{D40v&OTx)XU9mNqT|A~~64Gk2zYII7Q&{6GVot&9LP8)6mwQ*>$xKUa= zNz&79m}~L<^tg)CJSlCvz^Ygr;F!6ScFD}_T=>auT^H=4EuR&DkU)_BF+1MNfOXKZ zW*%?5+SszeY=sA|`$=|J?XCD2R@ns_(HCdL?)Aa^XZnl|JygfRbzD1+rV0bC&~3EU+J%5uPnh;jF-wR;c`c_e2@*mEkj;+f;hAEo zQ9qTV-vkIMxFYIO>p%Ud3_c#LO&%B+B&F#P+Hr6q3kVK$cN)Er*Zi^5uP6TD*Qn7- zb}lqsm2xYy0F*YfKW*0!Wiz{dpZ5p!;c=0}dqO zH13Ci4qaqnlQ`Lz_G=OohM^$=s!txdtO#MUb|m|IV60$DliqA~7ZqPxbxNGJ8$H}a zHiA*u7V6-R+8M26K+_%0bt$HiJ4>YI%d?ek!J7T@u>s{!ys3(xX-Z6Dx0|x3O%4pC z>_|mdM222P7es&Lhf(*D#JA38B4UJuQ*6GvSuG#jFPmGSXY!-+!u3b-+h9|=b1Us8 z=-<$Vh9DqaR6(K2k$vkBG58R@AsH7Jr{S*Sq6os?YQA076|tK|?~w!1Y8}Q;-Z*i- zb1N~8RAE}&2WKIXT^QLL*-hJBax@~LWRo#IEBDww>1@v|u?ww0KntxGUUd5< zg;JUrtBAMy=c!W8kGz)qQ-Z8BcfQz9le-)yct-YUPUkCgTz9V=BRu|CFJ8fGW=&{Pqy?gN$Ce}RUzS= zpwPY8O?$lz9RVBo_of$xc)c&(^5B=ELQX%%9L!dK5_TKl;1Qt`!@rMcQQh?3u3xlT zI~o6Dz}pvTYib=*1o9gL*%~bGoI)=s7-~lddu{^ zhHrBqv5SbCP@qRsgzMelVMUgKi4q{!ux0WS&*)E%Nao41(&WY^L+xF_m^xO-UzC_*l7y6#42#KG|spaYk zVueCo5l9shEvX)f{Xz%R?CT#`Fe!Qtra^r>P#utZecm%zVP-h&<>D@y)*_OUzt-}C zb^K29$#sa zIQ9b%y%AKAt40T~Y|HxR4hPMf>_lOF(c9A)9!00SS6qUUZ<*ONDC=!6Ok!N=b9Px@ z($P%nQ%6Hqe3l^6%M-)}9G@4BacG6_VMI|8)2!&*P>(O{IY{9;=y%MubO<0+mUBRzzBtJ+{ zHACG3HMgu5ugRh^g_XK_1Kxwvua3q(OM$Rz(RAfH4@xQByfWuB5cZG#yV_vL(}jU zrMy`3CVry5pGjX(yk7GNdjgPQNf)pW0_y7Ko)fK0U{YGUesfm=AHU7*&>nQdMsvFK zz9_daM%>CBCcpTlKs~ZX$J|Og!4CN?wer)Q)#C34vq);~*C-@mjjFbJquaKfO^?ny zcol_TR=?5vM%Zb%rd4YmGf)Zsjz)kW4snJjraTBJiBp}E++3XYAZ+s>IRAxhPnB!k zC6dkeahhA64aR}WWHhZy&@zke>yU854*Cvpz)B%+Td}+jsY07pkPp>Kgwxu*_7b!% zcWzvdLxTx6|8!6i5~{d?gK@;`a^|iQQ!YeZ;%PqlC(ro>57Ch_@<%ZE3|{3p^fUO5 zaD~BiDkK~F$q#;sqIQ;|#e!w~JHm(yyeKIS@jKt3FOD|=W-twu+ zvK)Y)w_!vZY$w^fo_}xn=1iw&zCRFR*UEYK((`uBXQEo}d3F_;Qi(OycYi5We&_H) zlB{JZ1syGaK)`CLnS@CxjetBQr0^O%*g5007ogvs;%je2^EyNYA)(WOsHgD?77J)F z^YU$N-Q`U;e~Y39bvk?3qcQ{{RhPJr^1>;PctY7cZVWU}=Q&#VA?j()KqmhX#>P81) z^hepDnc8_$Gc(f5NAQF&_$jxUdMbV-2%~h2#duJkwU-EvEj?7>3b6NB9*XGU zG(P3-y67&)l#AtX{pLc(uTAUZ`?^J zeYWuoQZWzjzwg~XFf!DgO6%?Cdm-j0ULUH5P>y9-bW`;yO%unKv}w#hZBpScw+p$f z^OvHFdMtNmq3M(f{JWmFDsr(b%~wSa$;cj^8ctlA_u-swPvrW6uyQ{bY;}>X^6AdR zQ|=A~X-&s94PT3%IVB({d^3IYf@Op8dv7Ie{N7ZMQLGRXu9%=r?$`8)gUCG=9gruaKlIHX|KOELiwOj8x`!D}!A|rT;0YiNp9o^%!B&2?QH*Lvp z-3zZGW~m#g24`n|EKeVMrDRzLR1QCeY<)J);GW7!l8UbGr?-tK`FHAfVxb|Qn~PKn z)<-VP=tPPhujY&vy;Ue!I{z8NUc&Ui4(1dBtkAuit&R`(&@;#QEoJ#;{7QqU>u(NO8E*!Mwp5)6v@hlQVpd zMx|sl>fx8=%+(PK=;!6}^&%?jCu4vq3tQn|2L=9GE~MSJdyRmi!z51Tax)jXenyrd zVJy{%A{(UI3ju=Jk!US7dgr6($sD*@`H?hC>D7R75Rq}0S*91G5D%fskM{uT0}`{O zJ=y;zc#)x%>^H!Ph=ssyCjd{*I$qcbrAxqCzE~o6RkI2*I-a!(yc(;DE8zS)C+B*3 zh3qb>*#Z>?Z=k`tYVI+NY4RW7Lxn>r)UUVCDBnD+HW(A}@XU)oXxWig?)mR$9P4d2 zh}(+9G^AlvkaVOyRw9CZ4!1 z6*|?E?1WB~^$EsJRRf+*Z#oCszWM#v{MdXlKk~=8l$7sFE_y0{y%pjz9iHydrJHXt z$uD@k=K~!P@RN5a9BHk?>o3Tr_Er}lg|#hxSdpBn{r-jp9jCP1*l<^@dWR7*#%SAK z-Q(d?oUVmSr|wL0UK=6}L_499Iy>?qgvVNombO)hru(SzX+A;jKR)PJ5H4lq-B=kW zpKP;xlSFurMX`g&by2tF`!9q7E~;@VyY_WD56eZ^#vyGkPNgldaGPwEW72fGZN`bK zqF6uPp~Us$e%g}LsQ_>(=;dO^E1~p3%Zs$x`2_oyF8KS-RnKGaXhfsjkUCf;BT;~A zcyrWUZ`I`H=KAFqC6HKNKo2aSb9hu@LErc8eoUncJ?mmK4UQo$7+amwT<)ul?vTn~ zb-SaJd7k0rDzNOjCWm6BPz8&wk?)}}>2`)~Lr^soY%t<|dXJ3g3%Pd$$u(jE51*PT zXSq!>n$K0|{aao|l_!qoOIZFG=hCJce9lMW3_R_s>Qz@2KJeRL>LF1PuWMv*Tid_6 z|5d;`^!OseXN}Y`x4HX5CrXT+SSFL2FyhJLZtW~=I;{5X594lGNGY03s z6UT3h&%ZSZ2@|U18UFh$GFp$n4^&MFZKLF)zBx6QNN*KNbOo(w7z`(I?n^V#|BZdw z6S6ESlxsFqQi+7Cq$$afP>3_};}6YP{g@YT$aaIFheU^-Z?~cf$hPQ?udsqq%#r?; zQa(yj_8XEILQ{|}hWAcpZ05sa#+14s9c5(g+faa>lg|G-kh@(NBuPm8qq+W8y}r=1 zel@Nqx}^$fE@keITvN%FX2gBXMXvZ(&>f9>zCjY!M_qFIQfr)?{<0ET`C3Mqs>nyba)>*(rFU+KAj`v-9k_S2q5pIWM5#7o|2_#a9xi_L`BifZObgW7WKj-^o*ar-VCOz2*`@A^5=xgz%42u?#%6i)b!OJZNF`Frd%`T&y21`(U2< zAf8sU<$_`;v6Q^s14*}dvEiy!%9nkh5hz}NAmwSr^U89$=YZ3><$=SdPjo-j6BocQ z(hSLtj3rKwT?XBSyys5>QHik_3@}`o%D>I*Y758{pQ)xEFAn2&pp zy^vX6Ev)1Jh2G#xfRaG04H^s(_j>-G$GX+78j_+=lc=K)Dly5PJlhMd;przK^>9g5pAIv(V;6X=0rT71(bL#eI7 zM{N%b8RPz4Q%<&VuYUOv6Nd|YeRuKG9M~B3^+m{Tr4N%3zFaH;c#}7mh5{EnMJ^yh zsB#bw9^bt{9=Q#t-k}5DnnC0a6)&%w5;+k?WL1_cZz9~*NYaEnlw5_?e}Ynd_@rVL zFvikj>7bBh(szH*P2)oY^cAvssNJ`FMzTxcc@E+d(Mr_+fK2h{{WmV+{7b2~Hh+x08n63`L{9w7I9dq0ybXGNf>azTswuIC( zV$Efdtre|w)FUmt@?w?nli)*UDcayWT@0GRX>C|GvQx-qL+4MdR#9srLm&Bp) zF^rZrP}p`qT5~xy5D;b>PVfG31*h0q&qSI3%Ax^;GXWWOsGS4(UpCS-Q5Tw*MHT|y zyExN`s=S`}juTuppa$mNK0|p2WR@I+{rquIB`~47EZg|dX0aeh{P$Bu z1mF`==7EM&+uz!n)a&u<1zHL_#6#xW&wY8{!(uYMI4Ad?Pc&(t%S3h6m+3r{qhG-S zlX_wq9*ed>0}rVeVBtrkYi-KyMD0G!4NtWDsQJ&kjqn#ElM02P>8x@@C|M;zk;3rz zl0WA~OD24RY~`7x-B<&J2xi2&_H$x;s*M=g4svywYO1Ezv11FbGEBFcT4!?(hOx)M z*DMqJU-SKwhiEUsV-RLh`?78SN!8jc%?HE5?WB>8nP_*CUliMRH#Rmg0@Aa3tn7lu z$njO}jNRVXWsX2{udqDTC$+XqSf~R-_KUj`T#h%|8WGTn?rlR!j)Om2D29M^3)FA~ zWT7Y2WT7o;+6#r>T@Ww$b)e@89UEGe2lFsx5#O{lDsi4SQc`)+vN8sPC(5fnw91mf zd}SGuPRWVo{!&EfpJjRPG+T@DWb zr>T1$<3q^#I9AcadXqS=F&gprOjQ$gciYl4kDeM1{gg6wr?@^nJdkvyr~fMh5Hvaf ze|=|hRYo&Vh+;%!k-dpT>~dWVQZ zf!ac1oAP)*RP8qF4_d#(;=|0)Ex#c3)>Bd;^X^`~P1#)u z4$v`(Kv`6H!K=k-OG-oOP3DJlr)}bi+DG@}bei#*$eQB_G-v zkpdAHW!?xWM8kF*`z{zyoe1rGDYVryirZmc+&tHRuIJ@G;TZHR;00f2Sp%+2#;TVY zs8>8?j5spL?eP=FG6R9CK|s+0k|z9g`zElDZLCgD=+k1-ns@k0lNTl1?Yd+HY83dD*6`_o3=j}rJ9b6cs8sTk=oDo5>Svt>teuv&sN<}0TCwbZA5gh z2l7H>(+AEtoXwaCo03=fAspAI{<9TMC~4ab@;qkbQ%aIh7skl$#f$tbdw=79Rrh^q zkXqYRJn{VbMYpB5G7&e?D`|K)WOsw?r8Y*MytZN*rCMvjj3FTdsvvvf1yAlcq;1i- z5desE@2MN8&qR>hm=7_o#H{oaOhoLq*tNubNNu(q*n?|82>9;%=sM3cIUFh^6Pj`Q zJXNzT%VM68)~E$x{Cw|}gNe6$yydX#>SW8y$`1%@pJCG--%`zvU&?^}p4i%b<;PW= z)R@G)D86Bu30wSCK?ZfTGXAb-^$Zvm$svK?c}?|tPI!TR#{ zA&skDz*q3mh4kJ_@PaYUzDT#MkEcB1j$;QQ9KlyljQYz({i^A}5___Z-wKo6#!f9o zBkR0l@{8}ZzKHr1dPqnj>Nj1$0%XvlR`~D!V%=E52_+-b`XFE8n=w6P2Ek zT=G{iCC}acG(hblp{{;!gn%%H>F-~*fx%I*V(Md}kTUt;dNJEzXFguV|NSiY-lmUD zZLKt?IXc%nxwa4B{e6EZ&;t6V`j;OBa~Q5m{k!<(|NVDW|F(crfE;Y{D`rYg;Peuz zvpi6Zh*x_BeFwzw$E4e2S6pOE>M>A6o%|oWNA&1BW; zg6$(7Nnq?bt|KU;BvXBHlaW{ecvR)B8VqoC2Dqn=R9}y*7L#ANL$4>SElo?5w%*;l zYGnIG(sqv!_f_`;e37rz!p@lHK_MZ7>y~sBl+-W(4^v+q7F8GZi-8~r2BoBQgGdjJ zgn*QE4N`)1$B>GEw19LYIW*ESNXO7M)POWIbmzc5yx;xqbI&t_e+Xyqy?XuD+IzDQ zRr(Bui){kb$uRi}hK22h@2VeUq(jh*=az*c0oNCsCT^+!F1M~|85z5b0lGX70NRDb z(`hKE82|fY_8sZQtPeka{J2j61W8)CWGz-)mksZ3sZTf5Jh0x#cD>^b{(T$pwPMEh zehM8OosMP=9m0kC?IWDW{W2WJM~5d@cOjEOg=DLy?0Qb3n@R(=cbnRoh4?zbFZJBi zErHHa4aL@Z zZ;SAv#Z#Zz(H3SqFJU4drOF?0%&3K|lxHCPjbHo25<^x~I}jZm8`n^e^sz0!(T70< zK919*>wyRzfba%mL%QPmJCR!rn^+So{-syyZXnp1CG7GwJsrBP-7XNvY;U2(&pHf< zMh<;zj;gJN2QZ7iIKH6F|7F2$2D8}uZg71QWa#(Y#mW`)mlXH@jcs^Rv^}4E`%42F zF^FMgN61rrtFRwGu(DJC!5Nlle$k%Bzuc?A`Az>9;*ON(g%)r{(Wi>p+!7P%i<%5&+pGX>}m} z75S1KahVZazDNWtZWhqMJ;Om(ZcGXgmM^GW|EE3vtSl0BvJhR{7u7#Oo3o`NLutbF zg~GtE-$8Za>8&PkLi5iXxc%M0P3Db51xJI~Obp#UkNW``WT~i>BrA4}_B!YR4=P9; zoOK_hLZ$>i>YVEnwq3RPgzG1!CN&~#I1{>e?w#bSb zqON)gM3?URE^lc_lH#uD#Ik9*R)w8T_z|ypc{M)80l%tb>cgQgV7IFAq zEMtSA%8pE8IAY~nL1}4d-rJZTh564%ZLX2AB)W}|(g53L51@JSgWnZ>=8ECWsq@5R zLHu5T;f3y>zV6bHaE=-6M*G=b?YU@$7@6yY&C!X87O_U9E5FNxA^yB)rh~p#?`Z64 zIV8P7dP~0NP__8H@h{scE{H=DA^+FW|Bm0^u^Tr;)5F1F)yAeHcr(?^ngLr7++IL-3r~TW8t>wHlzWfyPof4?M2>{`lr_7yYssi$AG$cZ}S~+ zz(7dxoQ#N(f%N|x2k(V4^sdIRS7mC7^QR4QCGAUkaSP+vCb|}@B_VmohamT6yi@_Z z7tA|H=2;|wnj;9jDcdPicwfF}|zs`z{Zyms< zMs9aU@5*XGS=b=^CD1~3SCKoW6s7#L;fs@sMpb9_ea{g2D!0FWbVqC6;3VcR@O zOQEr;J6<3g`O{M#7nPOrv&?-ZueN?lbUwTM!pyGzh}ZkG+>fF!kT#V1!$@gaudJ~ zPq+;RN)1t=w-_t{cMY6mDtp7t2NXY#(F=N>hQRu71Z<}RPWV>^TxZaRJzTI_k*23l|^kZ{JMRoaT!uvsDtTEm@F6A zoMzV?MeUskZB;e&H|*Oe&`^HsW!l;A+i-E(p62lp_TYN*C@?D@K)5x4Ca#g&M(Xn! zRqvEN099x@qiF{KK5Q%?*r8=&d!g>u9uprI4s;sk8odvJUf%L50;M#$1^(&19l%*) zvk^L#8^Qo(>_hL$3zS2^fJY!oE12tAA#SI4v2>3;kX%_ zo$L`%dfb-qA@;YO3-v#v{@YNEAOA6py(&VmCpw6=bMveg;L?2(z~zQ6(6r3wG#}f9 z+!|iwqFp%-F4BLky5oj1u>Y_c!DAk>T&aR{_i(pf)75_gAnzBio=3eZSCvu2iUy_Z zuUZ*Smbqya04a**?@GyXa*LhlU9_-H7bG+Xv!BUMGp2dM-R9M}$WHa5eVO9#ujwas zPa7T#M^WH}bkNp&0WTbFl+|dySe}Neba3C*_jX}!pZ@2CD*&1!;czN{mMh=lstOrJ z%zP=J3CY*8RWLs5pJzu}Maj4xu^*u3y*B6b*h89$p2wSfDlg_)hlvz}2(p1NDGdFOF)H0m^?O_^FMIG!#@45SpM=73-?mJVe!rRvp>$(ru z;MjtyGQ>g|lsr!!lx?X`e!(3r1i#2{y}a)VDicA#!L(t6AYTVa0vN-m9KW|IjjIqf4*I^B8Ms|P1syj*nTK5d_Zp_nJFDwo z{1L~z7)+`Ao5F8%{R{88`k*->{}NDRXm3|tcvly-0|ilGNdny)NjGRupQBO#(Rx2; ztpXr=Cf*0ksIk^*ZsMl8M3vVhKB3J5TpUK@(a$!>SQ9n!?)o@Uy{t0BRpXKnvB9SKuUke8~rbl+cFEFReg^z;A41*Y#4&KjhPoOHT_8 z9l7uQt)#MPRj?lC7wa|8cr3}ygnXg6vBSpAD#UTW&1A=k>*R?&mFUA#{o234R3lZ= zK^L@lQ)LH=u)Fn@GySgcZUZO*cgo7s0rnVZ ziRvIp1a`fZQ9Y-i(hA)JlHVWw?e|*_iMcDpyjna>wxI91eKSO4WrY<_`ZK2+O!TDT z><*6~M_)dSB{on=3u7x*tu{?0Vg+Bwot=+<#<~Lt-iAq~ezpd&jQo_8;RoXOj`n&nazHTnd+xV< zeg-H@p<^MA%HBd1XRSgiEl@StQ>dEnuH%ERaxLa;Fet>fo5npOHzE@`rFmB{Wc23K zU#w>FHGV$(`RV8)pv}T3mVtJH_?wyrE`Y^D(XMw<-~IachHEZ$(55DYuMrYCd9%p~ zQxUFkSzH<{epEIKZRM*y%BR+92e<#owexiUF^U? z7~}c%R~g`qIM45hUM5uNol>TvNcLnh^n<`+sW*wac<&GV~Hsy zRvL3YbfWY}Lv^vF2)%gY%PuR*HF59nC%i!6qF2k@Ti^IoZ@b-EuCm-x1Ha2#&rDrmU*OCx8&XAqn@_#sjXZDr)Wk1_|3&2~8=X(`;+y8MTC7tKP z_yp3=U!KgXImz&5^u>pm$~Op`uitBtPOlm9xj*=k^!1&L)EIaSWQb9045c4=4E;wS z8L-(`Fy_a$!r3u@wD*)MkjzcSaJGVt`&v+cyQGohU^nFilJ9a|9cgLCB{YhIZRdUE zv<+Y}*WED^Udti#O29k-&*UTgHk{ zf(|G)Z2{vm0Otb!-r!8y_b>kq#$47nyHSYpyK|6ogCmZQU2i}C&kI+Bf%xrp9bUMd zN01fJNOaOjCQ(-czGz3}Ioo%cDKg*Qn2`ibo`@J;6%IYSrqR5?&a7JS{vx}`t)TrW zEbKwf^0R~qVzMgU{k5k`Z}w96e#W>H0(b6gBAdtnXf%>q3pFS7u3vYM`-bp_p&13m|MOe^~fZ`fwz zz}Ge&SuW!t>Zp@ zN_GMMPYMf30WlP*XCL!L>2Yr>bAzA3dpt_6hKOI)anv5H#hIu3S;-QSb{3e5-L}4X zlK$KYTEo~fE{{hH(M>2I#sIP>gUVA z#6-u+`q;_INsU-`!W&3b01JWzSdjI7OCWK~X>q--f{f!U2yYC3rV{r*P0pP%N_Z*V zp7GPX;dg3Md|#qziwq^eJKV>Cvc^1aaj3F%OiqZwM9K{+j%u;}*o9 z62)()Z+}jc8L+x)&SyJ~6-h3@!S;`ch$tp03Ap#_Us%h#|MUeqs+)xa8w+YE4x02y zP9!u07S1D&>0G4Hd2r5Oq>S);WVT5k%TafhO%T(}ITg$7wfkM$Vz?u~2kro1ON zvC3CNlUvzwntx3~22(=jOE|E|bIi=t1+%%(i1H9Q0*Zu}DwzODrl)lYivV;BNS>qs ziqtNPty_p0YdZjOAR?T`xO(>LpmpjN_mjzuv@@+4gM$5%#eDxin>KJt!G=^MjA~c;a>*Gjr zewmI(1YvmRxw#Azr3PeDQc~hD+5h#)w}}VL zm0k$i_bCtX07jAOy12x|#bL+weV?8dVqjv-F$sKRHDCA~FsX{fhoAp!g=7E66b3?k z*ZZAA%G?oJ5HRE*^^qi~)@;WI>u9U4b)B~BnW$lG?rKXwm5$fV@SiG81lp-2S1OjKh*62`Qhl8CTq&37Pk&Zv1x4_yIA}pkq;6ZJPl_BS za8F|6Vt)P%0Qk_^+4-7@=@DRY(kN8#=5ZJ0KaiKz@!}pzZ9sLcG|tf=PQHwse!V`5`GdBqy8f_RLanh@&(ZrU8OzpMUc;u8JGKi9@_OezAM|^ z$gocC(KxWDzwOm*Io5!Z{hVC@7mIme2@B$48tk^Bz=+K(uLR13N+X9sEiX}%ht`*Gl!y<5q6a_o;zRDF0#6qpM6_UWGns^nW;Eo$eZFiPJhgLfyp@QhOTO6b zyY;W)M_br}BQq8v-sImw^<@cR%R%BQTc7i&whJ}?$C50G6#I^B7o4T}$|f19a*%C> z9%sesdi#>=Yd{^{&@yxY<$(jE8SyU1WX1kx)VmUghF<^dJ7g;L$(TV+0|d6u->`o( zuwW;0@0yC3{6^n!yf)A+_+JyFp8XbP4)^_Jw&21X?MdP`o7(8N1%1sCngEw8uD@SG z=&}n#7VQ7L=4QrGnGD_EcZ?314+#pY%mQFGQmIHIO&tYH4v;;=!)YtN!*}%0ClyojX_=XEUcGwtUR70IP7b(3XJFt%E}7_1 zf4`iZ+@q>Le*mQl1d5oeYisSXmQopvPYIi-9=&@;oKBdMFYN|(gsK#(F!Lz~a%ZPHC3E<`9<{O$C6TRC-lgPD?uj9*IRv~Y6|8+VLm$L?B(r@uA;f5E9=#IX6^d5+k;f9+zXwA;6 z+5B+YGvLBX;6uW?$tjdnMFVva)C_s>majMV(PMJHf(OtJ!Vn~36B4hu>;7a>yZPHT zVryyLq=rxSzEm=DQ&Q&U45s+n4IWynWPWyUUb5}i0$T}G#`(-GEt@!?_zoM~hLZaF zJQwP^dw2dR1C6TIp8eC#!};alJM4H{}M2;IWA_mf_~=%(gRAm__?zSUUnK9ES z79oZ6pSPbXS82s*?}kV>K*P9i1s=zG!!Tmpi3Ni%82 z{}4rig@x~BWaa3fnlUuMohCnjK6@G2onx?scog`xLn8FyI3IyPDuI`mmu%hqyrKE$ z&j~CgUEM zkg;2}o(}W%j~m^#!t9Nja?E<7tR|r(+_5iWhJg%4eC;H+Nu;bqqKeLY0)M3;wHUm< zRU{9HkyzCRJr-{cT2S>#q~c3WwGxj)N&8iQ{-P|zyy)pKc+jCD$UtnKW>vrKLZ;P5wlP|IW&4ld%g{ zjE|Lfhd$uUmD?ZNeg2v`1f+{USCZQ;0=ty_SbU00MFk&IKLLv#xl*Ch_@+ zxJQ@&$A(-}IcVKgntijfu1G~!i$uSSNZ*}Qlb15w4YIGpiVPy>WYsi{L zuqyg-TerD{IUh{7+vO3?m7J_k0Ip&MF2B#H_c zFCvY|>h&Ki0x5~=d-&?SMj%EI`|pmc%=Jmmp6SM{Y=>Vey(0` zs0({USws$qo<9f@Mtys7ARg7LLa?%R=>9mbJRAZ))<^fSbVp3 z;5wLwZnuB|;pf!$lWFI-*@fEXxj?%~98d$gq#%5audNP$l`X) zHjL`_{xtSKC9IDhe#6NhrEa+bp{GuN)mSil2SOi4Tr#;!=JSeeB|5g)h`e81D)u!i zC~H<_X(H=OuQ4n61-l$s8H2Br#TUcF6e4oUAY-!Td||%7gnyU6=L;*sw4ZU`Dh&?W zkm*!C!g~MWwZcy|04QXE7^-b51{GV!AEf27hux#%>SnJ`WRzrevR^W*_bZ!jxRW^F#D3{lg!X$c!fp)6BqVO%CUA6EMSUMllNb;iFzF~GDmp(K^fVC*hr`F;ur-JpSUUq2AJIFs~RaBe2U+!05Z`b)S z63F7(-Xvq9VGg6xrZ`U0Q{2t{j|wDi+(DXCF4)J-@YB8d<^unXbsPq8bfijJ{cJQwWT)Xl?#Z0s|ZRzN_MbFYs2FxkI9 z>Fwx(s$G7=V~nHm-U#s3h|TzzFyg=gujUf=b1KP)!J`-(?U-vPrcX`HN@Tl}1k65! zM|^qiA6LkcNBErbnPkJWr02mE(pL_uA;u%n6zo!K-D>HpN2jRM*6T3wiz3yn+&Gmn zew|k1J)aGc$%O^5YsWoJ!gj1{XmA+hGsU%G2iR5(5n)oU*gWs5e^uLDEjyNAxMi(h z-7Ka)H$ts6b*igkn`|K>)?GzPZsyjX^x15JBl(i!>d63hJaw#4fLfZOzwcKTbJ!ln zCyJ6knx}h0phih~2Wsq@=6<|4-YC)Zj;3YlQM&sqs__z|gQD8=3`t2%?fAkUP(_>d z`^75MZgoGgdQ>8K4(hODU1Ddy=l+7< z$em-E+QrWA52|Mvti=9OO7x(hOLY{S0xp-{`i-DLT-m=TL#R4Cu&AT)JR7yG}x0K;j5b1lvh zPp=M2>!g?c-A{ z$(gmrRqj;1qnB`jlTxFPHi>95s)EGYy~&W<^GCk>fe2LNmU!V-c`G=ajGM5o3yZER z(M2=Nwl$7Y+d|C6D0xYA@nj!N>$mQxyMpiKGtt;XNDvi4MLy5;#h}bifLnhdrqFoA zu7}8|mdF@#{_B$3ti=7*xJkaW4+p#!3rn&-3`Dh1MWwM=t7dIbco0L2ITCCw<@R55 zsBz!X_ucNMa2*of=&dSoG|33rjB%qT=dLQPuIh;Cr+rscPwgg>}9nSTdaQS+DlX=4K2C!Uw4^_CJU( zzf(}{jZA--eKR1NPTjBG2Ji9*C`wDpYhIsTW;oouDMp)=^6FTKzkhnz5FF1V4k!sC z>!IM?;wI51GI!~$HG%nXHk+S$5k?hdN(HN3${$BBHh9(LB4fe*bp#>_6W8d|My%4Wnb7_ zY)MBnYHh&a@3-$fHOh7$HB!4nLXPWjEXR)!4Wc8ipSFJna+HjqZb#o;#Q_XItukL}=G0SVH&y=U2&wj|r>pQJX1BclxV1`nQU+mR^Xk2}G;2X1uEX3qhii5K)!(^+=5qPj{ z#Byk3rffF9cGlcX=?{^rz^qD1TU9y;?w%59!T%Dj|B0h%ZGUfA@Rb?4#fLz1bOdoC z4}RzH%srOOMp0nVL}%MX=XqOSWlUfP z=IXLL_>mm%)T^#!duM=doxRzikE#08_%IjOVLdtW7-K6d;|Wc`#ea({F)|UUBmun1 zD>Kfw-LCyf-D(tIYAIEJK^4)W?w}qh%%v#9bJqg1Fyk=MPoz3gx@AA=wUI6#;wk32Ple0Zwqw}Jm zrVPcz$mlqw($rM<3x3W7BAW`zg0{Er>6JT7W_p9&x`W+SDS4=$<(D0_t#aKHVZ*MU z#QRCguGaFekjJA-ATb^uAszu|$NJVf2V1L8A8xL`9EgZ#N+%wrK0C^&ajWp?xe06$ zp-w#ZT=&6mOmqW0Ag9L*{+?mHy@Z;azwU{tnK^AGi<%DG`q1DZ#@R;yL@w{ecx!9h zk-OF9C4!+cbkFTZ>z|ut*u4KwT=w7A2}nzkRIWM9*kW9QWaa28pl8upbu72gR}6Rh8b!@9dEZ z<3)Y{arxB}=#TRb<6_&&z(sQ~hKtM9Gkq~?; zTL21OWlh+jbg=af;+Z-Ou;XTy&^keV>3;e9vNj0nU{DzI71M|suiFf!aG2<^Z&pVb z`?sW|q|n)Oy}5lh@^!`;!_>5hg|3Th@M)_X2_yl-*YU2UiVwOtdd}y^zYY1D`&gU$ z_yD%Zwg81A7V!EDbmKaud!3v)rlis=G}ofXnqw|Z&%I=5+I{RL`xg%OFA<@y%qHPU zMLh{Ml5gF*lR&RD=#%x$H0hJgqaNIk5_%nQnEZ>67D1KBx1_idE5f8>7Te9>0c_fR zuJF5Ti?H9V#}FaLAm}^dhIDG!E!@hNH$qUkjib~B)5(E>lML3u#1E_IPRT>Fp9ku zgIOGe1p&sfVCJAx;f{bDSDt1AbTm8Mbv{7>dX_JzIIOe=ziCI(fC^hL(CLksQwc=8 zj!{wcqHA0Nhu#Y(jjtDh0a4b^kNJ+W;KPRUy2cFOu2)ipTM>@y&Qc;#;mi0Re=dGM z69K;($3zXM?RxkKC*XVQXWN~n>^c6UQF^+wC`S9`%|FPsy+?wlo$r9cL?=-V!HGLZ zMs=F*SXFv150kxZfj#=u-{Zkfb3HdXCVP%QpP=L78ti6h1`U_<07+>%Co0sv+3AqE z_4jW-qi^cO-cclX9DRsR%`jg6C-rhH1#=M(^2tn?FZxn8#=EZ6)S7N-=-jhrt?Arj zq(iS!;MUXu{3v+Z@Wtbk^{l3@_AHeP^0+WnB|3k+NFAXZU0>7(PgK z(NEGBysojMyX-m_+Op}~5}SQFw}ihciLYQ^KiXA52%Wq73z?e~G9I1-JsaR~9!J*IqC zI^LPxeLH+xa2}MkW<9unZ%TrH3~(G7)sYqk?i{;7q*%Kml&~}XHo;=1)+~ajyNb$; z1FoB37Ex)zVS`@K?S6T+FJusF5n%!EecLS*n+z!_@?u;`Dhhm5NxzcUF>bDuqMvAP z_~m2SmNmK>Rc)9zkNUU8#@P_(yw>Q<%$T><$f{$nUzQqMTwUC8W)I@$7fW|82xew% zum_2;Hhd9GS5YY2${%M%xQzqBgzo7>GewWsF}oB)W5BI_ZgZtucOmLXHl^C@ z`=IqOQ}%5?L|g+*8kU7k@KLH&7rV5R>`$4G9s6;s3vK*`&-fA5o5xoHk~JTmx@1VN zpYZx;@BKC%=1A&NF3=$Q-QlOAELY!-cdBkgPvssY+@A$TpL}oe(aq!xdUTW=?GkjH zyb{5%13{rqVyBcYd%B0ZI3v@;hn<)E#yRJN$91Qiyv}l~ul;(Q7+=BN`6jdHP3`8J zl=l3FEv)VAr|vBIU81QQLBo3Q+v}_cd1Tdx;-w>jPyE;}y0ll0N_&PI|CBN#T-0q1 z!b&>_;!!5$1ur(9iv0U6ln1SSq{p<`_&Y@cs_4})MRa-y%_ciwjqn2!lu?$))oGG?gZ9&@}ENA8EJ zZv7UV&$_b?Wlg&veu1GN2_kGwT`jp-UJP+W9x8by z>ciGzjfKZ;8Rz0pSC6BdH6#I*n1jo5s7s_p=I-d}M||Q5BDYAz34Um;i_GHX?%7FA zxv%nFf*|g4Gzhv_jiYzqP>Tc<-&Q@-o~)ZJ-W0meyCyOzj;OUPqhA!bF5%ux#t)+Q zVUf=hpF6$YcF4vt{gx&iV|T-HWzt)NEKJ0=xv-wI*Hy&Sy_j+@UJH=ShQ}}eeb-VfVvB!4RWcJctfiOfwl!DzMSd|#`IZ4Sv@Q#8q5zS#c7!qx@h8;G_K3?2I;bTw z2#1o7*KZ0
    qN6Go1fU_|v2NAT?jS$5Rbcc~}5We(70$ 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 + + + + + + MeshChatX - Crash Report + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + +
    +
    +
    + MeshChatX Crashed +
    +
    Critical error detected in backend service.
    +
    +
    + +
    +
    +
    Exit Code
    +
    --
    +
    +
    +
    Status
    +
    Offline
    +
    +
    + +
    +
    +

    Diagnostic Logs

    + +
    + +
    +
    Standard Output (stdout)
    +
    +
    
    +                                
    +
    + +
    +
    Standard Error (stderr)
    +
    +
    
    +                                
    +
    +
    + +
    + + + +
    +
    +
    +
    +
    + + + + diff --git a/electron/loading.html b/electron/loading.html index 693df9b..0919259 100644 --- a/electron/loading.html +++ b/electron/loading.html @@ -1,6 +1,10 @@ + @@ -19,15 +23,15 @@ > -
    +
    -
    -
    +
    +
    -

    - MeshChatX -

    MeshChatX
    @@ -47,11 +48,11 @@
    - Preparing your node + Preparing your app
    -
    -
    +
    +
    @@ -79,7 +80,7 @@
    -
    +
    diff --git a/electron/main-legacy.js b/electron/main-legacy.js new file mode 100644 index 0000000..d69db25 --- /dev/null +++ b/electron/main-legacy.js @@ -0,0 +1,366 @@ +const { app, BrowserWindow, dialog, ipcMain, shell, systemPreferences } = require("electron"); +const electronPrompt = require("electron-prompt"); +const { spawn } = require("child_process"); +const fs = require("fs"); +const path = require("node:path"); + +// remember main window +var mainWindow = null; + +// remember child process for exe so we can kill it when app exits +var exeChildProcess = null; + +// allow fetching app version via ipc +ipcMain.handle("app-version", () => { + return app.getVersion(); +}); + +// allow fetching hardware acceleration status via ipc +ipcMain.handle("is-hardware-acceleration-enabled", () => { + // New in Electron 39, fallback for legacy + if (typeof app.isHardwareAccelerationEnabled === "function") { + return app.isHardwareAccelerationEnabled(); + } + return true; // Assume true for older versions +}); + +// allow fetching integrity status (Stub for legacy) +ipcMain.handle("get-integrity-status", () => { + return { + backend: { ok: true, issues: ["Not supported in legacy mode"] }, + data: { ok: true, issues: ["Not supported in legacy mode"] }, + }; +}); + +// ignore ssl errors +app.commandLine.appendSwitch("ignore-certificate-errors"); + +// add support for showing an alert window via ipc +ipcMain.handle("alert", async (event, message) => { + return await dialog.showMessageBox(mainWindow, { + message: message, + }); +}); + +// add support for showing a confirm window via ipc +ipcMain.handle("confirm", async (event, message) => { + // show confirm dialog + const result = await dialog.showMessageBox(mainWindow, { + type: "question", + title: "Confirm", + message: message, + cancelId: 0, // esc key should press cancel button + defaultId: 1, // enter key should press ok button + buttons: [ + "Cancel", // 0 + "OK", // 1 + ], + }); + + // check if user clicked OK + return result.response === 1; +}); + +// add support for showing a prompt window via ipc +ipcMain.handle("prompt", async (event, message) => { + return await electronPrompt({ + title: message, + label: "", + value: "", + type: "input", + inputAttrs: { + type: "text", + }, + }); +}); + +// allow relaunching app via ipc +ipcMain.handle("relaunch", () => { + app.relaunch(); + app.exit(); +}); + +// allow showing a file path in os file manager +ipcMain.handle("showPathInFolder", (event, path) => { + shell.showItemInFolder(path); +}); + +function log(message) { + // log to stdout of this process + console.log(message); + + // make sure main window exists + if (!mainWindow) { + return; + } + + // make sure window is not destroyed + if (mainWindow.isDestroyed()) { + return; + } + + // log to web console + mainWindow.webContents.send("log", message); +} + +function getDefaultStorageDir() { + // if we are running a windows portable exe, we want to use .reticulum-meshchat in the portable exe dir + // e.g if we launch "E:\Some\Path\MeshChat.exe" we want to use "E:\Some\Path\.reticulum-meshchat" + const portableExecutableDir = process.env.PORTABLE_EXECUTABLE_DIR; + if (process.platform === "win32" && portableExecutableDir != null) { + return path.join(portableExecutableDir, ".reticulum-meshchat"); + } + + // otherwise, we will fall back to putting the storage dir in the users home directory + // e.g: ~/.reticulum-meshchat + return path.join(app.getPath("home"), ".reticulum-meshchat"); +} + +function getDefaultReticulumConfigDir() { + // if we are running a windows portable exe, we want to use .reticulum in the portable exe dir + // e.g if we launch "E:\Some\Path\MeshChat.exe" we want to use "E:\Some\Path\.reticulum" + const portableExecutableDir = process.env.PORTABLE_EXECUTABLE_DIR; + if (process.platform === "win32" && portableExecutableDir != null) { + return path.join(portableExecutableDir, ".reticulum"); + } + + // otherwise, we will fall back to using the .reticulum folder in the users home directory + // e.g: ~/.reticulum + return path.join(app.getPath("home"), ".reticulum"); +} + +app.whenReady().then(async () => { + // get arguments passed to application, and remove the provided application path + const ignoredArguments = ["--no-sandbox", "--ozone-platform-hint=auto"]; + const userProvidedArguments = process.argv.slice(1).filter((arg) => !ignoredArguments.includes(arg)); + const shouldLaunchHeadless = userProvidedArguments.includes("--headless"); + + if (!shouldLaunchHeadless) { + // create browser window + mainWindow = new BrowserWindow({ + width: 1500, + height: 800, + webPreferences: { + // used to inject logging over ipc + preload: path.join(__dirname, "preload.js"), + // Security: disable node integration in renderer + nodeIntegration: false, + // Security: enable context isolation (default in Electron 12+) + contextIsolation: true, + // Security: enable sandbox for additional protection + sandbox: true, + // Security: disable remote module (deprecated but explicit) + enableRemoteModule: false, + }, + }); + + // open external links in default web browser instead of electron + mainWindow.webContents.setWindowOpenHandler(({ url }) => { + var shouldShowInNewElectronWindow = false; + + // we want to open call.html in a new electron window + // but all other target="_blank" links should open in the system web browser + // we don't want /rnode-flasher/index.html to open in electron, otherwise user can't select usb devices... + if ( + (url.startsWith("http://localhost") || url.startsWith("https://localhost")) && + url.includes("/call.html") + ) { + shouldShowInNewElectronWindow = true; + } + + // we want to open blob urls in a new electron window + else if (url.startsWith("blob:")) { + shouldShowInNewElectronWindow = true; + } + + // open in new electron window + if (shouldShowInNewElectronWindow) { + return { + action: "allow", + }; + } + + // fallback to opening any other url in external browser + shell.openExternal(url); + return { + action: "deny", + }; + }); + + // navigate to loading page + await mainWindow.loadFile(path.join(__dirname, "loading.html")); + + // ask mac users for microphone access for audio calls to work + if (process.platform === "darwin") { + await systemPreferences.askForMediaAccess("microphone"); + } + } + + // find path to python/cxfreeze reticulum meshchat executable + // Note: setup.py creates ReticulumMeshChatX (with X), not ReticulumMeshChat + const exeName = process.platform === "win32" ? "ReticulumMeshChatX.exe" : "ReticulumMeshChatX"; + + // get app path (handles both development and packaged app) + const appPath = app.getAppPath(); + // get resources path (where extraFiles are placed) + const resourcesPath = process.resourcesPath || path.join(appPath, "..", ".."); + var exe = null; + + // when packaged, extraFiles are placed at resources/app/electron/build/exe + // when packaged with asar, unpacked files are in app.asar.unpacked/ directory + // app.getAppPath() returns the path to app.asar, so unpacked is at the same level + const possiblePaths = [ + // packaged app - extraFiles location (resources/app/electron/build/exe) + path.join(resourcesPath, "app", "electron", "build", "exe", exeName), + // packaged app with asar (unpacked files from asarUnpack) + path.join(appPath, "..", "app.asar.unpacked", "build", "exe", exeName), + // packaged app without asar (relative to app path) + path.join(appPath, "build", "exe", exeName), + // development mode (relative to electron directory) + path.join(__dirname, "build", "exe", exeName), + // development mode (relative to project root) + path.join(__dirname, "..", "build", "exe", exeName), + ]; + + // find the first path that exists + for (const possibleExe of possiblePaths) { + if (fs.existsSync(possibleExe)) { + exe = possibleExe; + break; + } + } + + // verify executable exists + if (!exe || !fs.existsSync(exe)) { + const errorMsg = `Could not find executable: ${exeName}\nChecked paths:\n${possiblePaths.join("\n")}\n\nApp path: ${appPath}\nResources path: ${resourcesPath}`; + log(errorMsg); + if (mainWindow) { + await dialog.showMessageBox(mainWindow, { + message: errorMsg, + }); + } + app.quit(); + return; + } + + log(`Found executable at: ${exe}`); + + try { + // arguments we always want to pass in + const requiredArguments = [ + "--headless", // reticulum meshchat usually launches default web browser, we don't want this when using electron + "--port", + "9337", // FIXME: let system pick a random unused port? + // '--test-exception-message', 'Test Exception Message', // uncomment to test the crash dialog + ]; + + // if user didn't provide reticulum config dir, we should provide it + if (!userProvidedArguments.includes("--reticulum-config-dir")) { + requiredArguments.push("--reticulum-config-dir", getDefaultReticulumConfigDir()); + } + + // if user didn't provide storage dir, we should provide it + if (!userProvidedArguments.includes("--storage-dir")) { + requiredArguments.push("--storage-dir", getDefaultStorageDir()); + } + + // spawn executable + exeChildProcess = await spawn(exe, [ + ...requiredArguments, // always provide required arguments + ...userProvidedArguments, // also include any user provided arguments + ]); + + // log stdout + var stdoutLines = []; + exeChildProcess.stdout.setEncoding("utf8"); + exeChildProcess.stdout.on("data", function (data) { + // log + log(data.toString()); + + // keep track of last 10 stdout lines + stdoutLines.push(data.toString()); + if (stdoutLines.length > 10) { + stdoutLines.shift(); + } + }); + + // log stderr + var stderrLines = []; + exeChildProcess.stderr.setEncoding("utf8"); + exeChildProcess.stderr.on("data", function (data) { + // log + log(data.toString()); + + // keep track of last 10 stderr lines + stderrLines.push(data.toString()); + if (stderrLines.length > 10) { + stderrLines.shift(); + } + }); + + // log errors + exeChildProcess.on("error", function (error) { + log(error); + }); + + // quit electron app if exe dies + exeChildProcess.on("exit", async function (code) { + // if no exit code provided, we wanted exit to happen, so do nothing + if (code == null) { + return; + } + + // tell user that Visual C++ redistributable needs to be installed on Windows + if (code === 3221225781 && process.platform === "win32") { + await dialog.showMessageBox(mainWindow, { + message: "Microsoft Visual C++ redistributable must be installed to run this application.", + }); + app.quit(); + return; + } + + // show crash log + const stdout = stdoutLines.join(""); + const stderr = stderrLines.join(""); + await dialog.showMessageBox(mainWindow, { + message: [ + "MeshChat Crashed!", + "", + `Exit Code: ${code}`, + "", + `----- stdout -----`, + "", + stdout, + `----- stderr -----`, + "", + stderr, + ].join("\n"), + }); + + // quit after dismissing error dialog + app.quit(); + }); + } catch (e) { + log(e); + } +}); + +function quit() { + // kill python process + if (exeChildProcess) { + exeChildProcess.kill("SIGKILL"); + } + + // quit electron app + app.quit(); +} + +// quit electron if all windows are closed +app.on("window-all-closed", () => { + quit(); +}); + +// make sure child process is killed if app is quiting +app.on("quit", () => { + quit(); +}); diff --git a/electron/main.js b/electron/main.js index b83619a..f2f03ab 100644 --- a/electron/main.js +++ b/electron/main.js @@ -1,20 +1,188 @@ -const { app, BrowserWindow, dialog, ipcMain, shell, systemPreferences } = require("electron"); +const { + app, + BrowserWindow, + dialog, + ipcMain, + shell, + systemPreferences, + Tray, + Menu, + Notification, + powerSaveBlocker, + session, +} = require("electron"); const electronPrompt = require("electron-prompt"); const { spawn } = require("child_process"); const fs = require("fs"); const path = require("node:path"); +const crypto = require("crypto"); + // remember main window var mainWindow = null; +// tray instance +var tray = null; + +// power save blocker id +var activePowerSaveBlockerId = null; + +// track if we are actually quiting +var isQuiting = false; + // remember child process for exe so we can kill it when app exits var exeChildProcess = null; +// store integrity status +var integrityStatus = { + backend: { ok: true, issues: [] }, + data: { ok: true, issues: [] }, +}; + +// Check for hardware acceleration preference in storage dir +try { + const storageDir = getDefaultStorageDir(); + const disableGpuFile = path.join(storageDir, "disable-gpu"); + if (fs.existsSync(disableGpuFile)) { + app.disableHardwareAcceleration(); + console.log("Hardware acceleration disabled via storage flag."); + } +} catch { + // ignore errors reading storage dir this early +} + +// Handle hardware acceleration disabling via CLI +if (process.argv.includes("--disable-gpu") || process.argv.includes("--disable-software-rasterizer")) { + app.disableHardwareAcceleration(); +} + +// Protocol registration +if (process.defaultApp) { + if (process.argv.length >= 2) { + app.setAsDefaultProtocolClient("lxmf", process.execPath, [path.resolve(process.argv[1])]); + app.setAsDefaultProtocolClient("rns", process.execPath, [path.resolve(process.argv[1])]); + } +} else { + app.setAsDefaultProtocolClient("lxmf"); + app.setAsDefaultProtocolClient("rns"); +} + +// Single instance lock +const gotTheLock = app.requestSingleInstanceLock(); +if (!gotTheLock) { + app.quit(); +} else { + app.on("second-instance", (event, commandLine) => { + // Someone tried to run a second instance, we should focus our window. + if (mainWindow) { + if (mainWindow.isMinimized()) mainWindow.restore(); + mainWindow.show(); + mainWindow.focus(); + + // Handle protocol links from second instance + const url = commandLine.pop(); + if (url && (url.startsWith("lxmf://") || url.startsWith("rns://"))) { + mainWindow.webContents.send("open-protocol-link", url); + } + } + }); +} + +// Handle protocol links on macOS +app.on("open-url", (event, url) => { + event.preventDefault(); + if (mainWindow) { + mainWindow.show(); + mainWindow.webContents.send("open-protocol-link", url); + } +}); + +function verifyBackendIntegrity(exeDir) { + const manifestPath = path.join(__dirname, "backend-manifest.json"); + if (!fs.existsSync(manifestPath)) { + log("Backend integrity manifest missing, skipping check."); + return { ok: true, issues: ["Manifest missing"] }; + } + + try { + const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8")); + const issues = []; + + // The exeDir is build/exe when running or unpacked + // we only care about files in the manifest + for (const [relPath, expectedHash] of Object.entries(manifest)) { + const fullPath = path.join(exeDir, relPath); + if (!fs.existsSync(fullPath)) { + issues.push(`Missing: ${relPath}`); + continue; + } + + const fileBuffer = fs.readFileSync(fullPath); + const actualHash = crypto.createHash("sha256").update(fileBuffer).digest("hex"); + if (actualHash !== expectedHash) { + issues.push(`Modified: ${relPath}`); + } + } + + return { + ok: issues.length === 0, + issues: issues, + }; + } catch (error) { + log(`Backend integrity check failed: ${error.message}`); + return { ok: false, issues: [error.message] }; + } +} + // allow fetching app version via ipc ipcMain.handle("app-version", () => { return app.getVersion(); }); +// allow fetching hardware acceleration status via ipc +ipcMain.handle("is-hardware-acceleration-enabled", () => { + return app.isHardwareAccelerationEnabled(); +}); + +// allow fetching integrity status +ipcMain.handle("get-integrity-status", () => { + return integrityStatus; +}); + +// Native Notification IPC +ipcMain.handle("show-notification", (event, { title, body, silent }) => { + const notification = new Notification({ + title: title, + body: body, + silent: silent, + }); + notification.show(); + + notification.on("click", () => { + if (mainWindow) { + mainWindow.show(); + mainWindow.focus(); + } + }); +}); + +// Power Management IPC +ipcMain.handle("set-power-save-blocker", (event, enabled) => { + if (enabled) { + if (activePowerSaveBlockerId === null) { + activePowerSaveBlockerId = powerSaveBlocker.start("prevent-app-suspension"); + log("Power save blocker started."); + } + } else { + if (activePowerSaveBlockerId !== null) { + powerSaveBlocker.stop(activePowerSaveBlockerId); + activePowerSaveBlockerId = null; + log("Power save blocker stopped."); + } + } + return activePowerSaveBlockerId !== null; +}); + // ignore ssl errors app.commandLine.appendSwitch("ignore-certificate-errors"); @@ -63,6 +231,19 @@ ipcMain.handle("relaunch", () => { app.exit(); }); +ipcMain.handle("relaunch-emergency", () => { + app.relaunch({ args: process.argv.slice(1).concat(["--emergency"]) }); + app.exit(); +}); + +ipcMain.handle("shutdown", () => { + quit(); +}); + +ipcMain.handle("get-memory-usage", async () => { + return process.getProcessMemoryInfo(); +}); + // allow showing a file path in os file manager ipcMain.handle("showPathInFolder", (event, path) => { shell.showItemInFolder(path); @@ -112,7 +293,79 @@ function getDefaultReticulumConfigDir() { return path.join(app.getPath("home"), ".reticulum"); } +function createTray() { + const iconPath = path.join(__dirname, "build", "icon.png"); + const fallbackIconPath = path.join(__dirname, "assets", "images", "logo.png"); + const trayIcon = fs.existsSync(iconPath) ? iconPath : fallbackIconPath; + + tray = new Tray(trayIcon); + const contextMenu = Menu.buildFromTemplate([ + { + label: "Show App", + click: function () { + if (mainWindow) { + mainWindow.show(); + } + }, + }, + { + label: "Quit", + click: function () { + isQuiting = true; + quit(); + }, + }, + ]); + + tray.setToolTip("Reticulum MeshChatX"); + tray.setContextMenu(contextMenu); + + tray.on("click", () => { + if (mainWindow) { + if (mainWindow.isVisible()) { + mainWindow.hide(); + } else { + mainWindow.show(); + } + } + }); +} + app.whenReady().then(async () => { + // Security: Enforce CSP for all requests as a shell-level fallback + session.defaultSession.webRequest.onHeadersReceived((details, callback) => { + const responseHeaders = { ...details.responseHeaders }; + + // Define a robust fallback CSP that matches our backend's policy + const fallbackCsp = [ + "default-src 'self'", + "script-src 'self' 'unsafe-inline' 'unsafe-eval'", + "style-src 'self' 'unsafe-inline'", + "img-src 'self' data: blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org", + "font-src 'self' data:", + "connect-src 'self' http://localhost:9337 https://localhost:9337 ws://localhost:* wss://localhost:* blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://nominatim.openstreetmap.org", + "media-src 'self' blob:", + "worker-src 'self' blob:", + "frame-src 'self'", + "object-src 'none'", + "base-uri 'self'", + ].join("; "); + + // If the response doesn't already have a CSP, apply our fallback + if (!responseHeaders["Content-Security-Policy"] && !responseHeaders["content-security-policy"]) { + responseHeaders["Content-Security-Policy"] = [fallbackCsp]; + } + + callback({ responseHeaders }); + }); + + // Log Hardware Acceleration status (New in Electron 39) + const isHardwareAccelerationEnabled = app.isHardwareAccelerationEnabled(); + log(`Hardware Acceleration Enabled: ${isHardwareAccelerationEnabled}`); + + // Create system tray + createTray(); + // get arguments passed to application, and remove the provided application path const ignoredArguments = ["--no-sandbox", "--ozone-platform-hint=auto"]; const userProvidedArguments = process.argv.slice(1).filter((arg) => !ignoredArguments.includes(arg)); @@ -137,6 +390,15 @@ app.whenReady().then(async () => { }, }); + // minimize to tray behavior + mainWindow.on("close", (event) => { + if (!isQuiting) { + event.preventDefault(); + mainWindow.hide(); + return false; + } + }); + // open external links in default web browser instead of electron mainWindow.webContents.setWindowOpenHandler(({ url }) => { var shouldShowInNewElectronWindow = false; @@ -160,6 +422,16 @@ app.whenReady().then(async () => { if (shouldShowInNewElectronWindow) { return { action: "allow", + overrideBrowserWindowOptions: { + autoHideMenuBar: true, + webPreferences: { + preload: path.join(__dirname, "preload.js"), + nodeIntegration: false, + contextIsolation: true, + sandbox: true, + enableRemoteModule: false, + }, + }, }; } @@ -228,6 +500,13 @@ app.whenReady().then(async () => { log(`Found executable at: ${exe}`); + // Verify backend integrity before spawning + const exeDir = path.dirname(exe); + integrityStatus.backend = verifyBackendIntegrity(exeDir); + if (!integrityStatus.backend.ok) { + log(`INTEGRITY WARNING: Backend tampering detected! Issues: ${integrityStatus.backend.issues.join(", ")}`); + } + try { // arguments we always want to pass in const requiredArguments = [ @@ -260,9 +539,9 @@ app.whenReady().then(async () => { // log log(data.toString()); - // keep track of last 10 stdout lines + // keep track of last 100 stdout lines stdoutLines.push(data.toString()); - if (stdoutLines.length > 10) { + if (stdoutLines.length > 100) { stdoutLines.shift(); } }); @@ -274,9 +553,9 @@ app.whenReady().then(async () => { // log log(data.toString()); - // keep track of last 10 stderr lines + // keep track of last 100 stderr lines stderrLines.push(data.toString()); - if (stderrLines.length > 10) { + if (stderrLines.length > 100) { stderrLines.shift(); } }); @@ -293,35 +572,34 @@ app.whenReady().then(async () => { return; } - // tell user that Visual C++ redistributable needs to be installed on Windows - if (code === 3221225781 && process.platform === "win32") { - await dialog.showMessageBox(mainWindow, { - message: "Microsoft Visual C++ redistributable must be installed to run this application.", - }); - app.quit(); - return; - } - // show crash log const stdout = stdoutLines.join(""); const stderr = stderrLines.join(""); - await dialog.showMessageBox(mainWindow, { - message: [ - "MeshChat Crashed!", - "", - `Exit Code: ${code}`, - "", - `----- stdout -----`, - "", - stdout, - `----- stderr -----`, - "", - stderr, - ].join("\n"), - }); - // quit after dismissing error dialog - app.quit(); + // Base64 encode for safe URL passing + const stdoutBase64 = Buffer.from(stdout).toString("base64"); + const stderrBase64 = Buffer.from(stderr).toString("base64"); + + // Load crash page if main window exists + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.show(); // Ensure visible + mainWindow.focus(); + await mainWindow.loadFile(path.join(__dirname, "crash.html"), { + query: { + code: code.toString(), + stdout: stdoutBase64, + stderr: stderrBase64, + }, + }); + } else { + // Fallback for cases where window is gone + await dialog.showMessageBox({ + type: "error", + title: "MeshChatX Crashed", + message: `Backend exited with code: ${code}\n\nSTDOUT: ${stdout.slice(-500)}\n\nSTDERR: ${stderr.slice(-500)}`, + }); + app.quit(); + } }); } catch (e) { log(e); diff --git a/electron/preload.js b/electron/preload.js index d677747..5b2ec3d 100644 --- a/electron/preload.js +++ b/electron/preload.js @@ -9,6 +9,21 @@ contextBridge.exposeInMainWorld("electron", { return await ipcRenderer.invoke("app-version"); }, + // allow fetching electron version + electronVersion: function () { + return process.versions.electron; + }, + + // allow fetching chrome version + chromeVersion: function () { + return process.versions.chrome; + }, + + // allow fetching node version + nodeVersion: function () { + return process.versions.node; + }, + // show an alert dialog in electron browser window, this fixes a bug where alert breaks input fields on windows alert: async function (message) { return await ipcRenderer.invoke("alert", message); @@ -29,8 +44,43 @@ contextBridge.exposeInMainWorld("electron", { return await ipcRenderer.invoke("relaunch"); }, + // allow relaunching app in emergency mode + relaunchEmergency: async function () { + return await ipcRenderer.invoke("relaunch-emergency"); + }, + + // allow shutting down app in electron browser window + shutdown: async function () { + return await ipcRenderer.invoke("shutdown"); + }, + + // allow getting memory usage in electron browser window + getMemoryUsage: async function () { + return await ipcRenderer.invoke("get-memory-usage"); + }, + // allow showing a file path in os file manager showPathInFolder: async function (path) { return await ipcRenderer.invoke("showPathInFolder", path); }, + // allow checking hardware acceleration status + isHardwareAccelerationEnabled: async function () { + return await ipcRenderer.invoke("is-hardware-acceleration-enabled"); + }, + // allow checking integrity status + getIntegrityStatus: async function () { + return await ipcRenderer.invoke("get-integrity-status"); + }, + // allow showing a native notification + showNotification: function (title, body, silent = false) { + ipcRenderer.invoke("show-notification", { title, body, silent }); + }, + // allow controlling power save blocker + setPowerSaveBlocker: async function (enabled) { + return await ipcRenderer.invoke("set-power-save-blocker", enabled); + }, + // listen for protocol links + onProtocolLink: function (callback) { + ipcRenderer.on("open-protocol-link", (event, url) => callback(url)); + }, }); From 2f96ee07f3f934aa338f40527343d2293bcee3bf Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sat, 3 Jan 2026 16:03:34 -0600 Subject: [PATCH 005/234] feat: Update UI components and add new features including changelog modal, integrity warning, and voicemail playback functionality --- meshchatx/src/frontend/components/App.vue | 234 ++- .../frontend/components/ChangelogModal.vue | 277 ++++ .../frontend/components/CommandPalette.vue | 11 + .../src/frontend/components/ConfirmDialog.vue | 114 ++ .../components/IntegrityWarningModal.vue | 122 ++ .../src/frontend/components/LxmfUserIcon.vue | 9 +- .../components/MaterialDesignIcon.vue | 3 +- .../frontend/components/NotificationBell.vue | 5 + .../src/frontend/components/TutorialModal.vue | 1219 ++++++++++++++++ .../frontend/components/about/AboutPage.vue | 382 ++++- .../components/archives/ArchiveSidebar.vue | 111 ++ .../components/archives/ArchivesPage.vue | 577 ++++---- .../frontend/components/call/CallOverlay.vue | 201 ++- .../src/frontend/components/call/CallPage.vue | 1288 +++++++++++++---- .../components/call/RingtoneEditor.vue | 495 +++++++ .../components/call/RingtoneEditorModal.vue | 526 +++++++ .../components/debug/DebugLogsPage.vue | 110 ++ .../src/frontend/components/docs/DocsPage.vue | 623 ++++++++ .../interfaces/AddInterfacePage.vue | 58 +- .../components/interfaces/Interface.vue | 2 +- .../src/frontend/components/map/MapPage.vue | 772 +++++++++- .../components/messages/AddImageButton.vue | 12 +- .../messages/AudioWaveformPlayer.vue | 294 ++++ .../messages/ConversationDropDownMenu.vue | 63 +- .../messages/ConversationViewer.vue | 482 +++--- .../components/messages/MessagesPage.vue | 91 +- .../components/messages/MessagesSidebar.vue | 274 ++-- .../components/messages/PaperMessageModal.vue | 127 +- .../micron-editor/MicronEditorPage.vue | 184 ++- .../network-visualiser/NetworkVisualiser.vue | 336 ++++- .../nomadnetwork/NomadNetworkPage.vue | 90 +- .../nomadnetwork/NomadNetworkSidebar.vue | 125 +- .../components/settings/IdentitiesPage.vue | 21 +- .../components/settings/SettingsPage.vue | 217 +++ .../components/tools/PaperMessagePage.vue | 177 ++- .../frontend/components/tools/ToolsPage.vue | 26 + .../components/translator/TranslatorPage.vue | 48 +- 37 files changed, 8402 insertions(+), 1304 deletions(-) create mode 100644 meshchatx/src/frontend/components/ChangelogModal.vue create mode 100644 meshchatx/src/frontend/components/ConfirmDialog.vue create mode 100644 meshchatx/src/frontend/components/IntegrityWarningModal.vue create mode 100644 meshchatx/src/frontend/components/TutorialModal.vue create mode 100644 meshchatx/src/frontend/components/archives/ArchiveSidebar.vue create mode 100644 meshchatx/src/frontend/components/call/RingtoneEditor.vue create mode 100644 meshchatx/src/frontend/components/call/RingtoneEditorModal.vue create mode 100644 meshchatx/src/frontend/components/debug/DebugLogsPage.vue create mode 100644 meshchatx/src/frontend/components/docs/DocsPage.vue create mode 100644 meshchatx/src/frontend/components/messages/AudioWaveformPlayer.vue diff --git a/meshchatx/src/frontend/components/App.vue b/meshchatx/src/frontend/components/App.vue index 13bb054..6024141 100644 --- a/meshchatx/src/frontend/components/App.vue +++ b/meshchatx/src/frontend/components/App.vue @@ -419,14 +419,26 @@ + + + + @@ -463,13 +475,18 @@ import GlobalEmitter from "../js/GlobalEmitter"; import NotificationUtils from "../js/NotificationUtils"; import LxmfUserIcon from "./LxmfUserIcon.vue"; import Toast from "./Toast.vue"; +import ConfirmDialog from "./ConfirmDialog.vue"; import ToastUtils from "../js/ToastUtils"; import MaterialDesignIcon from "./MaterialDesignIcon.vue"; import NotificationBell from "./NotificationBell.vue"; import LanguageSelector from "./LanguageSelector.vue"; import CallOverlay from "./call/CallOverlay.vue"; import CommandPalette from "./CommandPalette.vue"; +import IntegrityWarningModal from "./IntegrityWarningModal.vue"; +import ChangelogModal from "./ChangelogModal.vue"; +import TutorialModal from "./TutorialModal.vue"; import KeyboardShortcuts from "../js/KeyboardShortcuts"; +import ElectronUtils from "../js/ElectronUtils"; import logoUrl from "../assets/images/logo.png"; export default { @@ -478,15 +495,20 @@ export default { LxmfUserIcon, SidebarLink, Toast, + ConfirmDialog, MaterialDesignIcon, NotificationBell, LanguageSelector, CallOverlay, CommandPalette, + IntegrityWarningModal, + ChangelogModal, + TutorialModal, }, data() { return { logoUrl, + ElectronUtils, reloadInterval: null, appInfoInterval: null, @@ -501,14 +523,22 @@ export default { displayName: "Anonymous Peer", config: null, appInfo: null, + hasCheckedForModals: false, activeCall: null, propagationNodeStatus: null, isCallEnded: false, wasDeclined: false, lastCall: null, + voicemailStatus: null, + isMicMuting: false, + isSpeakerMuting: false, endedTimeout: null, ringtonePlayer: null, + isFetchingRingtone: false, + initiationStatus: null, + initiationTargetHash: null, + isCallWindowOpen: false, }; }, computed: { @@ -535,6 +565,9 @@ export default { "complete", ].includes(this.propagationNodeStatus?.state); }, + activeCallTab() { + return GlobalState.activeCallTab; + }, }, watch: { $route() { @@ -591,13 +624,25 @@ export default { this.handleKeyboardShortcut(action); }); + GlobalEmitter.on("block-status-changed", () => { + this.getBlockedDestinations(); + }); + this.getAppInfo(); this.getConfig(); + this.getBlockedDestinations(); this.getKeyboardShortcuts(); this.updateRingtonePlayer(); this.updateTelephoneStatus(); this.updatePropagationNodeStatus(); + // listen for protocol links in electron + if (ElectronUtils.isElectron()) { + window.electron.onProtocolLink((url) => { + this.handleProtocolLink(url); + }); + } + // update info every few seconds this.reloadInterval = setInterval(() => { this.updateTelephoneStatus(); @@ -618,6 +663,7 @@ export default { switch (json.type) { case "config": { this.config = json.config; + GlobalState.config = json.config; this.displayName = json.config.display_name; if (this.config?.theme) { if (this.config.theme === "dark") { @@ -652,6 +698,11 @@ export default { ); break; } + case "telephone_initiation_status": { + this.initiationStatus = json.status; + this.initiationTargetHash = json.target_hash; + break; + } case "new_voicemail": { NotificationUtils.showNewVoicemailNotification( json.remote_identity_name || json.remote_identity_hash @@ -662,9 +713,24 @@ export default { case "telephone_call_established": case "telephone_call_ended": { this.stopRingtone(); + this.ringtonePlayer = null; this.updateTelephoneStatus(); break; } + case "lxmf.delivery": { + if (this.config?.do_not_disturb_enabled) { + break; + } + + // show notification for new messages if window is not focussed + if (!document.hasFocus()) { + NotificationUtils.showNewMessageNotification( + json.remote_identity_name, + json.lxmf_message?.content + ); + } + break; + } case "identity_switched": { ToastUtils.success(`Switched to identity: ${json.display_name}`); @@ -689,6 +755,17 @@ export default { try { const response = await window.axios.get(`/api/v1/app/info`); this.appInfo = response.data.app_info; + + // check if we should show tutorial or changelog (only on first load) + if (!this.hasCheckedForModals) { + this.hasCheckedForModals = true; + if (this.appInfo && !this.appInfo.tutorial_seen) { + this.$refs.tutorialModal.show(); + } else if (this.appInfo && this.appInfo.changelog_seen_version !== this.appInfo.version) { + // show changelog if version changed + this.$refs.changelogModal.show(); + } + } } catch (e) { // do nothing if failed to load app info console.log(e); @@ -698,6 +775,7 @@ export default { try { const response = await window.axios.get(`/api/v1/config`); this.config = response.data.config; + GlobalState.config = response.data.config; if (this.config?.theme) { if (this.config.theme === "dark") { document.documentElement.classList.add("dark"); @@ -710,6 +788,14 @@ export default { console.log(e); } }, + async getBlockedDestinations() { + try { + const response = await window.axios.get("/api/v1/blocked-destinations"); + GlobalState.blockedDestinations = response.data.blocked_destinations || []; + } catch (e) { + console.log("Failed to load blocked destinations:", e); + } + }, async getKeyboardShortcuts() { WebSocketConnection.send( JSON.stringify({ @@ -865,6 +951,9 @@ export default { if (status.has_custom_ringtone && status.id) { this.ringtonePlayer = new Audio(`/api/v1/telephone/ringtones/${status.id}/audio`); this.ringtonePlayer.loop = true; + if (status.volume !== undefined) { + this.ringtonePlayer.volume = status.volume; + } } } catch (e) { console.error("Failed to update ringtone player:", e); @@ -873,15 +962,21 @@ export default { }, playRingtone() { if (this.ringtonePlayer) { - this.ringtonePlayer.play().catch((e) => { - console.log("Failed to play custom ringtone:", e); - }); + if (this.ringtonePlayer.paused) { + this.ringtonePlayer.play().catch((e) => { + console.log("Failed to play custom ringtone:", e); + }); + } } }, stopRingtone() { if (this.ringtonePlayer) { - this.ringtonePlayer.pause(); - this.ringtonePlayer.currentTime = 0; + try { + this.ringtonePlayer.pause(); + this.ringtonePlayer.currentTime = 0; + } catch { + // ignore errors during pause + } } }, async updateTelephoneStatus() { @@ -889,13 +984,80 @@ export default { // fetch status const response = await axios.get("/api/v1/telephone/status"); const oldCall = this.activeCall; + const newCall = response.data.active_call; // update ui - this.activeCall = response.data.active_call; + this.activeCall = newCall; + this.voicemailStatus = response.data.voicemail; + this.initiationStatus = response.data.initiation_status; + this.initiationTargetHash = response.data.initiation_target_hash; - // Stop ringtone if not ringing anymore - if (this.activeCall?.status !== 4) { - this.stopRingtone(); + // Handle power management for calls + if (ElectronUtils.isElectron()) { + if (this.activeCall) { + window.electron.setPowerSaveBlocker(true); + } else if (!this.initiationStatus) { + window.electron.setPowerSaveBlocker(false); + } + } + + // Handle opening call in separate window if enabled + if ( + (this.activeCall || this.initiationStatus) && + this.config?.desktop_open_calls_in_separate_window && + ElectronUtils.isElectron() + ) { + if (!this.isCallWindowOpen && !this.$route.meta.isPopout) { + this.isCallWindowOpen = true; + window.open("/call.html", "_blank", "width=600,height=800"); + } + } else { + this.isCallWindowOpen = false; + } + + // Handle ringtone + if (this.activeCall?.status === 4) { + // Call is ringing + if (!this.ringtonePlayer && this.config?.custom_ringtone_enabled && !this.isFetchingRingtone) { + this.isFetchingRingtone = true; + try { + const caller_hash = this.activeCall.remote_identity_hash; + const ringResponse = await window.axios.get( + `/api/v1/telephone/ringtones/status?caller_hash=${caller_hash}` + ); + const status = ringResponse.data; + if (status.has_custom_ringtone && status.id) { + // Double check if we still need to play it (call might have ended during await) + if (this.activeCall?.status === 4) { + // Stop any existing player just in case + this.stopRingtone(); + + this.ringtonePlayer = new Audio(`/api/v1/telephone/ringtones/${status.id}/audio`); + this.ringtonePlayer.loop = true; + if (status.volume !== undefined) { + this.ringtonePlayer.volume = status.volume; + } + this.playRingtone(); + } + } + } finally { + this.isFetchingRingtone = false; + } + } else if (this.ringtonePlayer && this.activeCall?.status === 4) { + this.playRingtone(); + } + } else { + // Not ringing + if (this.ringtonePlayer) { + this.stopRingtone(); + this.ringtonePlayer = null; + } + } + + // Preserve local mute state if we're currently toggling + if (newCall && oldCall) { + newCall.is_mic_muted = oldCall.is_mic_muted; + newCall.is_speaker_muted = oldCall.is_speaker_muted; } // If call just ended, show ended state for a few seconds @@ -935,6 +1097,24 @@ export default { this.wasDeclined = true; } }, + onToggleMic(isMuted) { + this.isMicMuting = true; + if (this.activeCall) { + this.activeCall.is_mic_muted = isMuted; + } + setTimeout(() => { + this.isMicMuting = false; + }, 2000); + }, + onToggleSpeaker(isMuted) { + this.isSpeakerMuting = true; + if (this.activeCall) { + this.activeCall.is_speaker_muted = isMuted; + } + setTimeout(() => { + this.isSpeakerMuting = false; + }, 2000); + }, onAppNameClick() { // user may be on mobile, and is unable to scroll back to sidebar, so let them tap app name to do it this.$refs["middle"].scrollTo({ @@ -943,6 +1123,20 @@ export default { behavior: "smooth", }); }, + handleProtocolLink(url) { + try { + // lxmf:// or rns:// + const hash = url.replace("lxmf://", "").replace("rns://", "").split("/")[0].replace("/", ""); + if (hash && hash.length === 32) { + this.$router.push({ + name: "messages", + params: { destinationHash: hash }, + }); + } + } catch (e) { + console.error("Failed to handle protocol link:", e); + } + }, handleKeyboardShortcut(action) { switch (action) { case "nav_messages": @@ -984,7 +1178,25 @@ export default { }; - diff --git a/meshchatx/src/frontend/components/CommandPalette.vue b/meshchatx/src/frontend/components/CommandPalette.vue index 9034c5d..df02c70 100644 --- a/meshchatx/src/frontend/components/CommandPalette.vue +++ b/meshchatx/src/frontend/components/CommandPalette.vue @@ -63,6 +63,7 @@ > + +
    +
    + +
    +
    +
    +
    + +
    +
    +

    + Confirm +

    +

    + {{ pendingConfirm.message }} +

    +
    +
    + +
    + + +
    +
    +
    +
    +
    + + + + + diff --git a/meshchatx/src/frontend/components/IntegrityWarningModal.vue b/meshchatx/src/frontend/components/IntegrityWarningModal.vue new file mode 100644 index 0000000..e30df5d --- /dev/null +++ b/meshchatx/src/frontend/components/IntegrityWarningModal.vue @@ -0,0 +1,122 @@ + + + + + diff --git a/meshchatx/src/frontend/components/LxmfUserIcon.vue b/meshchatx/src/frontend/components/LxmfUserIcon.vue index 9ac5f95..be96beb 100644 --- a/meshchatx/src/frontend/components/LxmfUserIcon.vue +++ b/meshchatx/src/frontend/components/LxmfUserIcon.vue @@ -1,6 +1,9 @@ + + diff --git a/meshchatx/src/frontend/components/call/RingtoneEditorModal.vue b/meshchatx/src/frontend/components/call/RingtoneEditorModal.vue new file mode 100644 index 0000000..0d2e428 --- /dev/null +++ b/meshchatx/src/frontend/components/call/RingtoneEditorModal.vue @@ -0,0 +1,526 @@ + + + + + diff --git a/meshchatx/src/frontend/components/debug/DebugLogsPage.vue b/meshchatx/src/frontend/components/debug/DebugLogsPage.vue new file mode 100644 index 0000000..83abf86 --- /dev/null +++ b/meshchatx/src/frontend/components/debug/DebugLogsPage.vue @@ -0,0 +1,110 @@ + + + diff --git a/meshchatx/src/frontend/components/docs/DocsPage.vue b/meshchatx/src/frontend/components/docs/DocsPage.vue new file mode 100644 index 0000000..c03c690 --- /dev/null +++ b/meshchatx/src/frontend/components/docs/DocsPage.vue @@ -0,0 +1,623 @@ + + + + + diff --git a/meshchatx/src/frontend/components/interfaces/AddInterfacePage.vue b/meshchatx/src/frontend/components/interfaces/AddInterfacePage.vue index 72c62e7..4f12d8c 100644 --- a/meshchatx/src/frontend/components/interfaces/AddInterfacePage.vue +++ b/meshchatx/src/frontend/components/interfaces/AddInterfacePage.vue @@ -37,36 +37,23 @@
    -
    +
    -
    RNS Testnet Amsterdam
    +
    {{ communityIface.name }}
    - amsterdam.connect.reticulum.network:4965 + {{ communityIface.target_host }}:{{ communityIface.target_port }} + Online + Offline
    -
    -
    - -
    -
    - -
    -
    -
    - RNS Testnet BetweenTheBorders -
    -
    - reticulum.betweentheborders.com:4242 + {{ communityIface.description }}
    @@ -74,10 +61,10 @@ type="button" class="inline-flex items-center gap-x-2 rounded-full bg-blue-600/90 px-3 py-1.5 text-xs font-semibold text-white shadow hover:bg-blue-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500" @click=" - newInterfaceName = 'RNS Testnet BetweenTheBorders'; - newInterfaceType = 'TCPClientInterface'; - newInterfaceTargetHost = 'reticulum.betweentheborders.com'; - newInterfaceTargetPort = '4242'; + newInterfaceName = communityIface.name; + newInterfaceType = communityIface.type; + newInterfaceTargetHost = communityIface.target_host; + newInterfaceTargetPort = communityIface.target_port; " > Use Interface @@ -1097,6 +1084,8 @@ export default { config: null, + communityInterfaces: [], + comports: [], newInterfaceName: null, @@ -1228,6 +1217,7 @@ export default { mounted() { this.getConfig(); this.loadComports(); + this.loadCommunityInterfaces(); // check if we are editing an interface const interfaceName = this.$route.query.interface_name; @@ -1263,6 +1253,14 @@ export default { // do nothing if failed to load interfaces } }, + async loadCommunityInterfaces() { + try { + const response = await window.axios.get(`/api/v1/community-interfaces`); + this.communityInterfaces = response.data.interfaces; + } catch { + // do nothing if failed to load interfaces + } + }, async loadInterfaceToEdit(interfaceName) { try { // fetch interfaces diff --git a/meshchatx/src/frontend/components/interfaces/Interface.vue b/meshchatx/src/frontend/components/interfaces/Interface.vue index edce296..c025824 100644 --- a/meshchatx/src/frontend/components/interfaces/Interface.vue +++ b/meshchatx/src/frontend/components/interfaces/Interface.vue @@ -274,7 +274,7 @@ export default { diff --git a/meshchatx/src/frontend/components/messages/AddImageButton.vue b/meshchatx/src/frontend/components/messages/AddImageButton.vue index 795a30d..958af96 100644 --- a/meshchatx/src/frontend/components/messages/AddImageButton.vue +++ b/meshchatx/src/frontend/components/messages/AddImageButton.vue @@ -107,7 +107,9 @@ export default { quality: 0.2, mimeType: "image/webp", success: (result) => { - this.$emit("add-image", result); + // ensure result is a File with the same name as original + const compressedFile = new File([result], file.name, { type: result.type }); + this.$emit("add-image", compressedFile); }, error: (err) => { DialogUtils.alert(err.message); @@ -122,7 +124,9 @@ export default { quality: 0.6, mimeType: "image/webp", success: (result) => { - this.$emit("add-image", result); + // ensure result is a File with the same name as original + const compressedFile = new File([result], file.name, { type: result.type }); + this.$emit("add-image", compressedFile); }, error: (err) => { DialogUtils.alert(err.message); @@ -137,7 +141,9 @@ export default { quality: 0.75, mimeType: "image/webp", success: (result) => { - this.$emit("add-image", result); + // ensure result is a File with the same name as original + const compressedFile = new File([result], file.name, { type: result.type }); + this.$emit("add-image", compressedFile); }, error: (err) => { DialogUtils.alert(err.message); diff --git a/meshchatx/src/frontend/components/messages/AudioWaveformPlayer.vue b/meshchatx/src/frontend/components/messages/AudioWaveformPlayer.vue new file mode 100644 index 0000000..a062e35 --- /dev/null +++ b/meshchatx/src/frontend/components/messages/AudioWaveformPlayer.vue @@ -0,0 +1,294 @@ + + + + + diff --git a/meshchatx/src/frontend/components/messages/ConversationDropDownMenu.vue b/meshchatx/src/frontend/components/messages/ConversationDropDownMenu.vue index 0534e5f..c09155c 100644 --- a/meshchatx/src/frontend/components/messages/ConversationDropDownMenu.vue +++ b/meshchatx/src/frontend/components/messages/ConversationDropDownMenu.vue @@ -2,14 +2,14 @@ diff --git a/meshchatx/src/frontend/components/messages/ConversationViewer.vue b/meshchatx/src/frontend/components/messages/ConversationViewer.vue index 2ed99ec..d6b94d3 100644 --- a/meshchatx/src/frontend/components/messages/ConversationViewer.vue +++ b/meshchatx/src/frontend/components/messages/ConversationViewer.vue @@ -892,12 +892,50 @@ />
    -

    - {{ $t("messages.no_active_chat") }} -

    -

    - {{ $t("messages.select_peer_or_enter_address") }} -

    +
    +

    + {{ $t("messages.no_active_chat") }} +

    +

    + {{ $t("messages.select_peer_or_enter_address") }} +

    + + +
    +
    +

    + Latest Chats +

    +
    +
    +
    + +
    +
    + {{ chat.custom_display_name ?? chat.display_name }} +
    +
    + {{ chat.latest_message_preview || chat.latest_message_title || "No messages yet" }} +
    +
    + +
    +
    @@ -1088,6 +1126,9 @@ export default { isMobile() { return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); }, + latestConversations() { + return this.conversations.slice(0, 4); + }, canSendMessage() { // can send if message text is present const messageText = this.newMessageText.trim(); diff --git a/meshchatx/src/frontend/components/settings/IdentitiesPage.vue b/meshchatx/src/frontend/components/settings/IdentitiesPage.vue index ecb7af3..7165ba3 100644 --- a/meshchatx/src/frontend/components/settings/IdentitiesPage.vue +++ b/meshchatx/src/frontend/components/settings/IdentitiesPage.vue @@ -91,8 +91,23 @@
    - {{ identity.hash }} + ID: {{ identity.hash }} +
    +
    + LXMF: {{ identity.lxmf_address }} +
    +
    + LXST: {{ identity.lxst_address }}
    From c7c70a5868f2a586a275da028a7736506bb00954 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 00:04:40 -0600 Subject: [PATCH 118/234] feat(identity_manager, map_manager): add lxmf and lxst address handling in metadata and optimize tile downloading with parallel processing --- meshchatx/meshchat.py | 2 + meshchatx/src/backend/identity_manager.py | 10 ++ meshchatx/src/backend/map_manager.py | 133 ++++++++++++++-------- 3 files changed, 98 insertions(+), 47 deletions(-) diff --git a/meshchatx/meshchat.py b/meshchatx/meshchat.py index 09a1a4e..542c25b 100644 --- a/meshchatx/meshchat.py +++ b/meshchatx/meshchat.py @@ -1125,6 +1125,8 @@ class ReticulumMeshChat: "icon_name": self.config.lxmf_user_icon_name.get(), "icon_foreground_colour": self.config.lxmf_user_icon_foreground_colour.get(), "icon_background_colour": self.config.lxmf_user_icon_background_colour.get(), + "lxmf_address": self.config.lxmf_address_hash.get(), + "lxst_address": self.config.lxst_address_hash.get(), } self.identity_manager.update_metadata_cache(identity_hash, metadata) diff --git a/meshchatx/src/backend/identity_manager.py b/meshchatx/src/backend/identity_manager.py index 0992eb3..2e66de1 100644 --- a/meshchatx/src/backend/identity_manager.py +++ b/meshchatx/src/backend/identity_manager.py @@ -67,6 +67,8 @@ class IdentityManager: "icon_background_colour": metadata.get( "icon_background_colour" ), + "lxmf_address": metadata.get("lxmf_address"), + "lxst_address": metadata.get("lxst_address"), "is_current": ( current_identity_hash is not None and identity_hash == current_identity_hash @@ -84,6 +86,8 @@ class IdentityManager: icon_name = None icon_foreground_colour = None icon_background_colour = None + lxmf_address = None + lxst_address = None try: temp_provider = DatabaseProvider(db_path) @@ -96,6 +100,8 @@ class IdentityManager: icon_background_colour = temp_config_dao.get( "lxmf_user_icon_background_colour", ) + lxmf_address = temp_config_dao.get("lxmf_address_hash") + lxst_address = temp_config_dao.get("lxst_address_hash") temp_provider.close() # Save metadata for next time @@ -104,6 +110,8 @@ class IdentityManager: "icon_name": icon_name, "icon_foreground_colour": icon_foreground_colour, "icon_background_colour": icon_background_colour, + "lxmf_address": lxmf_address, + "lxst_address": lxst_address, } with open(metadata_path, "w") as f: json.dump(metadata, f) @@ -117,6 +125,8 @@ class IdentityManager: "icon_name": icon_name, "icon_foreground_colour": icon_foreground_colour, "icon_background_colour": icon_background_colour, + "lxmf_address": lxmf_address, + "lxst_address": lxst_address, "is_current": ( current_identity_hash is not None and identity_hash == current_identity_hash diff --git a/meshchatx/src/backend/map_manager.py b/meshchatx/src/backend/map_manager.py index 7bb502d..e04d908 100644 --- a/meshchatx/src/backend/map_manager.py +++ b/meshchatx/src/backend/map_manager.py @@ -1,4 +1,5 @@ import base64 +import concurrent.futures import math import os import sqlite3 @@ -184,14 +185,17 @@ class MapManager: # bbox: [min_lon, min_lat, max_lon, max_lat] min_lon, min_lat, max_lon, max_lat = bbox - # calculate total tiles - total_tiles = 0 + # collect all tiles to download + tiles_to_download = [] zoom_levels = range(min_zoom, max_zoom + 1) for z in zoom_levels: x1, y1 = self._lonlat_to_tile(min_lon, max_lat, z) x2, y2 = self._lonlat_to_tile(max_lon, min_lat, z) - total_tiles += (x2 - x1 + 1) * (y2 - y1 + 1) + for x in range(x1, x2 + 1): + for y in range(y1, y2 + 1): + tiles_to_download.append((z, x, y)) + total_tiles = len(tiles_to_download) self._export_progress[export_id]["total"] = total_tiles self._export_progress[export_id]["status"] = "downloading" @@ -220,61 +224,96 @@ class MapManager: ("bounds", f"{min_lon},{min_lat},{max_lon},{max_lat}"), ] cursor.executemany("INSERT INTO metadata VALUES (?, ?)", metadata) + conn.commit() + tile_server_url = self.config.map_tile_server_url.get() current_count = 0 - for z in zoom_levels: - x1, y1 = self._lonlat_to_tile(min_lon, max_lat, z) - x2, y2 = self._lonlat_to_tile(max_lon, min_lat, z) - for x in range(x1, x2 + 1): - for y in range(y1, y2 + 1): - # check if we should stop - if export_id in self._export_cancelled: - conn.close() - if os.path.exists(dest_path): - os.remove(dest_path) - if export_id in self._export_progress: - del self._export_progress[export_id] - self._export_cancelled.remove(export_id) - return + # download tiles in parallel + # using 10 workers for a good balance between speed and being polite + max_workers = 10 - # download tile - tile_server_url = self.config.map_tile_server_url.get() - tile_url = ( - tile_server_url.replace("{z}", str(z)) - .replace("{x}", str(x)) - .replace("{y}", str(y)) - ) - try: - # wait a bit to be nice to OSM - time.sleep(0.1) + def download_tile(tile_coords): + if export_id in self._export_cancelled: + return None - response = requests.get( - tile_url, - headers={"User-Agent": "MeshChatX/1.0 MapExporter"}, - timeout=10, - ) - if response.status_code == 200: - # MBTiles uses TMS (y flipped) - tms_y = (1 << z) - 1 - y - cursor.execute( - "INSERT INTO tiles VALUES (?, ?, ?, ?)", - (z, x, tms_y, response.content), - ) - except Exception as e: - RNS.log( - f"Export failed to download tile {z}/{x}/{y}: {e}", - RNS.LOG_ERROR, - ) + z, x, y = tile_coords + tile_url = ( + tile_server_url.replace("{z}", str(z)) + .replace("{x}", str(x)) + .replace("{y}", str(y)) + ) - current_count += 1 + try: + # small per-thread delay to avoid overwhelming servers + time.sleep(0.02) + + response = requests.get( + tile_url, + headers={"User-Agent": "MeshChatX/1.0 MapExporter"}, + timeout=15, + ) + if response.status_code == 200: + # MBTiles uses TMS (y flipped) + tms_y = (1 << z) - 1 - y + return (z, x, tms_y, response.content) + except Exception as e: + RNS.log( + f"Export failed to download tile {z}/{x}/{y}: {e}", + RNS.LOG_ERROR, + ) + return None + + with concurrent.futures.ThreadPoolExecutor( + max_workers=max_workers + ) as executor: + future_to_tile = { + executor.submit(download_tile, tile): tile + for tile in tiles_to_download + } + + batch_size = 50 + batch_data = [] + + for future in concurrent.futures.as_completed(future_to_tile): + if export_id in self._export_cancelled: + executor.shutdown(wait=False, cancel_futures=True) + break + + result = future.result() + if result: + batch_data.append(result) + + current_count += 1 + + # Update progress every few tiles or when batch is ready + if current_count % 5 == 0 or current_count == total_tiles: self._export_progress[export_id]["current"] = current_count self._export_progress[export_id]["progress"] = int( (current_count / total_tiles) * 100, ) - # commit after each zoom level - conn.commit() + # Write batches to database + if len(batch_data) >= batch_size or ( + current_count == total_tiles and batch_data + ): + try: + cursor.executemany( + "INSERT INTO tiles VALUES (?, ?, ?, ?)", batch_data + ) + conn.commit() + batch_data = [] + except Exception as e: + RNS.log(f"Failed to insert map tiles: {e}", RNS.LOG_ERROR) + + if export_id in self._export_cancelled: + conn.close() + if os.path.exists(dest_path): + os.remove(dest_path) + if export_id in self._export_progress: + del self._export_progress[export_id] + self._export_cancelled.remove(export_id) + return conn.close() self._export_progress[export_id]["status"] = "completed" From 5a995c7304da1ccbb75a8031272d64f6fdea8411 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 00:07:21 -0600 Subject: [PATCH 119/234] test(AboutPage, ConfirmDialog, MapPage): update tests for improved component behavior and UI consistency --- tests/frontend/AboutPage.test.js | 13 +++++++++---- tests/frontend/ConfirmDialog.test.js | 7 ++----- tests/frontend/MapPage.test.js | 11 +++++++++++ 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/tests/frontend/AboutPage.test.js b/tests/frontend/AboutPage.test.js index 1de7196..96315ab 100644 --- a/tests/frontend/AboutPage.test.js +++ b/tests/frontend/AboutPage.test.js @@ -91,24 +91,28 @@ describe("AboutPage.vue", () => { }); const wrapper = mountAboutPage(); + wrapper.vm.showAdvanced = true; await vi.runOnlyPendingTimers(); await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick(); // Extra tick for multiple async calls + await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick(); expect(axiosMock.get).toHaveBeenCalledWith("/api/v1/app/info"); expect(axiosMock.get).toHaveBeenCalledWith("/api/v1/config"); - expect(wrapper.text()).toContain("Reticulum MeshChatX"); + expect(wrapper.text()).toContain("MeshChatX"); + expect(wrapper.text()).toContain("Reticulum Network Stack"); expect(wrapper.text()).toContain("hash1"); expect(wrapper.text()).toContain("hash2"); // Check for Dependency Chain section - expect(wrapper.text()).toContain("about.dependency_chain"); + expect(wrapper.text()).toContain("Dependency Chain"); expect(wrapper.text()).toContain("Lightweight Extensible Message Format"); expect(wrapper.text()).toContain("Reticulum Network Stack"); // Check for dependencies - expect(wrapper.text()).toContain("about.backend_dependencies"); + expect(wrapper.text()).toContain("Backend Stack"); expect(wrapper.text()).toContain("aiohttp"); expect(wrapper.text()).toContain("3.8.1"); }); @@ -133,6 +137,7 @@ describe("AboutPage.vue", () => { }); const wrapper = mountAboutPage(); + wrapper.vm.showAdvanced = true; await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick(); @@ -140,7 +145,7 @@ describe("AboutPage.vue", () => { expect(getMemoryUsageSpy).toHaveBeenCalled(); expect(wrapper.vm.electronMemoryUsage).not.toBeNull(); - expect(wrapper.text()).toContain("Electron Resources"); + expect(wrapper.text()).toContain("Environment Information"); }); it("handles shutdown action", async () => { diff --git a/tests/frontend/ConfirmDialog.test.js b/tests/frontend/ConfirmDialog.test.js index 9a075a8..cc56d3c 100644 --- a/tests/frontend/ConfirmDialog.test.js +++ b/tests/frontend/ConfirmDialog.test.js @@ -95,12 +95,9 @@ describe("ConfirmDialog.vue", () => { await wrapper.vm.$nextTick(); - const backdrop = wrapper.findAll(".fixed").find((el) => { - const classes = el.classes(); - return classes.includes("inset-0") && !classes.includes("z-[200]"); - }); + const backdrop = wrapper.find(".backdrop-blur-sm"); - if (backdrop && backdrop.exists()) { + if (backdrop.exists()) { await backdrop.trigger("click"); await wrapper.vm.$nextTick(); expect(resolvePromise).toHaveBeenCalledWith(false); diff --git a/tests/frontend/MapPage.test.js b/tests/frontend/MapPage.test.js index 8810108..bcf6ac4 100644 --- a/tests/frontend/MapPage.test.js +++ b/tests/frontend/MapPage.test.js @@ -19,6 +19,12 @@ vi.mock("ol/Map", () => ({ on: vi.fn(), addLayer: vi.fn(), addInteraction: vi.fn(), + addOverlay: vi.fn(), + removeInteraction: vi.fn(), + removeOverlay: vi.fn(), + un: vi.fn(), + getEventPixel: vi.fn().mockReturnValue([0, 0]), + getTargetElement: vi.fn().mockReturnValue({ style: {} }), getView: vi.fn().mockReturnValue({ on: vi.fn(), setCenter: vi.fn(), @@ -33,6 +39,9 @@ vi.mock("ol/Map", () => ({ push: vi.fn(), getArray: vi.fn().mockReturnValue([]), }), + getOverlays: vi.fn().mockReturnValue({ + getArray: vi.fn().mockReturnValue([]), + }), forEachFeatureAtPixel: vi.fn(), setTarget: vi.fn(), updateSize: vi.fn(), @@ -129,10 +138,12 @@ describe("MapPage.vue", () => { patch: vi.fn().mockResolvedValue({ data: {} }), delete: vi.fn().mockResolvedValue({ data: {} }), }; + vi.stubGlobal("axios", axiosMock); window.axios = axiosMock; }); beforeEach(() => { + vi.stubGlobal("axios", axiosMock); window.axios = axiosMock; // Mock localStorage const localStorageMock = { From c8a014b06e36f84b17aa51e24310aaa2f7c6fa12 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 00:07:29 -0600 Subject: [PATCH 120/234] feat(AboutPage, MapPage): add identity hash and LXMF address display in AboutPage, and ensure axios is available before fetching peers in MapPage --- .../frontend/components/about/AboutPage.vue | 23 ++++++++++++++++++- .../src/frontend/components/map/MapPage.vue | 1 + 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/meshchatx/src/frontend/components/about/AboutPage.vue b/meshchatx/src/frontend/components/about/AboutPage.vue index f608f10..9f4602a 100644 --- a/meshchatx/src/frontend/components/about/AboutPage.vue +++ b/meshchatx/src/frontend/components/about/AboutPage.vue @@ -155,6 +155,27 @@
    +
    +
    + Identity Hash + {{ + config.identity_hash + }} +
    +
    + LXMF Address + {{ + config.lxmf_address_hash + }} +
    +
    Python Recovery diff --git a/meshchatx/src/frontend/components/map/MapPage.vue b/meshchatx/src/frontend/components/map/MapPage.vue index bd56dcb..8da7ef5 100644 --- a/meshchatx/src/frontend/components/map/MapPage.vue +++ b/meshchatx/src/frontend/components/map/MapPage.vue @@ -2035,6 +2035,7 @@ export default { this.isMobileScreen = window.innerWidth < 640; }, async fetchPeers() { + if (!window.axios) return; try { const response = await window.axios.get("/api/v1/lxmf/conversations"); const peers = {}; From 46872209d61c380ec8b542dd8b3486fb72d867ca Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 00:08:50 -0600 Subject: [PATCH 121/234] chore(eslint): update ignore patterns to exclude additional directories and files --- eslint.config.mjs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 140c2b2..55bd131 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -9,6 +9,10 @@ export default [ "**/node_modules/**", "**/dist/**", "**/build/**", + "**/out/**", + "**/android/**", + "**/MagicMock/**", + "**/reticulum_meshchatx.egg-info/**", "**/electron/assets/**", "**/meshchatx/public/**", "**/meshchatx/src/frontend/public/**", @@ -26,7 +30,6 @@ export default [ "**/*.wasm", "**/*.proto", "**/tests/**", - "**/tests/frontend/**", "**/.pnpm-store/**", ], }, From 23df1b0618845ec350155c8da8a94972a2eb7258 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 00:18:11 -0600 Subject: [PATCH 122/234] chore(eslint): add additional directories to ignore patterns --- eslint.config.mjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eslint.config.mjs b/eslint.config.mjs index 55bd131..7e3bf46 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -13,6 +13,8 @@ export default [ "**/android/**", "**/MagicMock/**", "**/reticulum_meshchatx.egg-info/**", + "**/meshchat-config/**", + "**/screenshots/**", "**/electron/assets/**", "**/meshchatx/public/**", "**/meshchatx/src/frontend/public/**", From 1dd6d93729eff234261e7aa0fec506c77769a202 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 00:18:19 -0600 Subject: [PATCH 123/234] refactor(AboutPage): remove unused MaterialDesignIcon component from AboutPage.vue --- meshchatx/src/frontend/components/about/AboutPage.vue | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/meshchatx/src/frontend/components/about/AboutPage.vue b/meshchatx/src/frontend/components/about/AboutPage.vue index 9f4602a..0aa12e4 100644 --- a/meshchatx/src/frontend/components/about/AboutPage.vue +++ b/meshchatx/src/frontend/components/about/AboutPage.vue @@ -714,13 +714,10 @@ import Utils from "../../js/Utils"; import ElectronUtils from "../../js/ElectronUtils"; import DialogUtils from "../../js/DialogUtils"; -import MaterialDesignIcon from "../MaterialDesignIcon.vue"; import ToastUtils from "../../js/ToastUtils"; export default { name: "AboutPage", - components: { - MaterialDesignIcon, - }, + components: {}, data() { return { appInfo: null, From e60db2008249508953caa2371d6cfb60325b6312 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 00:34:24 -0600 Subject: [PATCH 124/234] fix(post_ci_results.sh): improve CI result reporting and comment handling for Gitea --- scripts/post_ci_results.sh | 111 +++++++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 35 deletions(-) diff --git a/scripts/post_ci_results.sh b/scripts/post_ci_results.sh index 00d127f..3b4e75e 100755 --- a/scripts/post_ci_results.sh +++ b/scripts/post_ci_results.sh @@ -1,19 +1,11 @@ #!/bin/bash set -e -# Required environment variables: -# GITEA_TOKEN -# GITHUB_REPOSITORY -# GITHUB_EVENT_PATH -# GITHUB_SERVER_URL -# GITHUB_RUN_ID - if [ -z "$GITEA_TOKEN" ]; then echo "GITEA_TOKEN is not set. Skipping PR comment." exit 0 fi -# Extract PR number from the event JSON if [ -f "$GITHUB_EVENT_PATH" ]; then PR_NUMBER=$(jq -r '.pull_request.number' "$GITHUB_EVENT_PATH") else @@ -36,54 +28,103 @@ fi RUN_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" -# Clean up ANSI escape sequences (colors) from the output -# This makes the markdown output readable +if [[ "$GITHUB_SERVER_URL" == *"github.com"* ]] || [ -z "$GITHUB_SERVER_URL" ]; then + GITHUB_SERVER_URL="https://git.quad4.io" + RUN_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" +fi + sed -i 's/\x1b\[[0-9;]*[mK]//g' "$INPUT_FILE" if [ "$REPORT_TYPE" == "bench" ]; then HEADER="### Benchmark Summary (automated report)" - # Extract from summary start to the end, removing progress lines - # We look for the start of the benchmark summary table RESULTS=$(sed -n '/==================== BENCHMARK SUMMARY ====================/,$p' "$INPUT_FILE" | grep -v "Progress:") else - HEADER="### CI Status Report: $REPORT_TYPE" - # Check for failures if grep -qiE "FAILED|error|❌|exit status|failure" "$INPUT_FILE"; then - # Try to find a meaningful summary + HEADER="### ❌ CI Failure: $REPORT_TYPE" if grep -q "short test summary info" "$INPUT_FILE"; then RESULTS=$(sed -n '/=========================== short test summary info ============================/,$p' "$INPUT_FILE") - elif grep -q "Found [0-9]* error" "$INPUT_FILE"; then - # Ruff/Lint style errors + elif grep -qE "Found [0-9]* error" "$INPUT_FILE"; then RESULTS=$(grep -A 20 -B 2 -E "Found [0-9]* error|::error|❌" "$INPUT_FILE") else - # Extract lines that look like errors, with some context, limited to avoid too long comments RESULTS=$(grep -Ci 1 -E "FAILED|::error|❌|exit status|failure" "$INPUT_FILE" | tail -n 40) fi - HEADER="### ❌ CI Failure: $REPORT_TYPE" + if [ -z "$RESULTS" ]; then + RESULTS=$(tail -n 30 "$INPUT_FILE") + fi else + HEADER="### CI Status Report: $REPORT_TYPE" RESULTS="All checks passed! ✅" fi fi if [ -z "$RESULTS" ]; then - RESULTS="No detailed results found in $INPUT_FILE" + RESULTS="No detailed results found in $INPUT_FILE. Check full logs." fi -# Construct the message -# Note: Gitea/GitHub PR reviews use a JSON body where \n is a literal newline -BODY="${HEADER}\n\n" -BODY="${BODY}\`\`\`text\n${RESULTS}\n\`\`\`\n\n" -BODY="${BODY}🔗 [View Full Run](${RUN_URL})" +MARKER="" -# Use jq to construct the JSON payload safely -JSON_PAYLOAD=$(jq -n \ - --arg body "$BODY" \ - '{body: $body, event: "COMMENT"}') +NEW_SECTION=$(cat < Date: Sun, 4 Jan 2026 10:52:32 -0600 Subject: [PATCH 125/234] chore(build-test): update dependencies for Windows build and add i386 architecture support --- .gitea/workflows/build-test.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitea/workflows/build-test.yml b/.gitea/workflows/build-test.yml index 0a10bc0..b2f2c7d 100644 --- a/.gitea/workflows/build-test.yml +++ b/.gitea/workflows/build-test.yml @@ -38,8 +38,9 @@ jobs: - name: Install system dependencies run: | + sudo dpkg --add-architecture i386 sudo apt-get update - sudo apt-get install -y patchelf libopusfile0 ffmpeg espeak-ng wine nsis zip rpm flatpak flatpak-builder elfutils appstream appstream-util + sudo apt-get install -y wine32:i386 wine64 patchelf libopusfile0 ffmpeg espeak-ng nsis zip rpm flatpak flatpak-builder elfutils appstream appstream-util flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo # Install runtimes required for Flatpak build flatpak install --user -y flathub org.freedesktop.Platform//24.08 org.freedesktop.Sdk//24.08 org.electronjs.Electron2.BaseApp//24.08 @@ -70,6 +71,8 @@ jobs: run: task build-flatpak - name: Build Electron App (Windows EXE and NSIS) + env: + WINEDEBUG: -all run: pnpm run dist:windows - name: Build Electron App (ZIP) From 9b8086a8557c40798de880a58d40e903d153a1d8 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 11:06:57 -0600 Subject: [PATCH 126/234] chore(dependencies): update aiohttp to version 3.13.3, certifi to 2026.1.4, cx-freeze to 8.5.3, hypothesis to 6.148.11, and rns to 1.1.0 --- poetry.lock | 277 +++++++++++++++++++++++------------------------ pyproject.toml | 2 +- requirements.txt | 2 +- 3 files changed, 140 insertions(+), 141 deletions(-) diff --git a/poetry.lock b/poetry.lock index 78deee3..a85187a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -14,132 +14,132 @@ files = [ [[package]] name = "aiohttp" -version = "3.13.2" +version = "3.13.3" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "aiohttp-3.13.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2372b15a5f62ed37789a6b383ff7344fc5b9f243999b0cd9b629d8bc5f5b4155"}, - {file = "aiohttp-3.13.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e7f8659a48995edee7229522984bd1009c1213929c769c2daa80b40fe49a180c"}, - {file = "aiohttp-3.13.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:939ced4a7add92296b0ad38892ce62b98c619288a081170695c6babe4f50e636"}, - {file = "aiohttp-3.13.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6315fb6977f1d0dd41a107c527fee2ed5ab0550b7d885bc15fee20ccb17891da"}, - {file = "aiohttp-3.13.2-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6e7352512f763f760baaed2637055c49134fd1d35b37c2dedfac35bfe5cf8725"}, - {file = "aiohttp-3.13.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e09a0a06348a2dd73e7213353c90d709502d9786219f69b731f6caa0efeb46f5"}, - {file = "aiohttp-3.13.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a09a6d073fb5789456545bdee2474d14395792faa0527887f2f4ec1a486a59d3"}, - {file = "aiohttp-3.13.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b59d13c443f8e049d9e94099c7e412e34610f1f49be0f230ec656a10692a5802"}, - {file = "aiohttp-3.13.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:20db2d67985d71ca033443a1ba2001c4b5693fe09b0e29f6d9358a99d4d62a8a"}, - {file = "aiohttp-3.13.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:960c2fc686ba27b535f9fd2b52d87ecd7e4fd1cf877f6a5cba8afb5b4a8bd204"}, - {file = "aiohttp-3.13.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:6c00dbcf5f0d88796151e264a8eab23de2997c9303dd7c0bf622e23b24d3ce22"}, - {file = "aiohttp-3.13.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fed38a5edb7945f4d1bcabe2fcd05db4f6ec7e0e82560088b754f7e08d93772d"}, - {file = "aiohttp-3.13.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:b395bbca716c38bef3c764f187860e88c724b342c26275bc03e906142fc5964f"}, - {file = "aiohttp-3.13.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:204ffff2426c25dfda401ba08da85f9c59525cdc42bda26660463dd1cbcfec6f"}, - {file = "aiohttp-3.13.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:05c4dd3c48fb5f15db31f57eb35374cb0c09afdde532e7fb70a75aede0ed30f6"}, - {file = "aiohttp-3.13.2-cp310-cp310-win32.whl", hash = "sha256:e574a7d61cf10351d734bcddabbe15ede0eaa8a02070d85446875dc11189a251"}, - {file = "aiohttp-3.13.2-cp310-cp310-win_amd64.whl", hash = "sha256:364f55663085d658b8462a1c3f17b2b84a5c2e1ba858e1b79bff7b2e24ad1514"}, - {file = "aiohttp-3.13.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4647d02df098f6434bafd7f32ad14942f05a9caa06c7016fdcc816f343997dd0"}, - {file = "aiohttp-3.13.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e3403f24bcb9c3b29113611c3c16a2a447c3953ecf86b79775e7be06f7ae7ccb"}, - {file = "aiohttp-3.13.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:43dff14e35aba17e3d6d5ba628858fb8cb51e30f44724a2d2f0c75be492c55e9"}, - {file = "aiohttp-3.13.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e2a9ea08e8c58bb17655630198833109227dea914cd20be660f52215f6de5613"}, - {file = "aiohttp-3.13.2-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53b07472f235eb80e826ad038c9d106c2f653584753f3ddab907c83f49eedead"}, - {file = "aiohttp-3.13.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e736c93e9c274fce6419af4aac199984d866e55f8a4cec9114671d0ea9688780"}, - {file = "aiohttp-3.13.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ff5e771f5dcbc81c64898c597a434f7682f2259e0cd666932a913d53d1341d1a"}, - {file = "aiohttp-3.13.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3b6fb0c207cc661fa0bf8c66d8d9b657331ccc814f4719468af61034b478592"}, - {file = "aiohttp-3.13.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:97a0895a8e840ab3520e2288db7cace3a1981300d48babeb50e7425609e2e0ab"}, - {file = "aiohttp-3.13.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9e8f8afb552297aca127c90cb840e9a1d4bfd6a10d7d8f2d9176e1acc69bad30"}, - {file = "aiohttp-3.13.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ed2f9c7216e53c3df02264f25d824b079cc5914f9e2deba94155190ef648ee40"}, - {file = "aiohttp-3.13.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:99c5280a329d5fa18ef30fd10c793a190d996567667908bef8a7f81f8202b948"}, - {file = "aiohttp-3.13.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:2ca6ffef405fc9c09a746cb5d019c1672cd7f402542e379afc66b370833170cf"}, - {file = "aiohttp-3.13.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:47f438b1a28e926c37632bff3c44df7d27c9b57aaf4e34b1def3c07111fdb782"}, - {file = "aiohttp-3.13.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9acda8604a57bb60544e4646a4615c1866ee6c04a8edef9b8ee6fd1d8fa2ddc8"}, - {file = "aiohttp-3.13.2-cp311-cp311-win32.whl", hash = "sha256:868e195e39b24aaa930b063c08bb0c17924899c16c672a28a65afded9c46c6ec"}, - {file = "aiohttp-3.13.2-cp311-cp311-win_amd64.whl", hash = "sha256:7fd19df530c292542636c2a9a85854fab93474396a52f1695e799186bbd7f24c"}, - {file = "aiohttp-3.13.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b1e56bab2e12b2b9ed300218c351ee2a3d8c8fdab5b1ec6193e11a817767e47b"}, - {file = "aiohttp-3.13.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:364e25edaabd3d37b1db1f0cbcee8c73c9a3727bfa262b83e5e4cf3489a2a9dc"}, - {file = "aiohttp-3.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c5c94825f744694c4b8db20b71dba9a257cd2ba8e010a803042123f3a25d50d7"}, - {file = "aiohttp-3.13.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba2715d842ffa787be87cbfce150d5e88c87a98e0b62e0f5aa489169a393dbbb"}, - {file = "aiohttp-3.13.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:585542825c4bc662221fb257889e011a5aa00f1ae4d75d1d246a5225289183e3"}, - {file = "aiohttp-3.13.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:39d02cb6025fe1aabca329c5632f48c9532a3dabccd859e7e2f110668972331f"}, - {file = "aiohttp-3.13.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e67446b19e014d37342f7195f592a2a948141d15a312fe0e700c2fd2f03124f6"}, - {file = "aiohttp-3.13.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4356474ad6333e41ccefd39eae869ba15a6c5299c9c01dfdcfdd5c107be4363e"}, - {file = "aiohttp-3.13.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eeacf451c99b4525f700f078becff32c32ec327b10dcf31306a8a52d78166de7"}, - {file = "aiohttp-3.13.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8a9b889aeabd7a4e9af0b7f4ab5ad94d42e7ff679aaec6d0db21e3b639ad58d"}, - {file = "aiohttp-3.13.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:fa89cb11bc71a63b69568d5b8a25c3ca25b6d54c15f907ca1c130d72f320b76b"}, - {file = "aiohttp-3.13.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8aa7c807df234f693fed0ecd507192fc97692e61fee5702cdc11155d2e5cadc8"}, - {file = "aiohttp-3.13.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9eb3e33fdbe43f88c3c75fa608c25e7c47bbd80f48d012763cb67c47f39a7e16"}, - {file = "aiohttp-3.13.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9434bc0d80076138ea986833156c5a48c9c7a8abb0c96039ddbb4afc93184169"}, - {file = "aiohttp-3.13.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ff15c147b2ad66da1f2cbb0622313f2242d8e6e8f9b79b5206c84523a4473248"}, - {file = "aiohttp-3.13.2-cp312-cp312-win32.whl", hash = "sha256:27e569eb9d9e95dbd55c0fc3ec3a9335defbf1d8bc1d20171a49f3c4c607b93e"}, - {file = "aiohttp-3.13.2-cp312-cp312-win_amd64.whl", hash = "sha256:8709a0f05d59a71f33fd05c17fc11fcb8c30140506e13c2f5e8ee1b8964e1b45"}, - {file = "aiohttp-3.13.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7519bdc7dfc1940d201651b52bf5e03f5503bda45ad6eacf64dda98be5b2b6be"}, - {file = "aiohttp-3.13.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:088912a78b4d4f547a1f19c099d5a506df17eacec3c6f4375e2831ec1d995742"}, - {file = "aiohttp-3.13.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5276807b9de9092af38ed23ce120539ab0ac955547b38563a9ba4f5b07b95293"}, - {file = "aiohttp-3.13.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1237c1375eaef0db4dcd7c2559f42e8af7b87ea7d295b118c60c36a6e61cb811"}, - {file = "aiohttp-3.13.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:96581619c57419c3d7d78703d5b78c1e5e5fc0172d60f555bdebaced82ded19a"}, - {file = "aiohttp-3.13.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2713a95b47374169409d18103366de1050fe0ea73db358fc7a7acb2880422d4"}, - {file = "aiohttp-3.13.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:228a1cd556b3caca590e9511a89444925da87d35219a49ab5da0c36d2d943a6a"}, - {file = "aiohttp-3.13.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ac6cde5fba8d7d8c6ac963dbb0256a9854e9fafff52fbcc58fdf819357892c3e"}, - {file = "aiohttp-3.13.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f2bef8237544f4e42878c61cef4e2839fee6346dc60f5739f876a9c50be7fcdb"}, - {file = "aiohttp-3.13.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:16f15a4eac3bc2d76c45f7ebdd48a65d41b242eb6c31c2245463b40b34584ded"}, - {file = "aiohttp-3.13.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:bb7fb776645af5cc58ab804c58d7eba545a97e047254a52ce89c157b5af6cd0b"}, - {file = "aiohttp-3.13.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:e1b4951125ec10c70802f2cb09736c895861cd39fd9dcb35107b4dc8ae6220b8"}, - {file = "aiohttp-3.13.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:550bf765101ae721ee1d37d8095f47b1f220650f85fe1af37a90ce75bab89d04"}, - {file = "aiohttp-3.13.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fe91b87fc295973096251e2d25a811388e7d8adf3bd2b97ef6ae78bc4ac6c476"}, - {file = "aiohttp-3.13.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e0c8e31cfcc4592cb200160344b2fb6ae0f9e4effe06c644b5a125d4ae5ebe23"}, - {file = "aiohttp-3.13.2-cp313-cp313-win32.whl", hash = "sha256:0740f31a60848d6edb296a0df827473eede90c689b8f9f2a4cdde74889eb2254"}, - {file = "aiohttp-3.13.2-cp313-cp313-win_amd64.whl", hash = "sha256:a88d13e7ca367394908f8a276b89d04a3652044612b9a408a0bb22a5ed976a1a"}, - {file = "aiohttp-3.13.2-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:2475391c29230e063ef53a66669b7b691c9bfc3f1426a0f7bcdf1216bdbac38b"}, - {file = "aiohttp-3.13.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:f33c8748abef4d8717bb20e8fb1b3e07c6adacb7fd6beaae971a764cf5f30d61"}, - {file = "aiohttp-3.13.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ae32f24bbfb7dbb485a24b30b1149e2f200be94777232aeadba3eecece4d0aa4"}, - {file = "aiohttp-3.13.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d7f02042c1f009ffb70067326ef183a047425bb2ff3bc434ead4dd4a4a66a2b"}, - {file = "aiohttp-3.13.2-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:93655083005d71cd6c072cdab54c886e6570ad2c4592139c3fb967bfc19e4694"}, - {file = "aiohttp-3.13.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0db1e24b852f5f664cd728db140cf11ea0e82450471232a394b3d1a540b0f906"}, - {file = "aiohttp-3.13.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b009194665bcd128e23eaddef362e745601afa4641930848af4c8559e88f18f9"}, - {file = "aiohttp-3.13.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c038a8fdc8103cd51dbd986ecdce141473ffd9775a7a8057a6ed9c3653478011"}, - {file = "aiohttp-3.13.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66bac29b95a00db411cd758fea0e4b9bdba6d549dfe333f9a945430f5f2cc5a6"}, - {file = "aiohttp-3.13.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4ebf9cfc9ba24a74cf0718f04aac2a3bbe745902cc7c5ebc55c0f3b5777ef213"}, - {file = "aiohttp-3.13.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a4b88ebe35ce54205c7074f7302bd08a4cb83256a3e0870c72d6f68a3aaf8e49"}, - {file = "aiohttp-3.13.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:98c4fb90bb82b70a4ed79ca35f656f4281885be076f3f970ce315402b53099ae"}, - {file = "aiohttp-3.13.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:ec7534e63ae0f3759df3a1ed4fa6bc8f75082a924b590619c0dd2f76d7043caa"}, - {file = "aiohttp-3.13.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5b927cf9b935a13e33644cbed6c8c4b2d0f25b713d838743f8fe7191b33829c4"}, - {file = "aiohttp-3.13.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:88d6c017966a78c5265d996c19cdb79235be5e6412268d7e2ce7dee339471b7a"}, - {file = "aiohttp-3.13.2-cp314-cp314-win32.whl", hash = "sha256:f7c183e786e299b5d6c49fb43a769f8eb8e04a2726a2bd5887b98b5cc2d67940"}, - {file = "aiohttp-3.13.2-cp314-cp314-win_amd64.whl", hash = "sha256:fe242cd381e0fb65758faf5ad96c2e460df6ee5b2de1072fe97e4127927e00b4"}, - {file = "aiohttp-3.13.2-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:f10d9c0b0188fe85398c61147bbd2a657d616c876863bfeff43376e0e3134673"}, - {file = "aiohttp-3.13.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:e7c952aefdf2460f4ae55c5e9c3e80aa72f706a6317e06020f80e96253b1accd"}, - {file = "aiohttp-3.13.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c20423ce14771d98353d2e25e83591fa75dfa90a3c1848f3d7c68243b4fbded3"}, - {file = "aiohttp-3.13.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e96eb1a34396e9430c19d8338d2ec33015e4a87ef2b4449db94c22412e25ccdf"}, - {file = "aiohttp-3.13.2-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:23fb0783bc1a33640036465019d3bba069942616a6a2353c6907d7fe1ccdaf4e"}, - {file = "aiohttp-3.13.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e1a9bea6244a1d05a4e57c295d69e159a5c50d8ef16aa390948ee873478d9a5"}, - {file = "aiohttp-3.13.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0a3d54e822688b56e9f6b5816fb3de3a3a64660efac64e4c2dc435230ad23bad"}, - {file = "aiohttp-3.13.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7a653d872afe9f33497215745da7a943d1dc15b728a9c8da1c3ac423af35178e"}, - {file = "aiohttp-3.13.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:56d36e80d2003fa3fc0207fac644216d8532e9504a785ef9a8fd013f84a42c61"}, - {file = "aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:78cd586d8331fb8e241c2dd6b2f4061778cc69e150514b39a9e28dd050475661"}, - {file = "aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:20b10bbfbff766294fe99987f7bb3b74fdd2f1a2905f2562132641ad434dcf98"}, - {file = "aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9ec49dff7e2b3c85cdeaa412e9d438f0ecd71676fde61ec57027dd392f00c693"}, - {file = "aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:94f05348c4406450f9d73d38efb41d669ad6cd90c7ee194810d0eefbfa875a7a"}, - {file = "aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:fa4dcb605c6f82a80c7f95713c2b11c3b8e9893b3ebd2bc9bde93165ed6107be"}, - {file = "aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cf00e5db968c3f67eccd2778574cf64d8b27d95b237770aa32400bd7a1ca4f6c"}, - {file = "aiohttp-3.13.2-cp314-cp314t-win32.whl", hash = "sha256:d23b5fe492b0805a50d3371e8a728a9134d8de5447dce4c885f5587294750734"}, - {file = "aiohttp-3.13.2-cp314-cp314t-win_amd64.whl", hash = "sha256:ff0a7b0a82a7ab905cbda74006318d1b12e37c797eb1b0d4eb3e316cf47f658f"}, - {file = "aiohttp-3.13.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7fbdf5ad6084f1940ce88933de34b62358d0f4a0b6ec097362dcd3e5a65a4989"}, - {file = "aiohttp-3.13.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7c3a50345635a02db61792c85bb86daffac05330f6473d524f1a4e3ef9d0046d"}, - {file = "aiohttp-3.13.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0e87dff73f46e969af38ab3f7cb75316a7c944e2e574ff7c933bc01b10def7f5"}, - {file = "aiohttp-3.13.2-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2adebd4577724dcae085665f294cc57c8701ddd4d26140504db622b8d566d7aa"}, - {file = "aiohttp-3.13.2-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e036a3a645fe92309ec34b918394bb377950cbb43039a97edae6c08db64b23e2"}, - {file = "aiohttp-3.13.2-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:23ad365e30108c422d0b4428cf271156dd56790f6dd50d770b8e360e6c5ab2e6"}, - {file = "aiohttp-3.13.2-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1f9b2c2d4b9d958b1f9ae0c984ec1dd6b6689e15c75045be8ccb4011426268ca"}, - {file = "aiohttp-3.13.2-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a92cf4b9bea33e15ecbaa5c59921be0f23222608143d025c989924f7e3e0c07"}, - {file = "aiohttp-3.13.2-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:070599407f4954021509193404c4ac53153525a19531051661440644728ba9a7"}, - {file = "aiohttp-3.13.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:29562998ec66f988d49fb83c9b01694fa927186b781463f376c5845c121e4e0b"}, - {file = "aiohttp-3.13.2-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4dd3db9d0f4ebca1d887d76f7cdbcd1116ac0d05a9221b9dad82c64a62578c4d"}, - {file = "aiohttp-3.13.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d7bc4b7f9c4921eba72677cd9fedd2308f4a4ca3e12fab58935295ad9ea98700"}, - {file = "aiohttp-3.13.2-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:dacd50501cd017f8cccb328da0c90823511d70d24a323196826d923aad865901"}, - {file = "aiohttp-3.13.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:8b2f1414f6a1e0683f212ec80e813f4abef94c739fd090b66c9adf9d2a05feac"}, - {file = "aiohttp-3.13.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04c3971421576ed24c191f610052bcb2f059e395bc2489dd99e397f9bc466329"}, - {file = "aiohttp-3.13.2-cp39-cp39-win32.whl", hash = "sha256:9f377d0a924e5cc94dc620bc6366fc3e889586a7f18b748901cf016c916e2084"}, - {file = "aiohttp-3.13.2-cp39-cp39-win_amd64.whl", hash = "sha256:9c705601e16c03466cb72011bd1af55d68fa65b045356d8f96c216e5f6db0fa5"}, - {file = "aiohttp-3.13.2.tar.gz", hash = "sha256:40176a52c186aefef6eb3cad2cdd30cd06e3afbe88fe8ab2af9c0b90f228daca"}, + {file = "aiohttp-3.13.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7"}, + {file = "aiohttp-3.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821"}, + {file = "aiohttp-3.13.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845"}, + {file = "aiohttp-3.13.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af"}, + {file = "aiohttp-3.13.3-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940"}, + {file = "aiohttp-3.13.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160"}, + {file = "aiohttp-3.13.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7"}, + {file = "aiohttp-3.13.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455"}, + {file = "aiohttp-3.13.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279"}, + {file = "aiohttp-3.13.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e"}, + {file = "aiohttp-3.13.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d"}, + {file = "aiohttp-3.13.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808"}, + {file = "aiohttp-3.13.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40"}, + {file = "aiohttp-3.13.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29"}, + {file = "aiohttp-3.13.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11"}, + {file = "aiohttp-3.13.3-cp310-cp310-win32.whl", hash = "sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd"}, + {file = "aiohttp-3.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c"}, + {file = "aiohttp-3.13.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b"}, + {file = "aiohttp-3.13.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64"}, + {file = "aiohttp-3.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea"}, + {file = "aiohttp-3.13.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a"}, + {file = "aiohttp-3.13.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540"}, + {file = "aiohttp-3.13.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b"}, + {file = "aiohttp-3.13.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3"}, + {file = "aiohttp-3.13.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1"}, + {file = "aiohttp-3.13.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3"}, + {file = "aiohttp-3.13.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440"}, + {file = "aiohttp-3.13.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7"}, + {file = "aiohttp-3.13.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c"}, + {file = "aiohttp-3.13.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51"}, + {file = "aiohttp-3.13.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4"}, + {file = "aiohttp-3.13.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29"}, + {file = "aiohttp-3.13.3-cp311-cp311-win32.whl", hash = "sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239"}, + {file = "aiohttp-3.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f"}, + {file = "aiohttp-3.13.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c"}, + {file = "aiohttp-3.13.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168"}, + {file = "aiohttp-3.13.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d"}, + {file = "aiohttp-3.13.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29"}, + {file = "aiohttp-3.13.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3"}, + {file = "aiohttp-3.13.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d"}, + {file = "aiohttp-3.13.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463"}, + {file = "aiohttp-3.13.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc"}, + {file = "aiohttp-3.13.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf"}, + {file = "aiohttp-3.13.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033"}, + {file = "aiohttp-3.13.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f"}, + {file = "aiohttp-3.13.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679"}, + {file = "aiohttp-3.13.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423"}, + {file = "aiohttp-3.13.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce"}, + {file = "aiohttp-3.13.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a"}, + {file = "aiohttp-3.13.3-cp312-cp312-win32.whl", hash = "sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046"}, + {file = "aiohttp-3.13.3-cp312-cp312-win_amd64.whl", hash = "sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57"}, + {file = "aiohttp-3.13.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c"}, + {file = "aiohttp-3.13.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9"}, + {file = "aiohttp-3.13.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3"}, + {file = "aiohttp-3.13.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf"}, + {file = "aiohttp-3.13.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6"}, + {file = "aiohttp-3.13.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d"}, + {file = "aiohttp-3.13.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261"}, + {file = "aiohttp-3.13.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0"}, + {file = "aiohttp-3.13.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730"}, + {file = "aiohttp-3.13.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91"}, + {file = "aiohttp-3.13.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3"}, + {file = "aiohttp-3.13.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4"}, + {file = "aiohttp-3.13.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998"}, + {file = "aiohttp-3.13.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0"}, + {file = "aiohttp-3.13.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591"}, + {file = "aiohttp-3.13.3-cp313-cp313-win32.whl", hash = "sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf"}, + {file = "aiohttp-3.13.3-cp313-cp313-win_amd64.whl", hash = "sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e"}, + {file = "aiohttp-3.13.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808"}, + {file = "aiohttp-3.13.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415"}, + {file = "aiohttp-3.13.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f"}, + {file = "aiohttp-3.13.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6"}, + {file = "aiohttp-3.13.3-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687"}, + {file = "aiohttp-3.13.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26"}, + {file = "aiohttp-3.13.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a"}, + {file = "aiohttp-3.13.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1"}, + {file = "aiohttp-3.13.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25"}, + {file = "aiohttp-3.13.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603"}, + {file = "aiohttp-3.13.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a"}, + {file = "aiohttp-3.13.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926"}, + {file = "aiohttp-3.13.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba"}, + {file = "aiohttp-3.13.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c"}, + {file = "aiohttp-3.13.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43"}, + {file = "aiohttp-3.13.3-cp314-cp314-win32.whl", hash = "sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1"}, + {file = "aiohttp-3.13.3-cp314-cp314-win_amd64.whl", hash = "sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984"}, + {file = "aiohttp-3.13.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c"}, + {file = "aiohttp-3.13.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592"}, + {file = "aiohttp-3.13.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f"}, + {file = "aiohttp-3.13.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29"}, + {file = "aiohttp-3.13.3-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc"}, + {file = "aiohttp-3.13.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2"}, + {file = "aiohttp-3.13.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587"}, + {file = "aiohttp-3.13.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8"}, + {file = "aiohttp-3.13.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632"}, + {file = "aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64"}, + {file = "aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0"}, + {file = "aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56"}, + {file = "aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72"}, + {file = "aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df"}, + {file = "aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa"}, + {file = "aiohttp-3.13.3-cp314-cp314t-win32.whl", hash = "sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767"}, + {file = "aiohttp-3.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344"}, + {file = "aiohttp-3.13.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e"}, + {file = "aiohttp-3.13.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7"}, + {file = "aiohttp-3.13.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02"}, + {file = "aiohttp-3.13.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43"}, + {file = "aiohttp-3.13.3-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6"}, + {file = "aiohttp-3.13.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce"}, + {file = "aiohttp-3.13.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80"}, + {file = "aiohttp-3.13.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a"}, + {file = "aiohttp-3.13.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6"}, + {file = "aiohttp-3.13.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558"}, + {file = "aiohttp-3.13.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7"}, + {file = "aiohttp-3.13.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877"}, + {file = "aiohttp-3.13.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3"}, + {file = "aiohttp-3.13.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704"}, + {file = "aiohttp-3.13.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f"}, + {file = "aiohttp-3.13.3-cp39-cp39-win32.whl", hash = "sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1"}, + {file = "aiohttp-3.13.3-cp39-cp39-win_amd64.whl", hash = "sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538"}, + {file = "aiohttp-3.13.3.tar.gz", hash = "sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88"}, ] [package.dependencies] @@ -152,7 +152,7 @@ propcache = ">=0.2.0" yarl = ">=1.17.0,<2.0" [package.extras] -speedups = ["Brotli ; platform_python_implementation == \"CPython\"", "aiodns (>=3.3.0)", "backports.zstd ; platform_python_implementation == \"CPython\" and python_version < \"3.14\"", "brotlicffi ; platform_python_implementation != \"CPython\""] +speedups = ["Brotli (>=1.2) ; platform_python_implementation == \"CPython\"", "aiodns (>=3.3.0)", "backports.zstd ; platform_python_implementation == \"CPython\" and python_version < \"3.14\"", "brotlicffi (>=1.2) ; platform_python_implementation != \"CPython\""] [[package]] name = "aiohttp-session" @@ -356,14 +356,14 @@ files = [ [[package]] name = "certifi" -version = "2025.11.12" +version = "2026.1.4" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" groups = ["main"] files = [ - {file = "certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b"}, - {file = "certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316"}, + {file = "certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c"}, + {file = "certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120"}, ] [[package]] @@ -783,14 +783,14 @@ test-randomorder = ["pytest-randomly"] [[package]] name = "cx-freeze" -version = "8.5.2" +version = "8.5.3" description = "Create standalone executables from Python scripts" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "cx_freeze-8.5.2-py3-none-any.whl", hash = "sha256:b12811adbc9546e7a5d61fce27f78e13142ffd50cde5e8c92be36655f06c9900"}, - {file = "cx_freeze-8.5.2.tar.gz", hash = "sha256:e3c72bd5fae1e49f67a4cc747526c8ef48182bf2f8d90e85c840cc4bbba4d1c5"}, + {file = "cx_freeze-8.5.3-py3-none-any.whl", hash = "sha256:ceafd2ceaf38a93bb562d5d97028b20d12456d578fc47c3545827a3656f81437"}, + {file = "cx_freeze-8.5.3.tar.gz", hash = "sha256:772e41ada72467365342d521f42f124663db51882f6ba495bf88dec399dc6511"}, ] [package.dependencies] @@ -804,9 +804,9 @@ python-msilib = {version = ">=0.4.1", markers = "sys_platform == \"win32\" and p setuptools = ">=78.1.1,<81" [package.extras] -dev = ["bump-my-version (==1.2.5)", "pre-commit (==4.5.1)"] -doc = ["furo (==2025.9.25) ; python_version >= \"3.11\"", "myst-parser (==4.0.1) ; python_version >= \"3.11\"", "sphinx (==8.2.3) ; python_version >= \"3.11\"", "sphinx-issues (==5.0.1) ; python_version >= \"3.11\"", "sphinx-new-tab-link (==0.8.1) ; python_version >= \"3.11\"", "sphinx-tabs (==3.4.7) ; python_version >= \"3.11\""] -tests = ["coverage (==7.13.0)", "filelock (>=3.20.1)", "pluggy (==1.6.0)", "pytest (==9.0.2)", "pytest-mock (==3.15.1)", "pytest-timeout (==2.4.0)", "pytest-xdist (==3.8.0)"] +dev = ["bump-my-version (==1.2.6)", "pre-commit (==4.5.1)"] +doc = ["furo (==2025.12.19) ; python_version >= \"3.11\"", "myst-parser (==4.0.1) ; python_version >= \"3.11\"", "sphinx (==8.2.3) ; python_version >= \"3.11\"", "sphinx-issues (==5.0.1) ; python_version >= \"3.11\"", "sphinx-new-tab-link (==0.8.1) ; python_version >= \"3.11\"", "sphinx-tabs (==3.4.7) ; python_version >= \"3.11\""] +tests = ["coverage (==7.13.1)", "filelock (>=3.20.1)", "pluggy (==1.6.0)", "pytest (==9.0.2)", "pytest-mock (==3.15.1)", "pytest-timeout (==2.4.0)", "pytest-xdist (==3.8.0)"] [[package]] name = "dmgbuild" @@ -1076,14 +1076,14 @@ files = [ [[package]] name = "hypothesis" -version = "6.148.9" +version = "6.148.11" description = "The property-based testing library for Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "hypothesis-6.148.9-py3-none-any.whl", hash = "sha256:c514fcca90eded0e6b56d4df4bc41db935cb4635a9fe3ec9be21d09243ca983b"}, - {file = "hypothesis-6.148.9.tar.gz", hash = "sha256:6ec0696ed2fff8c514d61b6f1ca2cd1cb00c948ffd18cab1877c941c0ddb2839"}, + {file = "hypothesis-6.148.11-py3-none-any.whl", hash = "sha256:397b3fd13d0906cf5ece76f5da340a0fbb07bd18ab61ac41a7982ceb080312f0"}, + {file = "hypothesis-6.148.11.tar.gz", hash = "sha256:4f3c38030d0f0b38c8b7153d6907892e6fcac9ecb0410e627d6af2cea677f92c"}, ] [package.dependencies] @@ -1933,15 +1933,14 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "rns" -version = "1.0.4" +version = "1.1.0" description = "Self-configuring, encrypted and resilient mesh networking stack for LoRa, packet radio, WiFi and everything in between" optional = false python-versions = ">=3.7" groups = ["main"] files = [ - {file = "rns-1.0.4-1-py3-none-any.whl", hash = "sha256:f1804f8b07a8b8e1c1b61889f929fdb5cfbd57f4c354108c417135f0d67c5ef6"}, - {file = "rns-1.0.4-py3-none-any.whl", hash = "sha256:7a2b7893410833b42c0fa7f9a9e3369cebb085cdd26bd83f3031fa6c1051653c"}, - {file = "rns-1.0.4.tar.gz", hash = "sha256:e70667a767fe523bab8e7ea0627447258c4e6763b7756fbba50c6556dbb84399"}, + {file = "rns-1.1.0-py3-none-any.whl", hash = "sha256:180b8baec2ec7d21abe2cec25ff763e70b2129c012fb02fc23c2fd654f94c1f5"}, + {file = "rns-1.1.0.tar.gz", hash = "sha256:deec795c3d167c412d23ea76836103b1acf12dbdbd27f0a0d4d8b590c503d291"}, ] [package.dependencies] @@ -2255,4 +2254,4 @@ propcache = ">=0.2.1" [metadata] lock-version = "2.1" python-versions = ">=3.11" -content-hash = "c67b3ada4344775b47db71c46d8c43724f0631728f5b3922b48ef8859a82c76e" +content-hash = "4dda950e0586a558174bb05ed43a8d3feaaf2cf6acb056bafcb27e4b80e975f3" diff --git a/pyproject.toml b/pyproject.toml index ded16ce..a95e882 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,7 @@ dependencies = [ "aiohttp>=3.13.2", "lxmf>=0.9.3", "psutil>=7.1.3", - "rns>=1.0.4", + "rns>=1.1.0", "websockets>=15.0.1", "bcrypt>=5.0.0,<6.0.0", "aiohttp-session>=2.12.1,<3.0.0", diff --git a/requirements.txt b/requirements.txt index 455f417..425845e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ cx_freeze>=7.0.0 lxmf>=0.9.3 lxst>=0.4.4 psutil>=7.1.3 -rns>=1.0.4 +rns>=1.1.0 websockets>=14.2 requests>=2.32.5 hypothesis>=6.0.0 From 306557c473a5a9b8030066a87d255bfb77ad70e2 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 11:27:05 -0600 Subject: [PATCH 127/234] chore(ci): remove post CI result posting steps and delete related script --- .gitea/workflows/bench.yml | 6 -- .gitea/workflows/build.yml | 5 +- .gitea/workflows/ci.yml | 24 ------- .gitea/workflows/tests.yml | 6 -- scripts/post_ci_results.sh | 130 ------------------------------------- 5 files changed, 4 insertions(+), 167 deletions(-) delete mode 100755 scripts/post_ci_results.sh diff --git a/.gitea/workflows/bench.yml b/.gitea/workflows/bench.yml index 27e6379..a441316 100644 --- a/.gitea/workflows/bench.yml +++ b/.gitea/workflows/bench.yml @@ -47,9 +47,3 @@ jobs: run: | set -o pipefail task test-integrity 2>&1 | tee -a bench_results.txt - - - name: Post Results to PR - if: always() && github.event_name == 'pull_request' - env: - GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} - run: bash scripts/post_ci_results.sh bench bench_results.txt diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index 3bb3e95..4bb1615 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -71,8 +71,9 @@ jobs: - name: Install system dependencies run: | + sudo dpkg --add-architecture i386 sudo apt-get update - sudo apt-get install -y patchelf libopusfile0 ffmpeg espeak-ng wine nsis zip rpm flatpak flatpak-builder elfutils + sudo apt-get install -y wine32:i386 wine64 patchelf libopusfile0 ffmpeg espeak-ng nsis zip rpm flatpak flatpak-builder elfutils flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo - name: Setup Task @@ -101,6 +102,8 @@ jobs: run: task build-flatpak - name: Build Electron App (Windows EXE and NSIS) + env: + WINEDEBUG: -all run: pnpm run dist:windows - name: Build Electron App (ZIP) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index dc30ade..5b40e00 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -37,12 +37,6 @@ jobs: set -o pipefail task lint 2>&1 | tee lint_results.txt - - name: Post Results to PR - if: always() && github.event_name == 'pull_request' - env: - GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} - run: bash scripts/post_ci_results.sh "Linting" lint_results.txt - build-frontend: runs-on: ubuntu-latest steps: @@ -71,12 +65,6 @@ jobs: env: VITE_APP_VERSION: ${{ steps.version.outputs.version }} - - name: Post Results to PR - if: always() && github.event_name == 'pull_request' - env: - GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} - run: bash scripts/post_ci_results.sh "Frontend Build" build_results.txt - test-backend: runs-on: ubuntu-latest steps: @@ -95,12 +83,6 @@ jobs: set -o pipefail task compile 2>&1 | tee compile_results.txt - - name: Post Results to PR - if: always() && github.event_name == 'pull_request' - env: - GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} - run: bash scripts/post_ci_results.sh "Backend Compilation" compile_results.txt - test-lang: runs-on: ubuntu-latest steps: @@ -127,9 +109,3 @@ jobs: run: | set -o pipefail task test-lang 2>&1 | tee lang_results.txt - - - name: Post Results to PR - if: always() && github.event_name == 'pull_request' - env: - GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} - run: bash scripts/post_ci_results.sh "Language Tests" lang_results.txt diff --git a/.gitea/workflows/tests.yml b/.gitea/workflows/tests.yml index 48c3be7..9970e17 100644 --- a/.gitea/workflows/tests.yml +++ b/.gitea/workflows/tests.yml @@ -40,9 +40,3 @@ jobs: run: | set -o pipefail task test 2>&1 | tee test_results.txt - - - name: Post Results to PR - if: always() && github.event_name == 'pull_request' - env: - GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} - run: bash scripts/post_ci_results.sh "Tests" test_results.txt diff --git a/scripts/post_ci_results.sh b/scripts/post_ci_results.sh deleted file mode 100755 index 3b4e75e..0000000 --- a/scripts/post_ci_results.sh +++ /dev/null @@ -1,130 +0,0 @@ -#!/bin/bash -set -e - -if [ -z "$GITEA_TOKEN" ]; then - echo "GITEA_TOKEN is not set. Skipping PR comment." - exit 0 -fi - -if [ -f "$GITHUB_EVENT_PATH" ]; then - PR_NUMBER=$(jq -r '.pull_request.number' "$GITHUB_EVENT_PATH") -else - echo "GITHUB_EVENT_PATH not found. Skipping." - exit 0 -fi - -if [ "$PR_NUMBER" == "null" ] || [ -z "$PR_NUMBER" ]; then - echo "Not a pull request. Skipping." - exit 0 -fi - -REPORT_TYPE=$1 -INPUT_FILE=${2:-ci_results.txt} - -if [ ! -f "$INPUT_FILE" ]; then - echo "$INPUT_FILE not found. Nothing to post." - exit 0 -fi - -RUN_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" - -if [[ "$GITHUB_SERVER_URL" == *"github.com"* ]] || [ -z "$GITHUB_SERVER_URL" ]; then - GITHUB_SERVER_URL="https://git.quad4.io" - RUN_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" -fi - -sed -i 's/\x1b\[[0-9;]*[mK]//g' "$INPUT_FILE" - -if [ "$REPORT_TYPE" == "bench" ]; then - HEADER="### Benchmark Summary (automated report)" - RESULTS=$(sed -n '/==================== BENCHMARK SUMMARY ====================/,$p' "$INPUT_FILE" | grep -v "Progress:") -else - if grep -qiE "FAILED|error|❌|exit status|failure" "$INPUT_FILE"; then - HEADER="### ❌ CI Failure: $REPORT_TYPE" - if grep -q "short test summary info" "$INPUT_FILE"; then - RESULTS=$(sed -n '/=========================== short test summary info ============================/,$p' "$INPUT_FILE") - elif grep -qE "Found [0-9]* error" "$INPUT_FILE"; then - RESULTS=$(grep -A 20 -B 2 -E "Found [0-9]* error|::error|❌" "$INPUT_FILE") - else - RESULTS=$(grep -Ci 1 -E "FAILED|::error|❌|exit status|failure" "$INPUT_FILE" | tail -n 40) - fi - if [ -z "$RESULTS" ]; then - RESULTS=$(tail -n 30 "$INPUT_FILE") - fi - else - HEADER="### CI Status Report: $REPORT_TYPE" - RESULTS="All checks passed! ✅" - fi -fi - -if [ -z "$RESULTS" ]; then - RESULTS="No detailed results found in $INPUT_FILE. Check full logs." -fi - -MARKER="" - -NEW_SECTION=$(cat < Date: Sun, 4 Jan 2026 12:40:19 -0600 Subject: [PATCH 128/234] feat(rnpath): implement the blackhole, RNPathHandler and integrate path management APIs --- meshchatx/meshchat.py | 188 +++++++++++++++++- meshchatx/src/backend/config_manager.py | 7 + meshchatx/src/backend/identity_context.py | 4 + .../src/backend/persistent_log_handler.py | 53 ++++- meshchatx/src/backend/rnpath_handler.py | 62 ++++++ meshchatx/src/backend/rnstatus_handler.py | 17 ++ 6 files changed, 322 insertions(+), 9 deletions(-) create mode 100644 meshchatx/src/backend/rnpath_handler.py diff --git a/meshchatx/meshchat.py b/meshchatx/meshchat.py index 542c25b..1ba14c2 100644 --- a/meshchatx/meshchat.py +++ b/meshchatx/meshchat.py @@ -373,6 +373,15 @@ class ReticulumMeshChat: if self.current_context: self.current_context.rnstatus_handler = value + @property + def rnpath_handler(self): + return self.current_context.rnpath_handler if self.current_context else None + + @rnpath_handler.setter + def rnpath_handler(self, value): + if self.current_context: + self.current_context.rnpath_handler = value + @property def rnprobe_handler(self): return self.current_context.rnprobe_handler if self.current_context else None @@ -3976,6 +3985,11 @@ class ReticulumMeshChat: async def telephone_switch_audio_profile(request): profile_id = request.match_info.get("profile_id") try: + if self.telephone_manager.telephone is None: + return web.json_response( + {"message": "Telephone not initialized"}, status=400 + ) + await asyncio.to_thread( self.telephone_manager.telephone.switch_profile, int(profile_id), @@ -5522,6 +5536,75 @@ class ReticulumMeshChat: status=500, ) + @routes.get("/api/v1/rnpath/table") + async def rnpath_table(request): + max_hops = request.query.get("max_hops") + if max_hops: + max_hops = int(max_hops) + try: + table = self.rnpath_handler.get_path_table(max_hops=max_hops) + return web.json_response({"table": table}) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + + @routes.get("/api/v1/rnpath/rates") + async def rnpath_rates(request): + try: + rates = self.rnpath_handler.get_rate_table() + return web.json_response({"rates": rates}) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + + @routes.post("/api/v1/rnpath/drop") + async def rnpath_drop(request): + data = await request.json() + destination_hash = data.get("destination_hash") + if not destination_hash: + return web.json_response( + {"message": "destination_hash is required"}, status=400 + ) + try: + success = self.rnpath_handler.drop_path(destination_hash) + return web.json_response({"success": success}) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + + @routes.post("/api/v1/rnpath/drop-via") + async def rnpath_drop_via(request): + data = await request.json() + transport_instance_hash = data.get("transport_instance_hash") + if not transport_instance_hash: + return web.json_response( + {"message": "transport_instance_hash is required"}, status=400 + ) + try: + success = self.rnpath_handler.drop_all_via(transport_instance_hash) + return web.json_response({"success": success}) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + + @routes.post("/api/v1/rnpath/drop-queues") + async def rnpath_drop_queues(request): + try: + self.rnpath_handler.drop_announce_queues() + return web.json_response({"success": True}) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + + @routes.post("/api/v1/rnpath/request") + async def rnpath_request(request): + data = await request.json() + destination_hash = data.get("destination_hash") + if not destination_hash: + return web.json_response( + {"message": "destination_hash is required"}, status=400 + ) + try: + success = self.rnpath_handler.request_path(destination_hash) + return web.json_response({"success": success}) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + @routes.post("/api/v1/rnprobe") async def rnprobe(request): data = await request.json() @@ -6461,12 +6544,46 @@ class ReticulumMeshChat: try: self.database.misc.add_blocked_destination(destination_hash) - # drop any existing paths to this destination - try: - if hasattr(self, "reticulum") and self.reticulum: - self.reticulum.drop_path(bytes.fromhex(destination_hash)) - except Exception as e: - print(f"Failed to drop path for blocked destination: {e}") + + # add to Reticulum blackhole if available and enabled + if self.config.blackhole_integration_enabled.get(): + try: + if hasattr(self, "reticulum") and self.reticulum: + # Try to resolve identity hash from destination hash + identity_hash = None + announce = self.database.announces.get_announce_by_hash( + destination_hash + ) + if announce and announce.get("identity_hash"): + identity_hash = announce["identity_hash"] + + # Use resolved identity hash or fallback to destination hash + target_hash = identity_hash or destination_hash + dest_bytes = bytes.fromhex(target_hash) + + # Reticulum 1.1.0+ + if hasattr(self.reticulum, "blackhole_identity"): + reason = ( + f"Blocked in MeshChatX (from {destination_hash})" + if identity_hash + else "Blocked in MeshChatX" + ) + self.reticulum.blackhole_identity( + dest_bytes, reason=reason + ) + else: + # fallback to dropping path + self.reticulum.drop_path(dest_bytes) + except Exception as e: + print(f"Failed to blackhole identity in Reticulum: {e}") + else: + # fallback to just dropping path if integration disabled + try: + if hasattr(self, "reticulum") and self.reticulum: + self.reticulum.drop_path(bytes.fromhex(destination_hash)) + except Exception as e: + print(f"Failed to drop path for blocked destination: {e}") + return web.json_response({"message": "ok"}) except Exception: return web.json_response( @@ -6486,10 +6603,58 @@ class ReticulumMeshChat: try: self.database.misc.delete_blocked_destination(destination_hash) + + # remove from Reticulum blackhole if available and enabled + if self.config.blackhole_integration_enabled.get(): + try: + if hasattr(self, "reticulum") and self.reticulum: + # Try to resolve identity hash from destination hash + identity_hash = None + announce = self.database.announces.get_announce_by_hash( + destination_hash + ) + if announce and announce.get("identity_hash"): + identity_hash = announce["identity_hash"] + + # Use resolved identity hash or fallback to destination hash + target_hash = identity_hash or destination_hash + dest_bytes = bytes.fromhex(target_hash) + + if hasattr(self.reticulum, "unblackhole_identity"): + self.reticulum.unblackhole_identity(dest_bytes) + except Exception as e: + print(f"Failed to unblackhole identity in Reticulum: {e}") + return web.json_response({"message": "ok"}) except Exception as e: return web.json_response({"error": str(e)}, status=500) + @routes.get("/api/v1/reticulum/blackhole") + async def reticulum_blackhole_get(request): + if not hasattr(self, "reticulum") or not self.reticulum: + return web.json_response( + {"error": "Reticulum not initialized"}, status=503 + ) + + try: + if hasattr(self.reticulum, "get_blackholed_identities"): + identities = self.reticulum.get_blackholed_identities() + # Convert bytes keys to hex strings + formatted = {} + for h, info in identities.items(): + formatted[h.hex()] = { + "source": info.get("source", b"").hex() + if info.get("source") + else None, + "until": info.get("until"), + "reason": info.get("reason"), + } + return web.json_response({"blackholed_identities": formatted}) + else: + return web.json_response({"blackholed_identities": {}}) + except Exception as e: + return web.json_response({"error": str(e)}, status=500) + # get spam keywords @routes.get("/api/v1/spam-keywords") async def spam_keywords_get(request): @@ -6871,8 +7036,10 @@ class ReticulumMeshChat: # Add security headers to all responses response.headers["X-Content-Type-Options"] = "nosniff" - # Allow framing for docs - if request.path.startswith("/reticulum-docs/"): + # Allow framing for docs and rnode flasher + if request.path.startswith("/reticulum-docs/") or request.path.startswith( + "/rnode-flasher/" + ): response.headers["X-Frame-Options"] = "SAMEORIGIN" else: response.headers["X-Frame-Options"] = "DENY" @@ -7354,6 +7521,10 @@ class ReticulumMeshChat: except Exception as e: print(f"Failed to update GPU disable flag: {e}") + if "blackhole_integration_enabled" in data: + value = self._parse_bool(data["blackhole_integration_enabled"]) + self.config.blackhole_integration_enabled.set(value) + # update voicemail settings if "voicemail_enabled" in data: self.config.voicemail_enabled.set( @@ -8234,6 +8405,7 @@ class ReticulumMeshChat: "libretranslate_url": ctx.config.libretranslate_url.get(), "desktop_open_calls_in_separate_window": ctx.config.desktop_open_calls_in_separate_window.get(), "desktop_hardware_acceleration_enabled": ctx.config.desktop_hardware_acceleration_enabled.get(), + "blackhole_integration_enabled": ctx.config.blackhole_integration_enabled.get(), } # try and get a name for the provided identity hash diff --git a/meshchatx/src/backend/config_manager.py b/meshchatx/src/backend/config_manager.py index 660336c..7163af3 100644 --- a/meshchatx/src/backend/config_manager.py +++ b/meshchatx/src/backend/config_manager.py @@ -236,6 +236,13 @@ class ConfigManager: ) self.message_font_size = self.IntConfig(self, "message_font_size", 14) + # blackhole integration config + self.blackhole_integration_enabled = self.BoolConfig( + self, + "blackhole_integration_enabled", + True, + ) + def get(self, key: str, default_value=None) -> str | None: return self.db.config.get(key, default_value) diff --git a/meshchatx/src/backend/identity_context.py b/meshchatx/src/backend/identity_context.py index 3deb7e6..2d3c2d5 100644 --- a/meshchatx/src/backend/identity_context.py +++ b/meshchatx/src/backend/identity_context.py @@ -17,6 +17,7 @@ from meshchatx.src.backend.voicemail_manager import VoicemailManager from meshchatx.src.backend.ringtone_manager import RingtoneManager from meshchatx.src.backend.rncp_handler import RNCPHandler from meshchatx.src.backend.rnstatus_handler import RNStatusHandler +from meshchatx.src.backend.rnpath_handler import RNPathHandler from meshchatx.src.backend.rnprobe_handler import RNProbeHandler from meshchatx.src.backend.translator_handler import TranslatorHandler from meshchatx.src.backend.forwarding_manager import ForwardingManager @@ -195,6 +196,9 @@ class IdentityContext: self.rnstatus_handler = RNStatusHandler( reticulum_instance=getattr(self.app, "reticulum", None), ) + self.rnpath_handler = RNPathHandler( + reticulum_instance=getattr(self.app, "reticulum", None), + ) self.rnprobe_handler = RNProbeHandler( reticulum_instance=getattr(self.app, "reticulum", None), identity=self.identity, diff --git a/meshchatx/src/backend/persistent_log_handler.py b/meshchatx/src/backend/persistent_log_handler.py index 76a0e55..61d3842 100644 --- a/meshchatx/src/backend/persistent_log_handler.py +++ b/meshchatx/src/backend/persistent_log_handler.py @@ -1,5 +1,6 @@ import collections import logging +import re import threading import time from datetime import UTC, datetime @@ -22,6 +23,10 @@ class PersistentLogHandler(logging.Handler): self.message_counts = collections.defaultdict(int) self.last_reset_time = time.time() + # UA and IP tracking + self.known_ips = set() + self.known_uas = set() + def set_database(self, database): with self.lock: self.database = database @@ -54,8 +59,54 @@ class PersistentLogHandler(logging.Handler): except Exception: self.handleError(record) + def _detect_access_anomaly(self, message): + """Detect anomalies in aiohttp access logs.""" + # Regex to extract IP and User-Agent from aiohttp access log + # Format: IP [date] "GET ..." status size "referer" "User-Agent" + match = re.search( + r"^([\d\.\:]+) .* \"[^\"]+\" \d+ \d+ \"[^\"]*\" \"([^\"]+)\"", message + ) + if match: + ip = match.group(1) + ua = match.group(2) + + with self.lock: + is_anomaly = False + anomaly_type = None + + # Detect if this is a different UA or IP from what we've seen recently + if len(self.known_ips) > 0 and ip not in self.known_ips: + is_anomaly = True + anomaly_type = "multi_ip" + + if len(self.known_uas) > 0 and ua not in self.known_uas: + is_anomaly = True + if anomaly_type: + anomaly_type = "multi_ip_ua" + else: + anomaly_type = "multi_ua" + + self.known_ips.add(ip) + self.known_uas.add(ua) + + # Cap the tracking sets to prevent memory growth + if len(self.known_ips) > 100: + self.known_ips.clear() + if len(self.known_uas) > 100: + self.known_uas.clear() + + return is_anomaly, anomaly_type + + return False, None + def _detect_anomaly(self, record, message, timestamp): - # Only detect anomalies for WARNING level and above + # 1. Access anomaly detection (UA/IP) - checked for all levels of aiohttp.access + if record.name == "aiohttp.access": + is_acc_anomaly, acc_type = self._detect_access_anomaly(message) + if is_acc_anomaly: + return True, acc_type + + # Only detect other anomalies for WARNING level and above if record.levelno < logging.WARNING: return False, None diff --git a/meshchatx/src/backend/rnpath_handler.py b/meshchatx/src/backend/rnpath_handler.py new file mode 100644 index 0000000..92b54d5 --- /dev/null +++ b/meshchatx/src/backend/rnpath_handler.py @@ -0,0 +1,62 @@ +import RNS + + +class RNPathHandler: + def __init__(self, reticulum_instance: RNS.Reticulum): + self.reticulum = reticulum_instance + + def get_path_table(self, max_hops: int = None): + table = self.reticulum.get_path_table(max_hops=max_hops) + formatted_table = [] + for entry in table: + formatted_table.append( + { + "hash": entry["hash"].hex(), + "hops": entry["hops"], + "via": entry["via"].hex(), + "interface": entry["interface"], + "expires": entry["expires"], + } + ) + return sorted(formatted_table, key=lambda e: (e["interface"], e["hops"])) + + def get_rate_table(self): + table = self.reticulum.get_rate_table() + formatted_table = [] + for entry in table: + formatted_table.append( + { + "hash": entry["hash"].hex(), + "last": entry["last"], + "timestamps": entry["timestamps"], + "rate_violations": entry["rate_violations"], + "blocked_until": entry["blocked_until"], + } + ) + return sorted(formatted_table, key=lambda e: e["last"]) + + def drop_path(self, destination_hash: str) -> bool: + try: + dest_bytes = bytes.fromhex(destination_hash) + return self.reticulum.drop_path(dest_bytes) + except Exception: + return False + + def drop_all_via(self, transport_instance_hash: str) -> bool: + try: + ti_bytes = bytes.fromhex(transport_instance_hash) + return self.reticulum.drop_all_via(ti_bytes) + except Exception: + return False + + def drop_announce_queues(self): + self.reticulum.drop_announce_queues() + return True + + def request_path(self, destination_hash: str): + try: + dest_bytes = bytes.fromhex(destination_hash) + RNS.Transport.request_path(dest_bytes) + return True + except Exception: + return False diff --git a/meshchatx/src/backend/rnstatus_handler.py b/meshchatx/src/backend/rnstatus_handler.py index 58c65b3..50aa86c 100644 --- a/meshchatx/src/backend/rnstatus_handler.py +++ b/meshchatx/src/backend/rnstatus_handler.py @@ -1,5 +1,6 @@ import time from typing import Any +import RNS def size_str(num, suffix="B"): @@ -53,6 +54,19 @@ class RNStatusHandler: "link_count": link_count, } + blackhole_enabled = False + blackhole_sources = [] + blackhole_count = 0 + try: + blackhole_enabled = RNS.Reticulum.publish_blackhole_enabled() + blackhole_sources = [s.hex() for s in RNS.Reticulum.blackhole_sources()] + + # Get count of blackholed identities + if self.reticulum and hasattr(self.reticulum, "get_blackholed_identities"): + blackhole_count = len(self.reticulum.get_blackholed_identities()) + except Exception: + pass + interfaces = stats.get("interfaces", []) if sorting and isinstance(sorting, str): @@ -211,4 +225,7 @@ class RNStatusHandler: "interfaces": formatted_interfaces, "link_count": link_count, "timestamp": time.time(), + "blackhole_enabled": blackhole_enabled, + "blackhole_sources": blackhole_sources, + "blackhole_count": blackhole_count, } From f270160c6cf0bf203a2bbcb3e49980e6d30bd6c8 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 12:40:32 -0600 Subject: [PATCH 129/234] feat(theme): add light and dark themes to Vuetify configuration and introduce new RNPath route --- meshchatx/src/frontend/main.js | 39 +++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/meshchatx/src/frontend/main.js b/meshchatx/src/frontend/main.js index 0fd51c7..37f866f 100644 --- a/meshchatx/src/frontend/main.js +++ b/meshchatx/src/frontend/main.js @@ -27,7 +27,39 @@ const i18n = createI18n({ // init vuetify import { createVuetify } from "vuetify"; -const vuetify = createVuetify(); +const vuetify = createVuetify({ + theme: { + defaultTheme: "light", + themes: { + light: { + dark: false, + colors: { + background: "#f8fafc", + surface: "#ffffff", + primary: "#2563eb", + secondary: "#475569", + error: "#dc2626", + info: "#0284c7", + success: "#16a34a", + warning: "#f97316", + }, + }, + dark: { + dark: true, + colors: { + background: "#09090b", + surface: "#18181b", + primary: "#60a5fa", + secondary: "#94a3b8", + error: "#f87171", + info: "#38bdf8", + success: "#34d399", + warning: "#fb923c", + }, + }, + }, + }, +}); // provide axios globally window.axios = axios; @@ -142,6 +174,11 @@ const router = createRouter({ path: "/rnstatus", component: defineAsyncComponent(() => import("./components/rnstatus/RNStatusPage.vue")), }, + { + name: "rnpath", + path: "/rnpath", + component: defineAsyncComponent(() => import("./components/tools/RNPathPage.vue")), + }, { name: "rnprobe", path: "/rnprobe", From 6a61441e73f3ce0f50f6f94805369410c384211d Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 12:40:41 -0600 Subject: [PATCH 130/234] style: enhance chip components with improved styling and hover effects for better user experience --- meshchatx/src/frontend/style.css | 67 ++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/meshchatx/src/frontend/style.css b/meshchatx/src/frontend/style.css index a4501d3..9e9cc94 100644 --- a/meshchatx/src/frontend/style.css +++ b/meshchatx/src/frontend/style.css @@ -48,15 +48,65 @@ select.input-field option { } .primary-chip { - @apply inline-flex items-center gap-x-2 rounded-full bg-blue-600/90 px-3 py-1.5 text-xs font-semibold text-white shadow hover:bg-blue-500 transition; + @apply inline-flex items-center justify-center gap-x-2 rounded-full bg-blue-600 px-4 py-2 text-xs font-bold text-white shadow-sm transition-all !important; +} +.primary-chip:hover { + @apply bg-blue-500 -translate-y-0.5 !important; +} +.primary-chip:active { + @apply scale-95 translate-y-0 !important; } .secondary-chip { - @apply inline-flex items-center gap-x-2 rounded-full border border-gray-300 dark:border-zinc-700 px-3 py-1.5 text-xs font-semibold text-gray-700 dark:text-gray-100 bg-white/80 dark:bg-zinc-900/70 hover:border-blue-400 dark:hover:border-blue-500 transition; + @apply inline-flex items-center justify-center gap-x-2 rounded-full border border-gray-300 px-4 py-2 text-xs font-bold shadow-sm transition-all duration-200 !important; + background-color: white !important; + color: #374151 !important; /* text-gray-700 */ +} +.secondary-chip:hover { + background-color: #f9fafb !important; /* bg-gray-50 */ + color: #111827 !important; /* text-gray-900 */ + border-color: #60a5fa !important; /* border-blue-400 */ + @apply -translate-y-0.5 shadow-md !important; +} +.secondary-chip:active { + @apply scale-95 translate-y-0 shadow-sm !important; +} + +.dark .secondary-chip { + background-color: #18181b !important; /* bg-zinc-900 */ + color: #f4f4f5 !important; /* text-zinc-100 */ + border-color: #3f3f46 !important; /* border-zinc-700 */ +} +.dark .secondary-chip:hover { + background-color: #27272a !important; /* bg-zinc-800 */ + color: #ffffff !important; /* text-white */ + border-color: #3b82f6 !important; /* border-blue-500 */ + @apply shadow-lg shadow-blue-500/10 !important; } .danger-chip { - @apply inline-flex items-center gap-x-2 rounded-full border border-red-300 dark:border-red-900 px-3 py-1.5 text-xs font-semibold text-red-700 dark:text-red-100 bg-red-50/50 dark:bg-red-900/20 hover:bg-red-100 dark:hover:bg-red-900/40 transition; + @apply inline-flex items-center justify-center gap-x-2 rounded-full border border-red-200 px-4 py-2 text-xs font-bold transition-all duration-200 !important; + background-color: #fef2f2 !important; /* bg-red-50 */ + color: #b91c1c !important; /* text-red-700 */ +} +.danger-chip:hover { + background-color: #fee2e2 !important; /* bg-red-100 */ + color: #991b1b !important; /* text-red-800 */ + @apply -translate-y-0.5 shadow-md !important; +} +.danger-chip:active { + @apply scale-95 translate-y-0 !important; +} + +.dark .danger-chip { + background-color: rgba(69, 10, 10, 0.2) !important; /* bg-red-950/20 */ + color: #f87171 !important; /* text-red-400 */ + border-color: rgba(127, 29, 29, 0.5) !important; /* border-red-900/50 */ +} +.dark .danger-chip:hover { + background-color: rgba(127, 29, 29, 0.4) !important; /* bg-red-900/40 */ + color: #fca5a5 !important; /* text-red-300 */ + @apply shadow-lg shadow-red-500/10 !important; } .glass-label { @@ -85,7 +135,16 @@ select.input-field option { @apply text-sm text-gray-900 dark:text-white break-words pr-16; } .address-card__action { - @apply absolute top-3 right-3 inline-flex items-center gap-1 rounded-full border border-gray-200 dark:border-zinc-700 px-3 py-1 text-xs font-semibold text-gray-700 dark:text-gray-100 bg-white/70 dark:bg-zinc-900/60 hover:border-blue-400 dark:hover:border-blue-500 transition; + @apply absolute top-3 right-3 inline-flex items-center gap-1 rounded-full border border-gray-200 px-3 py-1 text-[10px] font-bold text-gray-700 bg-white shadow-sm transition-all !important; +} +.address-card__action:hover { + @apply bg-gray-50 text-gray-900 border-blue-400 !important; +} +.dark .address-card__action { + @apply border-zinc-700 text-zinc-100 bg-zinc-900 !important; +} +.dark .address-card__action:hover { + @apply bg-zinc-800 text-white border-blue-500 !important; } .file-input { From 4507a999fc69b8d40f6250a515ac520beb03dec8 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 12:41:34 -0600 Subject: [PATCH 131/234] feat(frontend): big updates (too many) --- .../frontend/components/LanguageSelector.vue | 69 +- .../src/frontend/components/LxmfUserIcon.vue | 4 +- .../frontend/components/NotificationBell.vue | 201 +-- .../frontend/components/about/AboutPage.vue | 1094 ++++++++--------- .../components/blocked/BlockedPage.vue | 167 +-- .../src/frontend/components/call/CallPage.vue | 6 +- .../interfaces/AddInterfacePage.vue | 6 - .../src/frontend/components/map/MapPage.vue | 42 +- .../messages/AudioWaveformPlayer.vue | 2 +- .../messages/ConversationDropDownMenu.vue | 14 +- .../messages/ConversationViewer.vue | 68 +- .../components/messages/MessagesPage.vue | 1 + .../components/messages/PaperMessageModal.vue | 115 +- .../nomadnetwork/NomadNetworkSidebar.vue | 8 +- .../src/frontend/components/ping/PingPage.vue | 12 +- .../src/frontend/components/rncp/RNCPPage.vue | 31 + .../components/rnstatus/RNStatusPage.vue | 41 +- .../components/settings/SettingsPage.vue | 46 +- .../components/tools/PaperMessagePage.vue | 72 +- .../frontend/components/tools/RNPathPage.vue | 311 +++++ .../frontend/components/tools/ToolsPage.vue | 15 + 21 files changed, 1474 insertions(+), 851 deletions(-) create mode 100644 meshchatx/src/frontend/components/tools/RNPathPage.vue diff --git a/meshchatx/src/frontend/components/LanguageSelector.vue b/meshchatx/src/frontend/components/LanguageSelector.vue index 44b87e9..7ad6d8d 100644 --- a/meshchatx/src/frontend/components/LanguageSelector.vue +++ b/meshchatx/src/frontend/components/LanguageSelector.vue @@ -4,34 +4,37 @@ type="button" class="relative rounded-full p-1.5 sm:p-2 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-zinc-800 transition-colors" :title="$t('app.language')" - @click="toggleDropdown" + @click.stop="toggleDropdown" > -
    -
    - + +
    +
    + +
    -
    +
    @@ -62,6 +65,7 @@ export default { data() { return { isDropdownOpen: false, + dropdownPosition: { top: 0, left: 0 }, languages: [ { code: "en", name: "English" }, { code: "de", name: "Deutsch" }, @@ -73,10 +77,27 @@ export default { currentLanguage() { return this.$i18n.locale; }, + dropdownStyle() { + return { + top: `${this.dropdownPosition.top}px`, + left: `${this.dropdownPosition.left}px`, + }; + }, }, methods: { - toggleDropdown() { + toggleDropdown(event) { this.isDropdownOpen = !this.isDropdownOpen; + if (this.isDropdownOpen) { + this.updateDropdownPosition(event); + } + }, + updateDropdownPosition(event) { + const button = event.currentTarget; + const rect = button.getBoundingClientRect(); + this.dropdownPosition = { + top: rect.bottom + 8, + left: Math.max(8, rect.right - 192), // 192px is w-48 + }; }, closeDropdown() { this.isDropdownOpen = false; diff --git a/meshchatx/src/frontend/components/LxmfUserIcon.vue b/meshchatx/src/frontend/components/LxmfUserIcon.vue index b3ea2a0..d054c88 100644 --- a/meshchatx/src/frontend/components/LxmfUserIcon.vue +++ b/meshchatx/src/frontend/components/LxmfUserIcon.vue @@ -16,10 +16,10 @@
    - +
    diff --git a/meshchatx/src/frontend/components/NotificationBell.vue b/meshchatx/src/frontend/components/NotificationBell.vue index 6871ce4..64170e8 100644 --- a/meshchatx/src/frontend/components/NotificationBell.vue +++ b/meshchatx/src/frontend/components/NotificationBell.vue @@ -3,7 +3,7 @@ -
    -
    -
    -

    Notifications

    - -
    -
    - -
    -
    -
    - + +
    +
    +
    +

    Notifications

    +
    -
    Loading notifications...
    -
    - -
    No new notifications
    -
    - -
    - +
    Loading notifications...
    +
    + +
    + +
    No new notifications
    +
    + +
    + +
    -
    +
    @@ -139,9 +146,17 @@ export default { notifications: [], unreadCount: 0, reloadInterval: null, + dropdownPosition: { top: 0, left: 0 }, }; }, - computed: {}, + computed: { + dropdownStyle() { + return { + top: `${this.dropdownPosition.top}px`, + left: `${this.dropdownPosition.left}px`, + }; + }, + }, beforeUnmount() { if (this.reloadInterval) { clearInterval(this.reloadInterval); @@ -158,13 +173,25 @@ export default { }, 5000); }, methods: { - async toggleDropdown() { + async toggleDropdown(event) { this.isDropdownOpen = !this.isDropdownOpen; if (this.isDropdownOpen) { + this.updateDropdownPosition(event); await this.loadNotifications(); await this.markNotificationsAsViewed(); } }, + updateDropdownPosition(event) { + const button = event.currentTarget; + const rect = button.getBoundingClientRect(); + const isMobile = window.innerWidth < 640; + const dropdownWidth = isMobile ? 320 : 384; // 80 (320px) or 96 (384px) + + this.dropdownPosition = { + top: rect.bottom + 8, + left: Math.max(16, rect.right - dropdownWidth), + }; + }, closeDropdown() { this.isDropdownOpen = false; }, diff --git a/meshchatx/src/frontend/components/about/AboutPage.vue b/meshchatx/src/frontend/components/about/AboutPage.vue index 0aa12e4..81fe925 100644 --- a/meshchatx/src/frontend/components/about/AboutPage.vue +++ b/meshchatx/src/frontend/components/about/AboutPage.vue @@ -27,36 +27,19 @@
    - - - - @@ -92,619 +75,577 @@ }}
    -
    - - - {{ showAdvanced ? "Hide Advanced" : "Advanced Mode" }} -
    - -
    - -
    +
    + +
    +
    - - Environment Information + + Security & Integrity
    -
    -
    -
    Reticulum Config
    -
    - {{ appInfo.reticulum_config_path }} -
    - - Reveal File - -
    -
    -
    Database Path
    -
    - {{ appInfo.database_path }} -
    - - Reveal DB - -
    -
    + -
    -
    - Identity Hash - {{ - config.identity_hash - }} -
    -
    - LXMF Address - {{ - config.lxmf_address_hash - }} -
    -
    -
    - Python - v{{ appInfo.python_version }} -
    -
    - LXMF - v{{ appInfo.lxmf_version }} -
    -
    - RNS - v{{ appInfo.rns_version }} -
    -
    -
    -
    - - -
    -
    -
    - - Security & Integrity -
    -
    - - - {{ + - -
    -
    - -
    -
    + {{ + appInfo.integrity_issues.length === 0 + ? $t("about.secured") + : $t("about.tampering_detected") + }} + +
    -
      -
    • - - {{ issue }} -
    • -
    -
    -
    - - {{ $t("about.no_integrity_violations") }} + + {{ $t("common.acknowledge_reset") }} +
    - -
    +
    - - Dependency Chain + + Technical Issues Detected
    -
    -
    -
    -
    +
  • + + {{ issue }} +
  • + +
    +
    + + {{ $t("about.no_integrity_violations") }} +
    +
    + + +
    +
    + + Environment Information +
    +
    +
    +
    Reticulum Config
    +
    + {{ appInfo.reticulum_config_path }} +
    + +
    +
    +
    Database Path
    +
    + {{ appInfo.database_path }} +
    + +
    +
    +
    +
    + Identity Hash - -
    -
    -
    - MeshChatX -
    -
    - v{{ appInfo.version }} -
    -
    + {{ + config.identity_hash + }}
    -
    -
    -
    + LXMF Address - LXMF -
    -
    -
    - Lightweight Extensible Message Format -
    -
    - v{{ appInfo.lxmf_version }} -
    -
    -
    -
    -
    -
    - RNS -
    -
    -
    - Reticulum Network Stack -
    -
    - v{{ appInfo.rns_version }} -
    -
    + {{ + config.lxmf_address_hash + }}
    - -
    -
    + Python -
    - Core Runtime -
    -
    -
    - LXST Engine - v{{ appInfo.lxst_version }} -
    -
    - Electron - v{{ electronVersion }} -
    -
    - Chrome - v{{ chromeVersion }} -
    -
    - Node.js - v{{ nodeVersion }} -
    -
    -
    - -
    -
    - Backend Stack -
    -
    -
    - {{ name.replace("_", " ") }} - v{{ version }} -
    -
    -
    + v{{ appInfo.python_version }} +
    +
    + LXMF + v{{ appInfo.lxmf_version }} +
    +
    + RNS + v{{ appInfo.rns_version }}
    +
    - -
    -
    -
    - - Database Health & Maintenance -
    -
    - - Refresh - - - Vacuum - - - Recovery - -
    -
    - -
    -
    + +
    +
    + + Dependency Chain +
    +
    +
    +
    - Integrity +
    -
    - {{ databaseHealth.quick_check }} +
    +
    MeshChatX
    +
    + v{{ appInfo.version }} +
    +
    - Journal + LXMF
    -
    - {{ databaseHealth.journal_mode }} +
    +
    + Lightweight Extensible Message Format +
    +
    + v{{ appInfo.lxmf_version }} +
    - Page Count -
    -
    - {{ databaseHealth.page_count }} -
    -
    -
    + class="absolute -left-[2px] top-0 bottom-0 w-[2px] bg-gradient-to-b from-purple-500 to-indigo-500" + >
    - Free Space + RNS
    -
    - {{ formatBytes(databaseHealth.estimated_free_bytes) }} +
    +
    + Reticulum Network Stack +
    +
    + v{{ appInfo.rns_version }} +
    -
    - -
    -
    -
    - - Database Backups -
    -
    - Full snapshots of your communications database. -
    -
    - +
    +
    - - Download Backup - -
    - - -
    -
    -
    -
    +
    +
    + LXST Engine + v{{ appInfo.lxst_version }} - - Local Snapshots -
    -
    - Create point-in-time restore points on disk. -
    -
    - - + Electron + v{{ electronVersion }} +
    +
    + Chrome + v{{ chromeVersion }} +
    +
    + Node.js + v{{ nodeVersion }} - Create -
    +
    -
    +
    +
    + Backend Stack +
    +
    -
    - {{ snapshot.name }} - {{ formatBytes(snapshot.size) }} • {{ snapshot.created_at }} -
    - {{ name.replace("_", " ") }} + v{{ version }} - Restore -
    - - -
    -
    - -
    -
    Identity Key Control
    -
    - Critical Security Warning -
    -
    -
    - -
    - - - Export Key File - - - - Copy Base32 Key - -
    - -
    -
    - Restore Identity -
    -
    - - - Upload Key File - - -
    - — or — -
    - - - Paste Base32 - -
    - - -
    - - - Confirm Key Restore - -
    -
    -
    -
    - + + +
    +
    +
    + + Database Health & Maintenance +
    +
    + + + +
    +
    + +
    +
    +
    + Integrity +
    +
    + {{ databaseHealth.quick_check }} +
    +
    +
    +
    + Journal +
    +
    + {{ databaseHealth.journal_mode }} +
    +
    +
    +
    + Page Count +
    +
    + {{ databaseHealth.page_count }} +
    +
    +
    +
    + Free Space +
    +
    + {{ formatBytes(databaseHealth.estimated_free_bytes) }} +
    +
    +
    + +
    + +
    +
    +
    + + Database Backups +
    +
    + Full snapshots of your communications database. +
    +
    + +
    + + +
    +
    +
    +
    + + Local Snapshots +
    +
    + Create point-in-time restore points on disk. +
    +
    +
    + + +
    +
    + +
    +
    +
    + {{ snapshot.name }} + {{ formatBytes(snapshot.size) }} • {{ snapshot.created_at }} +
    + +
    +
    +
    + + +
    +
    + +
    +
    Identity Key Control
    +
    + Critical Security Warning +
    +
    +
    + +
    + + +
    + +
    +
    + Restore Identity +
    +
    + + +
    + — or — +
    + +
    + + +
    + + +
    +
    +
    +
    +
    +
    +
    @@ -715,6 +656,7 @@ import Utils from "../../js/Utils"; import ElectronUtils from "../../js/ElectronUtils"; import DialogUtils from "../../js/DialogUtils"; import ToastUtils from "../../js/ToastUtils"; +import GlobalEmitter from "../../js/GlobalEmitter"; export default { name: "AboutPage", components: {}, @@ -758,7 +700,6 @@ export default { electronVersion: null, chromeVersion: null, nodeVersion: null, - showAdvanced: false, showIdentityPaste: false, }; }, @@ -1030,10 +971,10 @@ export default { } }, showChangelog() { - this.$router.push({ name: "changelog" }); + GlobalEmitter.emit("show-changelog"); }, showTutorial() { - this.$router.push({ name: "tutorial" }); + GlobalEmitter.emit("show-tutorial"); }, showReticulumConfigFile() { const reticulumConfigPath = this.appInfo.reticulum_config_path; @@ -1178,3 +1119,10 @@ export default { }, }; + + diff --git a/meshchatx/src/frontend/components/blocked/BlockedPage.vue b/meshchatx/src/frontend/components/blocked/BlockedPage.vue index 80603ad..57a3b6d 100644 --- a/meshchatx/src/frontend/components/blocked/BlockedPage.vue +++ b/meshchatx/src/frontend/components/blocked/BlockedPage.vue @@ -8,8 +8,8 @@
    -

    Blocked

    -

    Manage blocked users and nodes

    +

    Banished

    +

    Manage Banished users and nodes

    @@ -39,7 +39,7 @@
    -

    Loading blocked items...

    +

    Loading banished items...

    -

    No blocked items

    +

    No banished items

    {{ searchQuery - ? "No blocked items match your search." - : "You haven't blocked any users or nodes yet." + ? "No banished items match your search." + : "You haven't banished any users or nodes yet." }}

    @@ -95,6 +95,13 @@ > User + + RNS Blackhole +

    -
    - Blocked {{ formatTimeAgo(item.created_at) }} +
    + Banished {{ formatTimeAgo(item.created_at) }} +
    +
    + Source: {{ item.rns_source }} +
    +
    + "{{ item.rns_reason }}"
    @@ -114,7 +133,7 @@ @click="onUnblock(item)" > - Unblock + Lift Banishment
    @@ -137,17 +156,31 @@ export default { data() { return { blockedItems: [], + reticulumBlackholedItems: [], isLoading: false, searchQuery: "", }; }, computed: { + allBlockedItems() { + // Combine local blocked items and reticulum blackholed items + // Prioritize local items if they overlap + const localHashes = new Set(this.blockedItems.map((i) => i.destination_hash)); + const combined = [...this.blockedItems]; + + for (const item of this.reticulumBlackholedItems) { + if (!localHashes.has(item.destination_hash)) { + combined.push(item); + } + } + return combined; + }, filteredBlockedItems() { if (!this.searchQuery.trim()) { - return this.blockedItems; + return this.allBlockedItems; } const query = this.searchQuery.toLowerCase(); - return this.blockedItems.filter((item) => { + return this.allBlockedItems.filter((item) => { const matchesHash = item.destination_hash.toLowerCase().includes(query); const matchesDisplayName = (item.display_name || "").toLowerCase().includes(query); return matchesHash || matchesDisplayName; @@ -161,74 +194,70 @@ export default { async loadBlockedDestinations() { this.isLoading = true; try { + // Load local blocked destinations const response = await window.axios.get("/api/v1/blocked-destinations"); const blockedHashes = response.data.blocked_destinations || []; - const items = await Promise.all( - blockedHashes.map(async (blocked) => { - let displayName = "Unknown"; - let isNode = false; + // Load Reticulum blackholed identities + let reticulumBlackholed = {}; + try { + const rnsResponse = await window.axios.get("/api/v1/reticulum/blackhole"); + reticulumBlackholed = rnsResponse.data.blackholed_identities || {}; + } catch (e) { + console.error("Failed to load Reticulum blackhole", e); + } - try { - const nodeAnnounceResponse = await window.axios.get("/api/v1/announces", { - params: { - aspect: "nomadnetwork.node", - identity_hash: blocked.destination_hash, - include_blocked: true, - limit: 1, - }, - }); + const processItem = async (hash, data = {}) => { + let displayName = "Unknown"; + let isNode = false; - if (nodeAnnounceResponse.data.announces && nodeAnnounceResponse.data.announces.length > 0) { - const announce = nodeAnnounceResponse.data.announces[0]; - displayName = announce.display_name || "Unknown"; - isNode = true; - } else { - const announceResponse = await window.axios.get("/api/v1/announces", { - params: { - identity_hash: blocked.destination_hash, - include_blocked: true, - limit: 1, - }, - }); + try { + const announceResponse = await window.axios.get("/api/v1/announces", { + params: { + identity_hash: hash, + include_blocked: true, + limit: 1, + }, + }); - if (announceResponse.data.announces && announceResponse.data.announces.length > 0) { - const announce = announceResponse.data.announces[0]; - displayName = announce.display_name || "Unknown"; - isNode = announce.aspect === "nomadnetwork.node"; - } else { - const lxmfResponse = await window.axios.get("/api/v1/announces", { - params: { - destination_hash: blocked.destination_hash, - include_blocked: true, - limit: 1, - }, - }); - - if (lxmfResponse.data.announces && lxmfResponse.data.announces.length > 0) { - const announce = lxmfResponse.data.announces[0]; - displayName = announce.display_name || "Unknown"; - isNode = announce.aspect === "nomadnetwork.node"; - } - } - } - } catch (e) { - console.log(e); + if (announceResponse.data.announces && announceResponse.data.announces.length > 0) { + const announce = announceResponse.data.announces[0]; + displayName = announce.display_name || "Unknown"; + isNode = announce.aspect === "nomadnetwork.node"; } + } catch { + // ignore error + } - return { - destination_hash: blocked.destination_hash, - display_name: displayName, - created_at: blocked.created_at, - is_node: isNode, - }; - }) + return { + destination_hash: hash, + display_name: displayName, + created_at: data.created_at || null, + is_node: isNode, + is_rns_blackholed: !!data.is_rns, + rns_source: data.source || null, + rns_reason: data.reason || null, + rns_until: data.until || null, + }; + }; + + const items = await Promise.all( + blockedHashes.map((blocked) => + processItem(blocked.destination_hash, { created_at: blocked.created_at }) + ) + ); + + const rnsItems = await Promise.all( + Object.entries(reticulumBlackholed).map(([hash, info]) => + processItem(hash, { ...info, is_rns: true }) + ) ); this.blockedItems = items; + this.reticulumBlackholedItems = rnsItems; } catch (e) { console.log(e); - ToastUtils.error("Failed to load blocked destinations"); + ToastUtils.error("Failed to load banished destinations"); } finally { this.isLoading = false; } @@ -236,7 +265,7 @@ export default { async onUnblock(item) { if ( !(await DialogUtils.confirm( - `Are you sure you want to unblock ${item.display_name || item.destination_hash}?` + `Are you sure you want to lift the banishment for ${item.display_name || item.destination_hash}?` )) ) { return; @@ -245,10 +274,10 @@ export default { try { await window.axios.delete(`/api/v1/blocked-destinations/${item.destination_hash}`); await this.loadBlockedDestinations(); - ToastUtils.success("Unblocked successfully"); + ToastUtils.success("Banishment lifted successfully"); } catch (e) { console.log(e); - ToastUtils.error("Failed to unblock"); + ToastUtils.error("Failed to lift banishment"); } }, onSearchInput() {}, diff --git a/meshchatx/src/frontend/components/call/CallPage.vue b/meshchatx/src/frontend/components/call/CallPage.vue index 78585b2..eb10c63 100644 --- a/meshchatx/src/frontend/components/call/CallPage.vue +++ b/meshchatx/src/frontend/components/call/CallPage.vue @@ -2380,15 +2380,15 @@ export default { } }, async blockIdentity(hash) { - if (!confirm(`Are you sure you want to block this identity?`)) return; + if (!confirm(`Are you sure you want to banish this identity?`)) return; try { await window.axios.post("/api/v1/blocked-destinations", { destination_hash: hash, }); - ToastUtils.success("Identity blocked"); + ToastUtils.success("Identity banished"); this.getHistory(); } catch { - ToastUtils.error("Failed to block identity"); + ToastUtils.error("Failed to banish identity"); } }, async getVoicemailStatus() { diff --git a/meshchatx/src/frontend/components/interfaces/AddInterfacePage.vue b/meshchatx/src/frontend/components/interfaces/AddInterfacePage.vue index 8a75642..46b5358 100644 --- a/meshchatx/src/frontend/components/interfaces/AddInterfacePage.vue +++ b/meshchatx/src/frontend/components/interfaces/AddInterfacePage.vue @@ -1588,12 +1588,6 @@ export default { .glass-label { @apply mb-1 text-sm font-semibold text-gray-800 dark:text-gray-200; } -.primary-chip { - @apply inline-flex items-center gap-x-2 rounded-full bg-blue-600/90 px-3 py-1.5 text-xs font-semibold text-white shadow hover:bg-blue-500 transition; -} -.secondary-chip { - @apply inline-flex items-center gap-x-2 rounded-full border border-gray-300 dark:border-zinc-700 px-3 py-1.5 text-xs font-semibold text-gray-700 dark:text-gray-100 bg-white/80 dark:bg-zinc-900/70 hover:border-blue-400; -} .glass-field { @apply space-y-1; } diff --git a/meshchatx/src/frontend/components/map/MapPage.vue b/meshchatx/src/frontend/components/map/MapPage.vue index 8da7ef5..ae39c2f 100644 --- a/meshchatx/src/frontend/components/map/MapPage.vue +++ b/meshchatx/src/frontend/components/map/MapPage.vue @@ -78,12 +78,12 @@
    @@ -147,9 +147,7 @@ class="absolute top-2 left-4 right-4 sm:left-auto sm:right-4 sm:w-80 z-30" >
    -
    +
    @@ -250,15 +248,15 @@ >
    @@ -922,8 +920,8 @@ Edit Note @@ -938,15 +936,15 @@
    diff --git a/meshchatx/src/frontend/components/messages/AudioWaveformPlayer.vue b/meshchatx/src/frontend/components/messages/AudioWaveformPlayer.vue index a062e35..d6cd0e4 100644 --- a/meshchatx/src/frontend/components/messages/AudioWaveformPlayer.vue +++ b/meshchatx/src/frontend/components/messages/AudioWaveformPlayer.vue @@ -1,6 +1,6 @@ @@ -321,9 +321,9 @@ export default { try { await window.axios.delete(`/api/v1/blocked-destinations/${identityHash}`); GlobalEmitter.emit("block-status-changed"); - DialogUtils.alert("Node unblocked successfully"); + DialogUtils.alert("Banishment lifted successfully"); } catch (e) { - DialogUtils.alert("Failed to unblock node"); + DialogUtils.alert("Failed to lift banishment"); console.log(e); } }, diff --git a/meshchatx/src/frontend/components/ping/PingPage.vue b/meshchatx/src/frontend/components/ping/PingPage.vue index e7069a9..7f1cca3 100644 --- a/meshchatx/src/frontend/components/ping/PingPage.vue +++ b/meshchatx/src/frontend/components/ping/PingPage.vue @@ -40,28 +40,24 @@
    - - - diff --git a/meshchatx/src/frontend/components/rncp/RNCPPage.vue b/meshchatx/src/frontend/components/rncp/RNCPPage.vue index 81a7f0b..7ba3af8 100644 --- a/meshchatx/src/frontend/components/rncp/RNCPPage.vue +++ b/meshchatx/src/frontend/components/rncp/RNCPPage.vue @@ -15,6 +15,33 @@
    {{ $t("rncp.description") }}
    + +
    +
    + {{ $t("rncp.usage_steps") }} +
    +
    + +

    + +

    + +

    +
    +
    @@ -493,6 +520,10 @@ export default { this.listenDestinationHash = null; this.listenResult = null; }, + renderMarkdown(text) { + if (!text) return ""; + return text.replace(/\*\*(.*?)\*\*/g, "$1"); + }, }, }; diff --git a/meshchatx/src/frontend/components/rnstatus/RNStatusPage.vue b/meshchatx/src/frontend/components/rnstatus/RNStatusPage.vue index 92a6b38..8ff7d99 100644 --- a/meshchatx/src/frontend/components/rnstatus/RNStatusPage.vue +++ b/meshchatx/src/frontend/components/rnstatus/RNStatusPage.vue @@ -48,11 +48,36 @@
    -
    -
    Active Links: {{ linkCount }}
    +
    +
    +
    Active Links: {{ linkCount }}
    +
    + +
    +
    + Blackhole: {{ blackholeEnabled ? "Publishing" : "Active" }} + {{ blackholeCount }} Identities +
    +
    +
    +
    + +
    +
    Blackhole Sources
    +
    +
    + {{ source }} +
    @@ -189,6 +214,9 @@ export default { linkCount: null, includeLinkStats: false, sorting: "", + blackholeEnabled: null, + blackholeSources: [], + blackholeCount: 0, }; }, watch: { @@ -215,6 +243,9 @@ export default { const response = await window.axios.get("/api/v1/rnstatus", { params }); this.interfaces = response.data.interfaces || []; this.linkCount = response.data.link_count; + this.blackholeEnabled = response.data.blackhole_enabled; + this.blackholeSources = response.data.blackhole_sources || []; + this.blackholeCount = response.data.blackhole_count || 0; } catch (e) { console.error(e); } finally { diff --git a/meshchatx/src/frontend/components/settings/SettingsPage.vue b/meshchatx/src/frontend/components/settings/SettingsPage.vue index 0ee6f4a..61c3340 100644 --- a/meshchatx/src/frontend/components/settings/SettingsPage.vue +++ b/meshchatx/src/frontend/components/settings/SettingsPage.vue @@ -436,6 +436,40 @@
    + +
    +
    +
    +
    RNS Security
    +

    Network Security

    +

    Manage mesh-level security features.

    +
    +
    +
    +
    +
    +
    + {{ $t("app.blackhole_integration_enabled") }} +
    +
    + {{ $t("app.blackhole_integration_description") }} +
    +
    + +
    +
    +
    +
    @@ -494,14 +528,14 @@
    Privacy
    -

    Blocked

    -

    Manage blocked users and nodes

    +

    Banished

    +

    Manage Banished users and nodes

    - Manage Blocked + Manage Banished

    - Blocked users and nodes will not be able to send you messages, and their announces will + Banished users and nodes will not be able to send you messages, and their announces will be ignored.

    @@ -867,6 +901,7 @@ export default { banished_effect_enabled: true, banished_text: "BANISHED", banished_color: "#dc2626", + blackhole_integration_enabled: true, }, saveTimeouts: {}, shortcuts: [], @@ -1319,9 +1354,6 @@ export default { .setting-toggle__hint { @apply text-xs text-gray-500 dark:text-gray-400; } -.primary-chip { - @apply inline-flex items-center gap-x-1 rounded-full bg-blue-600/90 px-4 py-1.5 text-xs font-semibold text-white shadow hover:bg-blue-500 transition; -} .info-callout { @apply rounded-2xl border border-blue-100 dark:border-blue-900/40 bg-blue-50/60 dark:bg-blue-900/20 px-3 py-3 text-blue-900 dark:text-blue-100; } diff --git a/meshchatx/src/frontend/components/tools/PaperMessagePage.vue b/meshchatx/src/frontend/components/tools/PaperMessagePage.vue index 9eaab52..74aaefd 100644 --- a/meshchatx/src/frontend/components/tools/PaperMessagePage.vue +++ b/meshchatx/src/frontend/components/tools/PaperMessagePage.vue @@ -138,8 +138,8 @@

    Generated QR Code

    -
    -
    +
    +
    @@ -181,11 +181,20 @@
    @@ -227,6 +236,7 @@ export default { isGenerating: false, generatedUri: null, ingestUri: "", + isSending: false, }; }, computed: { @@ -284,7 +294,7 @@ export default { try { await QRCode.toCanvas(this.$refs.qrcode, this.generatedUri, { - width: 320, + width: 256, margin: 2, color: { dark: "#000000", @@ -341,6 +351,54 @@ export default { link.click(); } }, + async sendPaperMessage() { + const canvas = this.$refs.qrcode; + if (!canvas || !this.destinationHash || !this.generatedUri) return; + + try { + this.isSending = true; + + // get data url from canvas (format: data:image/png;base64,iVBORw0KG...) + const dataUrl = canvas.toDataURL("image/png"); + + // extract base64 data by removing the prefix + const imageBytes = dataUrl.split(",")[1]; + + // build lxmf message + const lxmf_message = { + destination_hash: this.destinationHash, + content: this.generatedUri, + fields: { + image: { + image_type: "png", + image_bytes: imageBytes, + name: "qrcode.png", + }, + }, + }; + + // send message + const response = await window.axios.post(`/api/v1/lxmf-messages/send`, { + delivery_method: "opportunistic", + lxmf_message: lxmf_message, + }); + + if (response.data.status === "success") { + ToastUtils.success("Paper message sent successfully"); + this.generatedUri = null; + this.destinationHash = ""; + this.content = ""; + this.title = ""; + } else { + ToastUtils.error(response.data.message || "Failed to send paper message"); + } + } catch (err) { + console.error("Failed to send paper message:", err); + ToastUtils.error("Failed to send paper message"); + } finally { + this.isSending = false; + } + }, printQRCode() { const canvas = this.$refs.qrcode; if (!canvas) return; diff --git a/meshchatx/src/frontend/components/tools/RNPathPage.vue b/meshchatx/src/frontend/components/tools/RNPathPage.vue new file mode 100644 index 0000000..588a699 --- /dev/null +++ b/meshchatx/src/frontend/components/tools/RNPathPage.vue @@ -0,0 +1,311 @@ + + + + + diff --git a/meshchatx/src/frontend/components/tools/ToolsPage.vue b/meshchatx/src/frontend/components/tools/ToolsPage.vue index bb8a85d..389ceae 100644 --- a/meshchatx/src/frontend/components/tools/ToolsPage.vue +++ b/meshchatx/src/frontend/components/tools/ToolsPage.vue @@ -70,6 +70,21 @@ + +
    + +
    +
    +
    {{ $t("tools.rnpath.title") }}
    +
    + {{ $t("tools.rnpath.description") }} +
    +
    + +
    +
    Date: Sun, 4 Jan 2026 12:41:49 -0600 Subject: [PATCH 132/234] feat(locales): update translations for emergency mode, blackhole integration, and RNCP usage instructions --- meshchatx/src/frontend/locales/de.json | 14 +++++++++++-- meshchatx/src/frontend/locales/en.json | 28 +++++++++++++++++--------- meshchatx/src/frontend/locales/ru.json | 14 +++++++++++-- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/meshchatx/src/frontend/locales/de.json b/meshchatx/src/frontend/locales/de.json index 19bac24..c5dc97b 100644 --- a/meshchatx/src/frontend/locales/de.json +++ b/meshchatx/src/frontend/locales/de.json @@ -161,7 +161,9 @@ "sync_error": "Synchronisierungsfehler: {status}", "switching_identity": "Identität wird gewechselt...", "loading_identity": "Ihre Identität wird geladen", - "emergency_mode_active": "Notfallmodus aktiv - In-Memory-Datenbank und eingeschränkte Dienste werden verwendet." + "emergency_mode_active": "Notfallmodus aktiv - In-Memory-Datenbank und eingeschränkte Dienste werden verwendet.", + "blackhole_integration_enabled": "Blackhole-Integration", + "blackhole_integration_description": "Identitäten automatisch auf der Reticulum-Transportebene sperren (Blackhole), wenn Benutzer in MeshChatX verbannt werden." }, "common": { "open": "Öffnen", @@ -504,6 +506,10 @@ "title": "RNStatus", "description": "Schnittstellenstatistiken und Netzwerkstatusinformationen anzeigen." }, + "rnpath": { + "title": "RNPath", + "description": "Verwalten Sie die Pfadtabelle, sehen Sie Ankündigungsraten und fordern Sie Pfade an." + }, "translator": { "title": "Übersetzer", "description": "Text mit der LibreTranslate API oder lokalem Argos Translate übersetzen." @@ -560,7 +566,11 @@ "rncp": { "file_transfer": "Dateiübertragung", "title": "RNCP - Reticulum Network Copy", - "description": "Senden und Empfangen von Dateien über das Reticulum-Netzwerk unter Verwendung von RNS-Ressourcen.", + "description": "Senden und Empfangen von Dateien über das Reticulum-Netzwerk unter Verwendung von RNS-Ressourcen. Dieses Tool ermöglicht eine zuverlässige Dateiübertragung zwischen Mesh-Knoten, selbst über Verbindungen mit hoher Latenz.", + "usage_steps": "Verwendung von RNCP:", + "step_1": "1. Um eine Datei zu **empfangen**, gehen Sie zum Tab **Hören**, geben Sie erlaubte Identitäts-Hashes ein (wer an Sie senden darf) und klicken Sie auf **Hören starten**.", + "step_2": "2. Um eine Datei zu **senden**, besorgen Sie sich den **Ziel-Hash** eines hörenden Knotens, geben Sie den **lokalen Dateipfad** ein und klicken Sie auf **Datei senden**.", + "step_3": "3. Um eine Datei **abzurufen**, besorgen Sie sich den **Ziel-Hash** eines Knotens, der mit aktiviertem 'Abruf zulassen' hört, geben Sie den **Remote-Dateipfad** ein und klicken Sie auf **Datei abrufen**.", "send_file": "Datei senden", "fetch_file": "Datei abrufen", "listen": "Hören", diff --git a/meshchatx/src/frontend/locales/en.json b/meshchatx/src/frontend/locales/en.json index f277158..32fbd9f 100644 --- a/meshchatx/src/frontend/locales/en.json +++ b/meshchatx/src/frontend/locales/en.json @@ -131,9 +131,9 @@ "smart_crawler": "Smart Crawler", "authentication": "Authentication", "banishment": "Banishment", - "banishment_description": "Customize the visual effect shown for blocked peers and nodes.", + "banishment_description": "Customize the visual effect shown for banished peers and nodes.", "banished_effect_enabled": "Enable Banishment Effect", - "banished_effect_description": "Show a visual overlay on blocked peers and nodes.", + "banished_effect_description": "Show a visual overlay on banished peers and nodes.", "banished_text_label": "Banishment Text", "banished_text_description": "Custom message to display on the overlay.", "banished_color_label": "Banishment Color", @@ -161,14 +161,16 @@ "sync_error": "Sync error: {status}", "switching_identity": "Switching Identity...", "loading_identity": "Loading your identity", - "emergency_mode_active": "Emergency Mode Active - Using in-memory database and restricted services." + "emergency_mode_active": "Emergency Mode Active - Using in-memory database and restricted services.", + "blackhole_integration_enabled": "Blackhole Integration", + "blackhole_integration_description": "Automatically blackhole identities at the Reticulum transport layer when banishing users in MeshChatX." }, "common": { "open": "Open", "close": "Close", "cancel": "Cancel", "save": "Save", - "block": "Block", + "block": "Banish", "delete": "Delete", "edit": "Edit", "add": "Add", @@ -428,12 +430,12 @@ "add_nodes_from_announces": "Add nodes from the announces tab.", "search_announces": "Search announces", "announced_time_ago": "Announced {time} ago", - "block_node": "Block Node", + "block_node": "Banish Node", "no_announces_yet": "No announces yet", "listening_for_peers": "Listening for peers on the mesh.", - "block_node_confirm": "Are you sure you want to block {name}? Their announces will be ignored and they won't appear in the announce stream.", - "node_blocked_successfully": "Node blocked successfully", - "failed_to_block_node": "Failed to block node", + "block_node_confirm": "Are you sure you want to banish {name}? Their announces will be ignored and they won't appear in the announce stream.", + "node_blocked_successfully": "Node banished successfully", + "failed_to_block_node": "Failed to banish node", "rename_favourite": "Rename this favourite", "remove_favourite_confirm": "Are you sure you want to remove this favourite?", "enter_nomadnet_url": "Enter a Nomadnet URL", @@ -504,6 +506,10 @@ "title": "RNStatus", "description": "View interface statistics and network status information." }, + "rnpath": { + "title": "RNPath", + "description": "Manage the path table, view announce rates and request paths." + }, "translator": { "title": "Translator", "description": "Translate text using LibreTranslate API or local Argos Translate." @@ -560,7 +566,11 @@ "rncp": { "file_transfer": "File Transfer", "title": "RNCP - Reticulum Network Copy", - "description": "Send and receive files over the Reticulum network using RNS resources.", + "description": "Send and receive files over the Reticulum network using RNS resources. This tool allows for reliable file transfer between mesh nodes even over high-latency links.", + "usage_steps": "How to use RNCP:", + "step_1": "1. To **receive** a file, go to the **Listen** tab, enter allowed identity hashes (who can send to you), and click **Start Listening**.", + "step_2": "2. To **send** a file, get the **Destination Hash** of a listening node, enter the **Local File Path**, and click **Send File**.", + "step_3": "3. To **fetch** a file, get the **Destination Hash** of a node listening with 'Allow Fetch' enabled, enter the **Remote File Path**, and click **Fetch File**.", "send_file": "Send File", "fetch_file": "Fetch File", "listen": "Listen", diff --git a/meshchatx/src/frontend/locales/ru.json b/meshchatx/src/frontend/locales/ru.json index a5aafa2..5bfacf0 100644 --- a/meshchatx/src/frontend/locales/ru.json +++ b/meshchatx/src/frontend/locales/ru.json @@ -161,7 +161,9 @@ "sync_error": "Ошибка синхронизации: {status}", "switching_identity": "Переключение личности...", "loading_identity": "Загрузка вашей личности", - "emergency_mode_active": "Аварийный режим активен — используется база данных в оперативной памяти и ограниченные службы." + "emergency_mode_active": "Аварийный режим активен — используется база данных в оперативной памяти и ограниченные службы.", + "blackhole_integration_enabled": "Интеграция Blackhole", + "blackhole_integration_description": "Автоматически блокировать (blackhole) личности на транспортном уровне Reticulum при изгнании пользователей в MeshChatX." }, "common": { "open": "Открыть", @@ -504,6 +506,10 @@ "title": "RNStatus", "description": "Статистика интерфейсов и информация о состоянии сети." }, + "rnpath": { + "title": "RNPath", + "description": "Управление таблицей путей, просмотр частоты анонсов и запрос путей." + }, "translator": { "title": "Translator", "description": "Перевод текста через LibreTranslate API или локальный Argos Translate." @@ -560,7 +566,11 @@ "rncp": { "file_transfer": "Передача файлов", "title": "RNCP - Reticulum Network Copy", - "description": "Отправка и получение файлов через сеть Reticulum с использованием ресурсов RNS.", + "description": "Отправка и получение файлов через сеть Reticulum с использованием ресурсов RNS. Этот инструмент обеспечивает надежную передачу файлов между узлами сети даже через каналы с высокой задержкой.", + "usage_steps": "Как использовать RNCP:", + "step_1": "1. Чтобы **получить** файл, перейдите на вкладку **Прослушивание**, введите разрешенные хеши идентичности (кто может присылать вам файлы) и нажмите **Начать прослушивание**.", + "step_2": "2. Чтобы **отправить** файл, получите **Хеш назначения** прослушиваемого узла, введите **Локальный путь к файлу** и нажмите **Отправить файл**.", + "step_3": "3. Чтобы **запросить** файл, получите **Хеш назначения** узла, прослушивающего с включенной опцией 'Разрешить получение', введите **Удаленный путь к файлу** и нажмите **Получить файл**.", "send_file": "Отправить файл", "fetch_file": "Получить файл", "listen": "Прослушивание", From bc40dcff4e157bd8bd3fc509428b0b34778ab7e6 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 12:41:55 -0600 Subject: [PATCH 133/234] feat(tests): add comprehensive tests for blackhole integration, RNPath management, and RNStatus handling --- tests/backend/test_blackhole_logic.py | 236 +++++++++++++++++++++++ tests/backend/test_rnpath_logic.py | 121 ++++++++++++ tests/backend/test_rnstatus_blackhole.py | 62 ++++++ 3 files changed, 419 insertions(+) create mode 100644 tests/backend/test_blackhole_logic.py create mode 100644 tests/backend/test_rnpath_logic.py create mode 100644 tests/backend/test_rnstatus_blackhole.py diff --git a/tests/backend/test_blackhole_logic.py b/tests/backend/test_blackhole_logic.py new file mode 100644 index 0000000..8ffadc5 --- /dev/null +++ b/tests/backend/test_blackhole_logic.py @@ -0,0 +1,236 @@ +import shutil +import tempfile +import pytest +import json +from unittest.mock import MagicMock, patch, AsyncMock +from meshchatx.meshchat import ReticulumMeshChat +import RNS +import asyncio + + +@pytest.fixture +def temp_dir(): + dir_path = tempfile.mkdtemp() + yield dir_path + shutil.rmtree(dir_path) + + +@pytest.fixture +def mock_rns_minimal(): + with ( + patch("RNS.Reticulum") as mock_rns, + patch("RNS.Transport"), + patch("LXMF.LXMRouter"), + patch("meshchatx.meshchat.get_file_path", return_value="/tmp/mock_path"), + ): + mock_rns_instance = mock_rns.return_value + mock_rns_instance.configpath = "/tmp/mock_config" + mock_rns_instance.is_connected_to_shared_instance = False + mock_rns_instance.transport_enabled.return_value = True + # Mock the new blackhole methods + mock_rns_instance.blackhole_identity = MagicMock() + mock_rns_instance.unblackhole_identity = MagicMock() + mock_rns_instance.get_blackholed_identities.return_value = {} + + mock_id = MagicMock(spec=RNS.Identity) + mock_id.hash = b"\x00" * 32 + mock_id.hexhash = mock_id.hash.hex() + mock_id.get_private_key.return_value = b"test_private_key" + yield mock_id + + +@pytest.mark.asyncio +async def test_banish_identity_with_blackhole(mock_rns_minimal, temp_dir): + with patch("meshchatx.meshchat.generate_ssl_certificate"): + app_instance = ReticulumMeshChat( + identity=mock_rns_minimal, + storage_dir=temp_dir, + reticulum_config_dir=temp_dir, + ) + + # Ensure blackhole integration is enabled + app_instance.config.blackhole_integration_enabled.set(True) + + # Mock database + app_instance.database = MagicMock() + app_instance.database.announces.get_announce_by_hash.return_value = None + + target_hash = "a" * 32 + + # Mock request + request = MagicMock() + request.json = AsyncMock(return_value={"destination_hash": target_hash}) + + # Find handler + handler = None + for route in app_instance.get_routes(): + if route.path == "/api/v1/blocked-destinations" and route.method == "POST": + handler = route.handler + break + + assert handler is not None + + response = await handler(request) + assert response.status == 200 + + # Verify DB call + app_instance.database.misc.add_blocked_destination.assert_called_with( + target_hash + ) + + # Verify RNS blackhole call + app_instance.reticulum.blackhole_identity.assert_called() + args, kwargs = app_instance.reticulum.blackhole_identity.call_args + assert args[0] == bytes.fromhex(target_hash) + + +@pytest.mark.asyncio +async def test_banish_identity_with_resolution(mock_rns_minimal, temp_dir): + with patch("meshchatx.meshchat.generate_ssl_certificate"): + app_instance = ReticulumMeshChat( + identity=mock_rns_minimal, + storage_dir=temp_dir, + reticulum_config_dir=temp_dir, + ) + + app_instance.config.blackhole_integration_enabled.set(True) + app_instance.database = MagicMock() + + dest_hash = "d" * 32 + ident_hash = "e" * 32 + + # Mock identity resolution + app_instance.database.announces.get_announce_by_hash.return_value = { + "identity_hash": ident_hash + } + + request = MagicMock() + request.json = AsyncMock(return_value={"destination_hash": dest_hash}) + + handler = None + for route in app_instance.get_routes(): + if route.path == "/api/v1/blocked-destinations" and route.method == "POST": + handler = route.handler + break + + await handler(request) + + # Should have blackholed the IDENTITY hash, not the destination hash + app_instance.reticulum.blackhole_identity.assert_called() + args, _ = app_instance.reticulum.blackhole_identity.call_args + assert args[0] == bytes.fromhex(ident_hash) + + +@pytest.mark.asyncio +async def test_banish_identity_disabled_integration(mock_rns_minimal, temp_dir): + with patch("meshchatx.meshchat.generate_ssl_certificate"): + app_instance = ReticulumMeshChat( + identity=mock_rns_minimal, + storage_dir=temp_dir, + reticulum_config_dir=temp_dir, + ) + + # DISABLE blackhole integration + app_instance.config.blackhole_integration_enabled.set(False) + app_instance.database = MagicMock() + + target_hash = "b" * 32 + request = MagicMock() + request.json = AsyncMock(return_value={"destination_hash": target_hash}) + + handler = None + for route in app_instance.get_routes(): + if route.path == "/api/v1/blocked-destinations" and route.method == "POST": + handler = route.handler + break + + await handler(request) + + # DB call should still happen + app_instance.database.misc.add_blocked_destination.assert_called_with( + target_hash + ) + + # RNS blackhole call should NOT happen + app_instance.reticulum.blackhole_identity.assert_not_called() + + +@pytest.mark.asyncio +async def test_lift_banishment(mock_rns_minimal, temp_dir): + with patch("meshchatx.meshchat.generate_ssl_certificate"): + app_instance = ReticulumMeshChat( + identity=mock_rns_minimal, + storage_dir=temp_dir, + reticulum_config_dir=temp_dir, + ) + + app_instance.config.blackhole_integration_enabled.set(True) + app_instance.database = MagicMock() + # Mock identity resolution + app_instance.database.announces.get_announce_by_hash.return_value = None + + target_hash = "c" * 32 + + # Mock request with match_info for the variable in path + request = MagicMock() + request.match_info = {"destination_hash": target_hash} + + handler = None + for route in app_instance.get_routes(): + if ( + route.path == "/api/v1/blocked-destinations/{destination_hash}" + and route.method == "DELETE" + ): + handler = route.handler + break + + assert handler is not None + + await handler(request) + + # Verify DB call + app_instance.database.misc.delete_blocked_destination.assert_called_with( + target_hash + ) + + # Verify RNS unblackhole call + app_instance.reticulum.unblackhole_identity.assert_called() + args, _ = app_instance.reticulum.unblackhole_identity.call_args + assert args[0] == bytes.fromhex(target_hash) + + +@pytest.mark.asyncio +async def test_get_blackhole_list(mock_rns_minimal, temp_dir): + with patch("meshchatx.meshchat.generate_ssl_certificate"): + app_instance = ReticulumMeshChat( + identity=mock_rns_minimal, + storage_dir=temp_dir, + reticulum_config_dir=temp_dir, + ) + + ident_hash_bytes = b"\x01" * 32 + app_instance.reticulum.get_blackholed_identities.return_value = { + ident_hash_bytes: { + "source": b"\x02" * 32, + "until": 1234567890, + "reason": "Spam", + } + } + + request = MagicMock() + + handler = None + for route in app_instance.get_routes(): + if route.path == "/api/v1/reticulum/blackhole" and route.method == "GET": + handler = route.handler + break + + assert handler is not None + + response = await handler(request) + data = json.loads(response.body) + + assert ident_hash_bytes.hex() in data["blackholed_identities"] + info = data["blackholed_identities"][ident_hash_bytes.hex()] + assert info["reason"] == "Spam" + assert info["source"] == (b"\x02" * 32).hex() diff --git a/tests/backend/test_rnpath_logic.py b/tests/backend/test_rnpath_logic.py new file mode 100644 index 0000000..9f00286 --- /dev/null +++ b/tests/backend/test_rnpath_logic.py @@ -0,0 +1,121 @@ +import pytest +import json +from unittest.mock import MagicMock, patch, AsyncMock +from meshchatx.meshchat import ReticulumMeshChat +import RNS + + +@pytest.fixture +def temp_dir(tmp_path): + return str(tmp_path) + + +@pytest.fixture +def mock_rns_minimal(): + with ( + patch("RNS.Reticulum") as mock_rns, + patch("RNS.Transport"), + patch("LXMF.LXMRouter"), + patch("meshchatx.meshchat.get_file_path", return_value="/tmp/mock_path"), + ): + mock_rns_instance = mock_rns.return_value + mock_rns_instance.configpath = "/tmp/mock_config" + mock_rns_instance.is_connected_to_shared_instance = False + mock_rns_instance.transport_enabled.return_value = True + + # Path management mocks + mock_rns_instance.get_path_table.return_value = [] + mock_rns_instance.get_rate_table.return_value = [] + mock_rns_instance.drop_path.return_value = True + mock_rns_instance.drop_all_via.return_value = True + mock_rns_instance.drop_announce_queues = MagicMock() + + mock_id = MagicMock(spec=RNS.Identity) + mock_id.hash = b"\x00" * 32 + mock_id.hexhash = mock_id.hash.hex() + mock_id.get_private_key.return_value = b"test_private_key" + yield mock_id + + +@pytest.mark.asyncio +async def test_rnpath_table_endpoint(mock_rns_minimal, temp_dir): + with patch("meshchatx.meshchat.generate_ssl_certificate"): + app_instance = ReticulumMeshChat( + identity=mock_rns_minimal, + storage_dir=temp_dir, + reticulum_config_dir=temp_dir, + ) + + entry = { + "hash": b"\x01" * 32, + "hops": 1, + "via": b"\x02" * 32, + "interface": "UDP", + "expires": 1234567890, + } + app_instance.reticulum.get_path_table.return_value = [entry] + + request = MagicMock() + request.query = {} + + handler = next( + r.handler + for r in app_instance.get_routes() + if r.path == "/api/v1/rnpath/table" + ) + response = await handler(request) + data = json.loads(response.body) + + assert len(data["table"]) == 1 + assert data["table"][0]["hash"] == entry["hash"].hex() + + +@pytest.mark.asyncio +async def test_rnpath_request_endpoint(mock_rns_minimal, temp_dir): + with ( + patch("meshchatx.meshchat.generate_ssl_certificate"), + patch.object(RNS.Transport, "request_path") as mock_request_path, + ): + app_instance = ReticulumMeshChat( + identity=mock_rns_minimal, + storage_dir=temp_dir, + reticulum_config_dir=temp_dir, + ) + + target_hash = "a" * 32 + request = MagicMock() + request.json = AsyncMock(return_value={"destination_hash": target_hash}) + + handler = next( + r.handler + for r in app_instance.get_routes() + if r.path == "/api/v1/rnpath/request" + ) + response = await handler(request) + + mock_request_path.assert_called_with(bytes.fromhex(target_hash)) + assert json.loads(response.body)["success"] is True + + +@pytest.mark.asyncio +async def test_rnpath_drop_endpoint(mock_rns_minimal, temp_dir): + with patch("meshchatx.meshchat.generate_ssl_certificate"): + app_instance = ReticulumMeshChat( + identity=mock_rns_minimal, + storage_dir=temp_dir, + reticulum_config_dir=temp_dir, + ) + + target_hash = "b" * 32 + request = MagicMock() + request.json = AsyncMock(return_value={"destination_hash": target_hash}) + + handler = next( + r.handler + for r in app_instance.get_routes() + if r.path == "/api/v1/rnpath/drop" + ) + response = await handler(request) + + app_instance.reticulum.drop_path.assert_called_with(bytes.fromhex(target_hash)) + assert json.loads(response.body)["success"] is True diff --git a/tests/backend/test_rnstatus_blackhole.py b/tests/backend/test_rnstatus_blackhole.py new file mode 100644 index 0000000..2911616 --- /dev/null +++ b/tests/backend/test_rnstatus_blackhole.py @@ -0,0 +1,62 @@ +import pytest +from unittest.mock import MagicMock, patch +from meshchatx.src.backend.rnstatus_handler import RNStatusHandler +import RNS + + +@pytest.fixture +def mock_reticulum_instance(): + mock = MagicMock() + mock.get_interface_stats.return_value = {"interfaces": []} + mock.get_link_count.return_value = 0 + return mock + + +def test_blackhole_status_enabled(mock_reticulum_instance): + with ( + patch.object(RNS.Reticulum, "publish_blackhole_enabled", return_value=True), + patch.object( + RNS.Reticulum, + "blackhole_sources", + return_value=[b"\x01" * 16, b"\x02" * 16], + ), + ): + handler = RNStatusHandler(mock_reticulum_instance) + status = handler.get_status() + + assert status["blackhole_enabled"] is True + assert len(status["blackhole_sources"]) == 2 + assert status["blackhole_sources"][0] == (b"\x01" * 16).hex() + + +def test_blackhole_status_disabled(mock_reticulum_instance): + with ( + patch.object(RNS.Reticulum, "publish_blackhole_enabled", return_value=False), + patch.object(RNS.Reticulum, "blackhole_sources", return_value=[]), + ): + handler = RNStatusHandler(mock_reticulum_instance) + status = handler.get_status() + + assert status["blackhole_enabled"] is False + assert status["blackhole_sources"] == [] + + +def test_blackhole_status_missing_api(mock_reticulum_instance): + # Test backward compatibility or when API is missing (e.g. older RNS version simulation) + # We simulate this by making the attribute access raise AttributeError + # However, since we import RNS in the module, we need to ensure the mock raises AttributeError + + # We can't easily remove attributes from the real RNS module if it's already imported. + # But we can patch the RNS object inside rnstatus_handler module. + + with patch( + "meshchatx.src.backend.rnstatus_handler.RNS.Reticulum" + ) as mock_rns_class: + del mock_rns_class.publish_blackhole_enabled + + handler = RNStatusHandler(mock_reticulum_instance) + status = handler.get_status() + + # Should default to False/Empty on exception + assert status["blackhole_enabled"] is False + assert status["blackhole_sources"] == [] From 54ccc03c4da62c3406f3871c9db7fd8375374998 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 12:42:02 -0600 Subject: [PATCH 134/234] feat(tests): add unit tests for BanishedPage and RNPathPage components, enhancing coverage for blocked items and path management --- tests/frontend/BanishedPage.test.js | 119 ++++++++++++++++++++ tests/frontend/LanguageSelector.test.js | 17 +-- tests/frontend/NotificationBell.test.js | 2 + tests/frontend/RNPathPage.test.js | 105 +++++++++++++++++ tests/frontend/UIThemeAndVisibility.test.js | 45 ++++++++ 5 files changed, 280 insertions(+), 8 deletions(-) create mode 100644 tests/frontend/BanishedPage.test.js create mode 100644 tests/frontend/RNPathPage.test.js diff --git a/tests/frontend/BanishedPage.test.js b/tests/frontend/BanishedPage.test.js new file mode 100644 index 0000000..f83972d --- /dev/null +++ b/tests/frontend/BanishedPage.test.js @@ -0,0 +1,119 @@ +import { mount } from "@vue/test-utils"; +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import BlockedPage from "@/components/blocked/BlockedPage.vue"; +import GlobalState from "@/js/GlobalState"; + +describe("BlockedPage.vue (Banished UI)", () => { + let axiosMock; + + beforeEach(() => { + axiosMock = { + get: vi.fn(), + post: vi.fn(), + delete: vi.fn(), + }; + window.axios = axiosMock; + + // Mock localization + const t = (key) => { + const translations = { + "common.save": "Save", + "common.cancel": "Cancel", + }; + return translations[key] || key; + }; + + axiosMock.get.mockImplementation((url) => { + if (url === "/api/v1/blocked-destinations") { + return Promise.resolve({ + data: { + blocked_destinations: [ + { destination_hash: "a".repeat(32), created_at: "2026-01-04T12:00:00Z" }, + ], + }, + }); + } + if (url === "/api/v1/reticulum/blackhole") { + return Promise.resolve({ + data: { + blackholed_identities: { + ["b".repeat(32)]: { + source: "c".repeat(32), + reason: "Spam", + until: null, + }, + }, + }, + }); + } + if (url === "/api/v1/announces") { + return Promise.resolve({ data: { announces: [] } }); + } + return Promise.resolve({ data: {} }); + }); + }); + + afterEach(() => { + delete window.axios; + }); + + const mountBlockedPage = () => { + return mount(BlockedPage, { + global: { + mocks: { + $t: (key) => key, + }, + stubs: { + MaterialDesignIcon: { + template: '
    ', + props: ["iconName"], + }, + }, + }, + }); + }; + + it("displays 'Banished' title and subtext", async () => { + const wrapper = mountBlockedPage(); + // Wait for isLoading to become false + await vi.waitFor(() => expect(wrapper.vm.isLoading).toBe(false)); + + expect(wrapper.text()).toContain("Banished"); + expect(wrapper.text()).toContain("Manage Banished users and nodes"); + }); + + it("combines local blocked and RNS blackholed items", async () => { + const wrapper = mountBlockedPage(); + await vi.waitFor(() => expect(wrapper.vm.isLoading).toBe(false)); + + expect(wrapper.vm.allBlockedItems.length).toBe(2); + + const rnsItem = wrapper.vm.allBlockedItems.find((i) => i.is_rns_blackholed); + expect(rnsItem).toBeDefined(); + expect(rnsItem.destination_hash).toBe("b".repeat(32)); + expect(rnsItem.rns_reason).toBe("Spam"); + }); + + it("displays RNS Blackhole badge for blackholed items", async () => { + const wrapper = mountBlockedPage(); + await vi.waitFor(() => expect(wrapper.vm.isLoading).toBe(false)); + + expect(wrapper.text()).toContain("RNS Blackhole"); + }); + + it("calls delete API when lifting banishment", async () => { + // Mock DialogUtils.confirm + const DialogUtils = await import("@/js/DialogUtils"); + vi.spyOn(DialogUtils.default, "confirm").mockResolvedValue(true); + + const wrapper = mountBlockedPage(); + await vi.waitFor(() => expect(wrapper.vm.isLoading).toBe(false)); + + const unblockButtons = wrapper.findAll("button").filter((b) => b.text().includes("Lift Banishment")); + expect(unblockButtons.length).toBeGreaterThan(0); + + await unblockButtons[0].trigger("click"); + + expect(axiosMock.delete).toHaveBeenCalled(); + }); +}); diff --git a/tests/frontend/LanguageSelector.test.js b/tests/frontend/LanguageSelector.test.js index fff5897..8e77e9e 100644 --- a/tests/frontend/LanguageSelector.test.js +++ b/tests/frontend/LanguageSelector.test.js @@ -14,6 +14,7 @@ describe("LanguageSelector.vue", () => { }, stubs: { MaterialDesignIcon: true, + Teleport: true, }, }, }); @@ -28,20 +29,20 @@ describe("LanguageSelector.vue", () => { const wrapper = mountLanguageSelector(); const button = wrapper.find("button"); - expect(wrapper.find(".absolute").exists()).toBe(false); + expect(wrapper.find(".fixed").exists()).toBe(false); await button.trigger("click"); - expect(wrapper.find(".absolute").exists()).toBe(true); + expect(wrapper.find(".fixed").exists()).toBe(true); await button.trigger("click"); - expect(wrapper.find(".absolute").exists()).toBe(false); + expect(wrapper.find(".fixed").exists()).toBe(false); }); it("lists all available languages in the dropdown", async () => { const wrapper = mountLanguageSelector(); await wrapper.find("button").trigger("click"); - const languageButtons = wrapper.findAll(".absolute button"); + const languageButtons = wrapper.findAll(".fixed button"); expect(languageButtons).toHaveLength(3); expect(languageButtons[0].text()).toContain("English"); expect(languageButtons[1].text()).toContain("Deutsch"); @@ -52,22 +53,22 @@ describe("LanguageSelector.vue", () => { const wrapper = mountLanguageSelector("en"); await wrapper.find("button").trigger("click"); - const deButton = wrapper.findAll(".absolute button")[1]; + const deButton = wrapper.findAll(".fixed button")[1]; await deButton.trigger("click"); expect(wrapper.emitted("language-change")).toBeTruthy(); expect(wrapper.emitted("language-change")[0]).toEqual(["de"]); - expect(wrapper.find(".absolute").exists()).toBe(false); + expect(wrapper.find(".fixed").exists()).toBe(false); }); it("does not emit language-change when the current language is selected", async () => { const wrapper = mountLanguageSelector("en"); await wrapper.find("button").trigger("click"); - const enButton = wrapper.findAll(".absolute button")[0]; + const enButton = wrapper.findAll(".fixed button")[0]; await enButton.trigger("click"); expect(wrapper.emitted("language-change")).toBeFalsy(); - expect(wrapper.find(".absolute").exists()).toBe(false); + expect(wrapper.find(".fixed").exists()).toBe(false); }); }); diff --git a/tests/frontend/NotificationBell.test.js b/tests/frontend/NotificationBell.test.js index 743291c..c1925d8 100644 --- a/tests/frontend/NotificationBell.test.js +++ b/tests/frontend/NotificationBell.test.js @@ -32,6 +32,7 @@ describe("NotificationBell.vue", () => { }, stubs: { MaterialDesignIcon: true, + Teleport: true, }, directives: { "click-outside": {}, @@ -172,6 +173,7 @@ describe("NotificationBell.vue", () => { }, stubs: { MaterialDesignIcon: true, + Teleport: true, }, directives: { "click-outside": {}, diff --git a/tests/frontend/RNPathPage.test.js b/tests/frontend/RNPathPage.test.js new file mode 100644 index 0000000..7fcf42c --- /dev/null +++ b/tests/frontend/RNPathPage.test.js @@ -0,0 +1,105 @@ +import { mount } from "@vue/test-utils"; +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import RNPathPage from "@/components/tools/RNPathPage.vue"; + +describe("RNPathPage.vue", () => { + let axiosMock; + + beforeEach(() => { + axiosMock = { + get: vi.fn(), + post: vi.fn(), + }; + window.axios = axiosMock; + + axiosMock.get.mockImplementation((url) => { + if (url === "/api/v1/rnpath/table") { + return Promise.resolve({ + data: { + table: [ + { + hash: "a".repeat(32), + hops: 1, + via: "b".repeat(32), + interface: "UDP", + expires: 1234567890, + }, + ], + }, + }); + } + if (url === "/api/v1/rnpath/rates") { + return Promise.resolve({ + data: { + rates: [ + { + hash: "c".repeat(32), + last: 1234567890, + timestamps: [], + rate_violations: 0, + blocked_until: 0, + }, + ], + }, + }); + } + return Promise.resolve({ data: {} }); + }); + }); + + afterEach(() => { + delete window.axios; + }); + + const mountRNPathPage = () => { + return mount(RNPathPage, { + global: { + mocks: { + $t: (key) => key, + }, + stubs: { + MaterialDesignIcon: { + template: '
    ', + props: ["iconName"], + }, + }, + }, + }); + }; + + it("renders and loads data", async () => { + const wrapper = mountRNPathPage(); + await vi.waitFor(() => expect(wrapper.vm.isLoading).toBe(false)); + + expect(wrapper.text()).toContain("RNPath"); + expect(wrapper.vm.pathTable.length).toBe(1); + expect(wrapper.vm.rateTable.length).toBe(1); + }); + + it("switches tabs", async () => { + const wrapper = mountRNPathPage(); + await vi.waitFor(() => expect(wrapper.vm.isLoading).toBe(false)); + + const ratesButton = wrapper.findAll("button").find((b) => b.text() === "Rates"); + await ratesButton.trigger("click"); + expect(wrapper.vm.tab).toBe("rates"); + + const actionsButton = wrapper.findAll("button").find((b) => b.text() === "Actions"); + await actionsButton.trigger("click"); + expect(wrapper.vm.tab).toBe("actions"); + }); + + it("calls request path API", async () => { + const wrapper = mountRNPathPage(); + await vi.waitFor(() => expect(wrapper.vm.isLoading).toBe(false)); + + await wrapper.setData({ tab: "actions", requestHash: "d".repeat(32) }); + + const requestButton = wrapper.findAll("button").find((b) => b.text() === "Request"); + await requestButton.trigger("click"); + + expect(axiosMock.post).toHaveBeenCalledWith("/api/v1/rnpath/request", { + destination_hash: "d".repeat(32), + }); + }); +}); diff --git a/tests/frontend/UIThemeAndVisibility.test.js b/tests/frontend/UIThemeAndVisibility.test.js index c33e603..13e6565 100644 --- a/tests/frontend/UIThemeAndVisibility.test.js +++ b/tests/frontend/UIThemeAndVisibility.test.js @@ -8,6 +8,14 @@ import ChangelogModal from "../../meshchatx/src/frontend/components/ChangelogMod import NotificationBell from "../../meshchatx/src/frontend/components/NotificationBell.vue"; import LanguageSelector from "../../meshchatx/src/frontend/components/LanguageSelector.vue"; +vi.mock("vuetify", () => ({ + useTheme: vi.fn(() => ({ + global: { + name: { value: "light" }, + }, + })), +})); + vi.mock("../../meshchatx/src/frontend/js/WebSocketConnection", () => ({ default: { on: vi.fn(), @@ -344,6 +352,7 @@ describe("Visibility Checks", () => { banished_effect_enabled: true, banished_text: "BANISHED", banished_color: "#dc2626", + blackhole_integration_enabled: true, }, }, }), @@ -379,6 +388,42 @@ describe("Visibility Checks", () => { delete window.axios; }); + it("SettingsPage shows blackhole integration toggle", async () => { + const axiosMock = { + get: vi.fn().mockResolvedValue({ + data: { + config: { + blackhole_integration_enabled: true, + }, + }, + }), + patch: vi.fn().mockResolvedValue({ data: {} }), + }; + window.axios = axiosMock; + + const wrapper = mount(SettingsPage, { + global: { + stubs: { + MaterialDesignIcon: { template: "
    " }, + Toggle: Toggle, + ShortcutRecorder: { template: "
    " }, + RouterLink: { template: "" }, + }, + mocks: { + $t: (key) => key, + $router: { push: vi.fn() }, + }, + }, + }); + + await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick(); + + expect(wrapper.text()).toContain("app.blackhole_integration_enabled"); + + delete window.axios; + }); + it("SettingsPage hides banished config when toggle is disabled", async () => { const axiosMock = { get: vi.fn().mockResolvedValue({ From 162d7c14f9b4fed706a9f15b38c6d5be703fb7bd Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 12:42:16 -0600 Subject: [PATCH 135/234] feat(theme): refactor theme handling to utilize Vuetify's useTheme, streamline theme application logic, and enhance header styling for improved UX --- meshchatx/src/frontend/components/App.vue | 49 +++++++++++++---------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/meshchatx/src/frontend/components/App.vue b/meshchatx/src/frontend/components/App.vue index 10ae5f5..935a7f4 100644 --- a/meshchatx/src/frontend/components/App.vue +++ b/meshchatx/src/frontend/components/App.vue @@ -22,9 +22,8 @@
    + + diff --git a/meshchatx/src/frontend/components/tools/ToolsPage.vue b/meshchatx/src/frontend/components/tools/ToolsPage.vue index 389ceae..e68e4d5 100644 --- a/meshchatx/src/frontend/components/tools/ToolsPage.vue +++ b/meshchatx/src/frontend/components/tools/ToolsPage.vue @@ -2,193 +2,199 @@
    -
    -
    -
    - {{ $t("tools.utilities") }} +
    +
    +
    +
    + {{ $t("tools.utilities") }} +
    +
    + {{ $t("tools.power_tools") }} +
    +
    + {{ $t("tools.diagnostics_description") }} +
    -
    {{ $t("tools.power_tools") }}
    -
    - {{ $t("tools.diagnostics_description") }} -
    -
    -
    - -
    - -
    -
    -
    {{ $t("tools.ping.title") }}
    -
    - {{ $t("tools.ping.description") }} +
    + +
    +
    -
    - - - - -
    - -
    -
    -
    {{ $t("tools.rnprobe.title") }}
    -
    - {{ $t("tools.rnprobe.description") }} +
    +
    {{ $t("tools.ping.title") }}
    +
    + {{ $t("tools.ping.description") }} +
    -
    - - - - -
    - -
    -
    -
    {{ $t("tools.rncp.title") }}
    -
    - {{ $t("tools.rncp.description") }} -
    -
    - -
    - - -
    - -
    -
    -
    {{ $t("tools.rnstatus.title") }}
    -
    - {{ $t("tools.rnstatus.description") }} -
    -
    - -
    - - -
    - -
    -
    -
    {{ $t("tools.rnpath.title") }}
    -
    - {{ $t("tools.rnpath.description") }} -
    -
    - -
    - - -
    - -
    -
    -
    {{ $t("tools.translator.title") }}
    -
    - {{ $t("tools.translator.description") }} -
    -
    - -
    - - -
    - -
    -
    -
    {{ $t("tools.forwarder.title") }}
    -
    - {{ $t("tools.forwarder.description") }} -
    -
    - -
    - - -
    - -
    -
    -
    {{ $t("docs.title") }}
    -
    - {{ $t("docs.subtitle") }} -
    -
    - -
    - - -
    - -
    -
    -
    {{ $t("tools.micron_editor.title") }}
    -
    - {{ $t("tools.micron_editor.description") }} -
    -
    - -
    - - -
    - -
    -
    -
    {{ $t("tools.paper_message.title") }}
    -
    - {{ $t("tools.paper_message.description") }} -
    -
    - -
    - - -
    - RNode -
    -
    -
    {{ $t("tools.rnode_flasher.title") }}
    -
    - {{ $t("tools.rnode_flasher.description") }} -
    -
    -
    - - - -
    -
    + - -
    - -
    -
    -
    Debug Logs
    -
    - View and export internal system logs for troubleshooting. + +
    +
    -
    - - +
    +
    {{ $t("tools.rnprobe.title") }}
    +
    + {{ $t("tools.rnprobe.description") }} +
    +
    + + + + +
    + +
    +
    +
    {{ $t("tools.rncp.title") }}
    +
    + {{ $t("tools.rncp.description") }} +
    +
    + +
    + + +
    + +
    +
    +
    {{ $t("tools.rnstatus.title") }}
    +
    + {{ $t("tools.rnstatus.description") }} +
    +
    + +
    + + +
    + +
    +
    +
    {{ $t("tools.rnpath.title") }}
    +
    + {{ $t("tools.rnpath.description") }} +
    +
    + +
    + + +
    + +
    +
    +
    {{ $t("tools.translator.title") }}
    +
    + {{ $t("tools.translator.description") }} +
    +
    + +
    + + +
    + +
    +
    +
    {{ $t("tools.forwarder.title") }}
    +
    + {{ $t("tools.forwarder.description") }} +
    +
    + +
    + + +
    + +
    +
    +
    {{ $t("docs.title") }}
    +
    + {{ $t("docs.subtitle") }} +
    +
    + +
    + + +
    + +
    +
    +
    {{ $t("tools.micron_editor.title") }}
    +
    + {{ $t("tools.micron_editor.description") }} +
    +
    + +
    + + +
    + +
    +
    +
    {{ $t("tools.paper_message.title") }}
    +
    + {{ $t("tools.paper_message.description") }} +
    +
    + +
    + + +
    + RNode +
    +
    +
    {{ $t("tools.rnode_flasher.title") }}
    +
    + {{ $t("tools.rnode_flasher.description") }} +
    +
    +
    + + + + +
    +
    + + +
    + +
    +
    +
    Debug Logs
    +
    + View and export internal system logs for troubleshooting. +
    +
    + +
    +
    From bbf61d88a5a73b7ca28318e4e4c667dea89acca1 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 14:59:27 -0600 Subject: [PATCH 138/234] feat(vitest): add setupFiles configuration to Vitest for frontend tests --- vitest.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/vitest.config.js b/vitest.config.js index a643eab..bf87aee 100644 --- a/vitest.config.js +++ b/vitest.config.js @@ -8,6 +8,7 @@ export default defineConfig({ globals: true, environment: "jsdom", include: ["tests/frontend/**/*.{test,spec}.{js,ts,jsx,tsx}"], + setupFiles: ["tests/frontend/setup.js"], }, resolve: { alias: { From fd846e3ed27d8bbd42c86c6eeedef377f03f3fca Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 14:59:36 -0600 Subject: [PATCH 139/234] feat(security): update Content Security Policy to allow connections to GitHub API and related domains --- electron/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/electron/main.js b/electron/main.js index 0526a8c..ee86e31 100644 --- a/electron/main.js +++ b/electron/main.js @@ -350,7 +350,7 @@ app.whenReady().then(async () => { "style-src 'self' 'unsafe-inline'", "img-src 'self' data: blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org", "font-src 'self' data:", - "connect-src 'self' http://localhost:9337 https://localhost:9337 ws://localhost:* wss://localhost:* blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://nominatim.openstreetmap.org", + "connect-src 'self' http://localhost:9337 https://localhost:9337 ws://localhost:* wss://localhost:* blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://nominatim.openstreetmap.org https://api.github.com https://objects.githubusercontent.com https://github.com", "media-src 'self' blob:", "worker-src 'self' blob:", "frame-src 'self'", From 014e463527af2d3aa5ea4fc10f98d2e705093fbb Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 14:59:47 -0600 Subject: [PATCH 140/234] feat(api): add firmware download endpoint with GitHub URL validation and enhance initiation status response with target name --- meshchatx/meshchat.py | 98 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 4 deletions(-) diff --git a/meshchatx/meshchat.py b/meshchatx/meshchat.py index 1ba14c2..8df3c8d 100644 --- a/meshchatx/meshchat.py +++ b/meshchatx/meshchat.py @@ -2,6 +2,7 @@ import argparse import asyncio +import aiohttp import atexit import base64 import configparser @@ -1807,6 +1808,16 @@ class ReticulumMeshChat: ctx = context or self.current_context if not ctx: return + + target_name = None + if target_hash: + try: + contact = ctx.database.contacts.get_contact_by_hash(target_hash) + if contact: + target_name = contact.name + except Exception: # noqa: S110 + pass + AsyncUtils.run_async( self.websocket_broadcast( json.dumps( @@ -1814,6 +1825,7 @@ class ReticulumMeshChat: "type": "telephone_initiation_status", "status": status, "target_hash": target_hash, + "target_name": target_name, }, ), ), @@ -2245,6 +2257,40 @@ class ReticulumMeshChat: }, ) + @routes.get("/api/v1/tools/rnode/download_firmware") + async def tools_rnode_download_firmware(request): + url = request.query.get("url") + if not url: + return web.json_response({"error": "URL is required"}, status=400) + + # Restrict to GitHub for safety + if not url.startswith("https://github.com/") and not url.startswith( + "https://objects.githubusercontent.com/" + ): + return web.json_response({"error": "Invalid download URL"}, status=403) + + try: + async with aiohttp.ClientSession() as session: + async with session.get(url, allow_redirects=True) as response: + if response.status != 200: + return web.json_response( + {"error": f"Failed to download: {response.status}"}, + status=response.status, + ) + + data = await response.read() + filename = url.split("/")[-1] + + return web.Response( + body=data, + content_type="application/zip", + headers={ + "Content-Disposition": f'attachment; filename="{filename}"' + }, + ) + except Exception as e: + return web.json_response({"error": str(e)}, status=500) + # fetch reticulum interfaces @routes.get("/api/v1/reticulum/interfaces") async def reticulum_interfaces(request): @@ -3825,6 +3871,18 @@ class ReticulumMeshChat: "is_contact": contact is not None, } + initiation_target_hash = self.telephone_manager.initiation_target_hash + initiation_target_name = None + if initiation_target_hash: + try: + contact = self.database.contacts.get_contact_by_hash( + initiation_target_hash + ) + if contact: + initiation_target_name = contact.name + except Exception: # noqa: S110 + pass + return web.json_response( { "enabled": True, @@ -3839,7 +3897,8 @@ class ReticulumMeshChat: "latest_id": self.database.voicemails.get_latest_voicemail_id(), }, "initiation_status": self.telephone_manager.initiation_status, - "initiation_target_hash": self.telephone_manager.initiation_target_hash, + "initiation_target_hash": initiation_target_hash, + "initiation_target_name": initiation_target_name, }, ) @@ -5541,9 +5600,26 @@ class ReticulumMeshChat: max_hops = request.query.get("max_hops") if max_hops: max_hops = int(max_hops) + + search = request.query.get("search") + interface = request.query.get("interface") + hops = request.query.get("hops") + if hops: + hops = int(hops) + + page = int(request.query.get("page", 1)) + limit = int(request.query.get("limit", 50)) + try: - table = self.rnpath_handler.get_path_table(max_hops=max_hops) - return web.json_response({"table": table}) + result = self.rnpath_handler.get_path_table( + max_hops=max_hops, + search=search, + interface=interface, + hops=hops, + page=page, + limit=limit, + ) + return web.json_response(result) except Exception as e: return web.json_response({"message": str(e)}, status=500) @@ -7014,6 +7090,8 @@ class ReticulumMeshChat: @web.middleware async def mime_type_middleware(request, handler): response = await handler(request) + if response is None: + return None path = request.path if path.endswith(".js") or path.endswith(".mjs"): response.headers["Content-Type"] = ( @@ -7033,6 +7111,8 @@ class ReticulumMeshChat: @web.middleware async def security_middleware(request, handler): response = await handler(request) + if response is None: + return None # Add security headers to all responses response.headers["X-Content-Type-Options"] = "nosniff" @@ -7055,7 +7135,7 @@ class ReticulumMeshChat: "style-src 'self' 'unsafe-inline'; " "img-src 'self' data: blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org; " "font-src 'self' data:; " - "connect-src 'self' ws://localhost:* wss://localhost:* blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://nominatim.openstreetmap.org; " + "connect-src 'self' ws://localhost:* wss://localhost:* blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://nominatim.openstreetmap.org https://api.github.com https://objects.githubusercontent.com https://github.com; " "media-src 'self' blob:; " "worker-src 'self' blob:; " "frame-src 'self'; " @@ -7698,8 +7778,16 @@ class ReticulumMeshChat: elif _type == "nomadnet.page.archives.get": destination_hash = data["destination_hash"] page_path = data["page_path"] + + # Try relative path first archives = self.get_archived_page_versions(destination_hash, page_path) + # If nothing found and path doesn't look like it's already absolute, + # try searching with the destination hash prefix (support for old buggy archives) + if not archives and not page_path.startswith(destination_hash): + buggy_path = f"{destination_hash}:{page_path}" + archives = self.get_archived_page_versions(destination_hash, buggy_path) + AsyncUtils.run_async( client.send_str( json.dumps( @@ -7711,6 +7799,8 @@ class ReticulumMeshChat: { "id": archive.id, "hash": archive.hash, + "destination_hash": archive.destination_hash, + "page_path": archive.page_path, "created_at": archive.created_at.isoformat() if hasattr(archive.created_at, "isoformat") else str(archive.created_at), From f3ec20b14e4e38b597af7f2ccee6cc16bfb5d6c7 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 15:00:16 -0600 Subject: [PATCH 141/234] feat(rnpath): improve get_path_table method with filtering, sorting, and pagination; include additional stats for path entries --- meshchatx/src/backend/rnpath_handler.py | 78 ++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/meshchatx/src/backend/rnpath_handler.py b/meshchatx/src/backend/rnpath_handler.py index 92b54d5..032528c 100644 --- a/meshchatx/src/backend/rnpath_handler.py +++ b/meshchatx/src/backend/rnpath_handler.py @@ -5,10 +5,46 @@ class RNPathHandler: def __init__(self, reticulum_instance: RNS.Reticulum): self.reticulum = reticulum_instance - def get_path_table(self, max_hops: int = None): + def get_path_table( + self, + max_hops: int = None, + search: str = None, + interface: str = None, + hops: int = None, + page: int = 1, + limit: int = 0, + ): table = self.reticulum.get_path_table(max_hops=max_hops) formatted_table = [] for entry in table: + # Get additional data directly from Transport.path_table if available + # to provide more stats as requested. + dst_hash = entry["hash"] + announce_hash = None + state = RNS.Transport.STATE_UNKNOWN + + if dst_hash in RNS.Transport.path_table: + pt_entry = RNS.Transport.path_table[dst_hash] + if len(pt_entry) > 6: + announce_hash = pt_entry[6].hex() if pt_entry[6] else None + + if dst_hash in RNS.Transport.path_states: + state = RNS.Transport.path_states[dst_hash] + + # Filtering + if search: + search = search.lower() + hash_str = entry["hash"].hex().lower() + via_str = entry["via"].hex().lower() + if search not in hash_str and search not in via_str: + continue + + if interface and entry["interface"] != interface: + continue + + if hops is not None and entry["hops"] != hops: + continue + formatted_table.append( { "hash": entry["hash"].hex(), @@ -16,9 +52,47 @@ class RNPathHandler: "via": entry["via"].hex(), "interface": entry["interface"], "expires": entry["expires"], + "timestamp": entry.get("timestamp"), + "announce_hash": announce_hash, + "state": state, } ) - return sorted(formatted_table, key=lambda e: (e["interface"], e["hops"])) + + # Sort: Responsive first, then by hops, then by interface + formatted_table.sort( + key=lambda e: ( + 0 if e["state"] == RNS.Transport.STATE_RESPONSIVE else 1, + e["hops"], + e["interface"], + ) + ) + + total = len(formatted_table) + responsive_count = len( + [e for e in formatted_table if e["state"] == RNS.Transport.STATE_RESPONSIVE] + ) + unresponsive_count = len( + [ + e + for e in formatted_table + if e["state"] == RNS.Transport.STATE_UNRESPONSIVE + ] + ) + + # Pagination + if limit > 0: + start = (page - 1) * limit + end = start + limit + formatted_table = formatted_table[start:end] + + return { + "table": formatted_table, + "total": total, + "responsive": responsive_count, + "unresponsive": unresponsive_count, + "page": page, + "limit": limit, + } def get_rate_table(self): table = self.reticulum.get_rate_table() From c4674992e0f8c76fd964873d085bbaf9651010d7 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 15:57:49 -0600 Subject: [PATCH 142/234] lots of fixes, changes, styling, fixing outbound calls, rnode-flasher. --- CHANGELOG.md | 5 + README.md | 2 +- electron/backend-manifest.json | 3482 +++++++++++++++++ electron/main.js | 2 +- meshchatx/meshchat.py | 100 +- meshchatx/src/backend/docs_manager.py | 227 +- meshchatx/src/backend/telephone_manager.py | 76 +- meshchatx/src/backend/voicemail_manager.py | 53 +- meshchatx/src/frontend/components/App.vue | 2 +- .../frontend/components/call/CallOverlay.vue | 30 +- .../src/frontend/components/call/CallPage.vue | 26 +- .../src/frontend/components/docs/DocsPage.vue | 106 + .../messages/AudioWaveformPlayer.vue | 3 + .../micron-editor/MicronEditorPage.vue | 2 +- .../components/tools/RNodeFlasherPage.vue | 84 +- .../src/frontend/js/WebSocketConnection.js | 29 +- .../src/frontend/js/rnode/Nrf52DfuFlasher.js | 263 ++ meshchatx/src/frontend/js/rnode/RNode.js | 461 +++ meshchatx/src/frontend/js/rnode/RNodeUtils.js | 49 + meshchatx/src/frontend/js/rnode/ROM.js | 244 ++ meshchatx/src/frontend/js/rnode/products.js | 515 +++ meshchatx/src/frontend/locales/de.json | 276 +- meshchatx/src/frontend/locales/en.json | 276 +- meshchatx/src/frontend/locales/ru.json | 276 +- package.json | 12 +- pnpm-lock.yaml | 59 +- tests/backend/test_blackhole_logic.py | 1 - tests/backend/test_rnpath_logic.py | 9 +- tests/frontend/ChangelogModal.test.js | 3 +- tests/frontend/ConversationViewer.test.js | 3 + tests/frontend/DocsPage.test.js | 10 +- tests/frontend/MicronEditorPage.test.js | 25 +- tests/frontend/Toast.test.js | 32 +- tests/frontend/setup.js | 83 + 34 files changed, 6540 insertions(+), 286 deletions(-) create mode 100644 electron/backend-manifest.json create mode 100644 meshchatx/src/frontend/js/rnode/Nrf52DfuFlasher.js create mode 100644 meshchatx/src/frontend/js/rnode/RNode.js create mode 100644 meshchatx/src/frontend/js/rnode/RNodeUtils.js create mode 100644 meshchatx/src/frontend/js/rnode/ROM.js create mode 100644 meshchatx/src/frontend/js/rnode/products.js create mode 100644 tests/frontend/setup.js diff --git a/CHANGELOG.md b/CHANGELOG.md index a891a81..81197da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ Season 1 Episode 1 - A MASSIVE REFACTOR ### New Features +- **Banishment System (formerly Blocked):** + - Renamed all instances of "Blocked" to **"Banished"**, you can now banish people to the shadow realm. + - **Blackhole Integration:** Automatically blackholes identities at the RNS transport layer when they are banished in MeshChatX. This prevents their traffic from being relayed through your node and publishes the update to your interfaces (trusted interfaces will pull and enforce the banishment). + - Integrated RNS 1.1.0 Blackhole to display publishing status, sources, and current blackhole counts in the RNStatus page. +- **RNPath Management Tool:** New UI tool to manage the Reticulum path table, monitor announce rates (with rate-limit detection), and perform manual path requests or purges directly from the app. - **Maps:** You can now draw and doodle directly on the map to mark locations or plan routes. - **Calls & Audio:** - Added support for custom ringtones and a brand-new ringtone editor. diff --git a/README.md b/README.md index 2b9dce5..b509738 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ For issues contact me over LXMF: `73 [![Build](https://git.quad4.io/RNS-Things/MeshChatX/actions/workflows/build.yml/badge.svg?branch=master)](https://git.quad4.io/RNS-Things/MeshChatX/actions/workflows/build.yml) [![Docker](https://git.quad4.io/RNS-Things/MeshChatX/actions/workflows/docker.yml/badge.svg?branch=master)](https://git.quad4.io/RNS-Things/MeshChatX/actions/workflows/docker.yml) -A [Reticulum MeshChat](https://github.com/liamcottle/reticulum-meshchat) fork from the future. +A [Reticulum MeshChat](https://git.quad4.io/Reticulum/Reticulum) fork from the future. diff --git a/electron/backend-manifest.json b/electron/backend-manifest.json new file mode 100644 index 0000000..0bad21f --- /dev/null +++ b/electron/backend-manifest.json @@ -0,0 +1,3482 @@ +{ + "_metadata": { + "version": 1, + "date": "2026-01-04", + "time": "06:17:38" + }, + "files": { + "ReticulumMeshChatX": "9430b1f140db84c8749b32370bd055c049aa94f798b423788cf41879459a1587", + "frozen_application_license.txt": "988537f8e7c42331ddf7c807a20298955b93ea09785e4ed38cd4dd4ccc032c1d", + "icon.ico": "f0ca1240f4bc0bc6dfdedb7bdd03b4e39a1b25840ad5166bb4dc67864fe5f247", + "lib/LXMF/Handlers.pyc": "74295db6b2bad7a2c5028c6f91e0d28aa19e28e3acffc78f327acaca47cae108", + "lib/LXMF/LXMF.pyc": "04d3a37e01f5684d14995912db7c62866e9c5ecf65f51074fbfef2149df60ce7", + "lib/LXMF/LXMPeer.pyc": "c1bf6485ef9c8ce0bf6a105e4bf9b713e0d8d59d6fd98dec7c70c8a369576491", + "lib/LXMF/LXMRouter.pyc": "809f9aa8e1b28dc93c9e5e71a117e1881bfc20b2409c79b9fa82342788046095", + "lib/LXMF/LXMessage.pyc": "e3c2ea41ef33030eeced38ecbd11b19e992dc0c01b8368801cce6d3b56bdd58c", + "lib/LXMF/LXStamper.pyc": "ec531b5a12eba3cdf0be123bb8a71170f970b9592312d0a9d5cfe963609ad5e7", + "lib/LXMF/__init__.pyc": "ab464606de135b378a6d6aba61feb2f0b7e25677dbd75906ddb57400bd13a489", + "lib/LXMF/_version.pyc": "d953a723070a5dcd01029966c5610d486d58d4365e50a23b3865ec10f19744b5", + "lib/LXST/Codecs/Codec.pyc": "acca231e1b3caef34685186aec01419af0f3b5d5991e2c85df64a740863cfb4a", + "lib/LXST/Codecs/Codec2.pyc": "470e5a0ce03b314b4b29b8b34cdd0b9bef34d7cfdbea940b51e8a3de88f2d961", + "lib/LXST/Codecs/Opus.pyc": "f721244c0e4c239b2288b4a002a294dc8426ba7f267899cf1a68941e29e2493d", + "lib/LXST/Codecs/Raw.pyc": "0bc3bf59bf3ccc567aef02b4810a2c64a8485f03f5f7050eff67ac0200c30d19", + "lib/LXST/Codecs/__init__.pyc": "dbff677ed536f9c2b6e3ccdbdaa92a02497edaf6ab64918f53b9e4dc578a97d1", + "lib/LXST/Codecs/libs/pydub/__init__.pyc": "7ef852f560d1c887ed34c530f3a3ba6a120d1e0ee2380456b137de113ff33e52", + "lib/LXST/Codecs/libs/pydub/audio_segment.pyc": "643298d5b0257bbd9719b2a71bf290814539fa30f4620bc085db83f8646a07a4", + "lib/LXST/Codecs/libs/pydub/effects.pyc": "c399c5c993ccda5bbd701bf9010b57115b5e6bd56bb4c9f679773a186a54b21c", + "lib/LXST/Codecs/libs/pydub/exceptions.pyc": "e53e726f1bb7ee3ff67dfbaba9a71b08e8f78d3527e6ad0ec36005cf0d57b75b", + "lib/LXST/Codecs/libs/pydub/logging_utils.pyc": "5d2382ce56dead79e6635b9dbbb62276693b992b29b34c57c2d3ec371b00d81f", + "lib/LXST/Codecs/libs/pydub/silence.pyc": "ab74ad7e6daaa2365f7bbec4479319e65ad284cacdbf7669fdd19c42021cf6ca", + "lib/LXST/Codecs/libs/pydub/utils.pyc": "a226d924d5fc9ff157a64e58f786b10770dabeb3a802d0be361b32858a70ad4e", + "lib/LXST/Codecs/libs/pyogg/__init__.pyc": "3cc903976ff13d8df196c7857bae51eb424e1bb02233781e7428e12e28055f63", + "lib/LXST/Codecs/libs/pyogg/audio_file.pyc": "905fa028f062763120d257813fd844f1b25fc7a30715174da51d37d1263073e8", + "lib/LXST/Codecs/libs/pyogg/flac.pyc": "347fa08b44d70110ac31573f72a47159a0ef2ef0404ace28f7e3a9cee8834014", + "lib/LXST/Codecs/libs/pyogg/flac_file.pyc": "20e503470751e22f7a86df7e11fc6a782041749eee031b9c5de427547dfa4286", + "lib/LXST/Codecs/libs/pyogg/flac_file_stream.pyc": "37919027e7ff5f72d80872eeaf2cfcb6de39ff381c869a54123775aa87f08b6f", + "lib/LXST/Codecs/libs/pyogg/library_loader.pyc": "8ebb468e674f9837c0154fa8c40b454628b73f136d76076b684c2fe976a0fabb", + "lib/LXST/Codecs/libs/pyogg/libs/macos/README": "dbfc7b3afe61a41fba59e07d236688ca6d9bcadd9cbcdbee4fc268c4a64a0e6e", + "lib/LXST/Codecs/libs/pyogg/libs/macos/libFLAC.8.dylib": "f76564da36ec091dffbdd20edfd652b38cac315c92ead7d7371dabf8314ded55", + "lib/LXST/Codecs/libs/pyogg/libs/macos/libogg.0.dylib": "398deb4ce797a9b3a08d56081f6ec999c4c88cbdd50a36cad87d2f37ede7172b", + "lib/LXST/Codecs/libs/pyogg/libs/macos/libopus.0.dylib": "ff375387d3c50d384c4949d69e2bf1c19263ebc2aa77698c71bf85ba3d955f76", + "lib/LXST/Codecs/libs/pyogg/libs/macos/libopusenc.0.dylib": "d5d57f67c3912d9554641b5b1a30b111d36723ed463b91e76e7c6f7882767c39", + "lib/LXST/Codecs/libs/pyogg/libs/macos/libopusfile.0.dylib": "4bf93d3cfae4ac9b9bde446b3017d2fbcae2c936320ad8113c69cffc579d3982", + "lib/LXST/Codecs/libs/pyogg/libs/macos/libvorbis.0.dylib": "b43457ff25ec5a1abf3547d24aeb3b90a96ac006d85ae3e6b723bfb1ca465ba1", + "lib/LXST/Codecs/libs/pyogg/libs/macos/libvorbisenc.2.dylib": "40c730031fe4d201747b89e1f4291e4386b46f925d47b67c05e01aeb49f98efd", + "lib/LXST/Codecs/libs/pyogg/libs/macos/libvorbisfile.3.dylib": "fe499650bbe016beb8d5ce7672e4f46378ffd0a74fd5dc23ccb1e9f8f1ff5f08", + "lib/LXST/Codecs/libs/pyogg/libs/win32/libFLAC.dll": "6bc2027a54012cdbcd9834c18f6a30eb2b53b9ebef8e56b264f9e3a8c40c37ad", + "lib/LXST/Codecs/libs/pyogg/libs/win32/libcrypto-1_1.dll": "1051faaadf5576c8106ff9843db069c23b5ec9cd66e74ebcb65b7c6e2cf318e8", + "lib/LXST/Codecs/libs/pyogg/libs/win32/libssl-1_1.dll": "ec06895227b5f4b5618ade134d087953e0f06a35e8a7d9ea4217a11c5c6b451e", + "lib/LXST/Codecs/libs/pyogg/libs/win32/libvorbis.dll": "17e42fd237723b3aa824e6ca7aefa7f2d8eb7fbb536ea37dc3ecfea79355d4e3", + "lib/LXST/Codecs/libs/pyogg/libs/win32/libvorbisfile.dll": "78392a93e6903148d6fc8a7d25005ff8e22e394683ae5be7989509058984805e", + "lib/LXST/Codecs/libs/pyogg/libs/win32/ogg.dll": "b72338bf51835d7472f63ef3c6279a923d2127d6286576c62cc9bce7370c5fc8", + "lib/LXST/Codecs/libs/pyogg/libs/win32/opus.dll": "b4d47ccd5d2cb86f6fd9fb99da7554adc8e7cffdb873d48f607d407eec2033ea", + "lib/LXST/Codecs/libs/pyogg/libs/win32/opusenc.dll": "7a0222524b78f114555f18a1dee0ada25c60787de85cf443b1538767c6efae83", + "lib/LXST/Codecs/libs/pyogg/libs/win32/opusfile.dll": "275ead5c110cba4e9f98c841e22eff69882c5be3c1fdac280893e89ee38b0f11", + "lib/LXST/Codecs/libs/pyogg/libs/win_amd64/libFLAC.dll": "f59af83f8c64cc37ee523990da16c4135c2774fd6294a8f21dafc510099566b8", + "lib/LXST/Codecs/libs/pyogg/libs/win_amd64/libcrypto-1_1-x64.dll": "df6ee9b3db7a5e8302f2fdc00354cb258691af73398020003946fbbc592a7699", + "lib/LXST/Codecs/libs/pyogg/libs/win_amd64/libssl-1_1-x64.dll": "f218c99fdc3da374af464d437022639ed77eadb349b377f5fde1bf51a4345965", + "lib/LXST/Codecs/libs/pyogg/libs/win_amd64/libvorbis.dll": "ff676051b50b5561cda1701f6b84bbdd6f8cc9f36aeecb05dc534e73b91ff539", + "lib/LXST/Codecs/libs/pyogg/libs/win_amd64/libvorbisfile.dll": "a86b65a11eccd35a3802844f5abd2ea1c15bf3d160fb49d3dd18c540e08bee11", + "lib/LXST/Codecs/libs/pyogg/libs/win_amd64/ogg.dll": "3bfe098e8c087ce2d89e648be88cfdf91bfcb440ac312eb3d89788bd07cbcde2", + "lib/LXST/Codecs/libs/pyogg/libs/win_amd64/opus.dll": "776e40e3f5c1dbdd37281ddbdafd4eb82660420f764d6c3d5b7d4229fcf788ff", + "lib/LXST/Codecs/libs/pyogg/libs/win_amd64/opusenc.dll": "f00ad84ec2c01eb586081baec0277c8cd1a01c6bfb5dcec57d99ede0c3aa9e4d", + "lib/LXST/Codecs/libs/pyogg/libs/win_amd64/opusfile.dll": "216aee2dfc17e9e47da999a63c8af46d63f4c559ad978ba642d25f140b47b99d", + "lib/LXST/Codecs/libs/pyogg/ogg.pyc": "8872933f7fe0160dcea07ec3070bcdcce27643e5287505c4f80ef143b40edb4a", + "lib/LXST/Codecs/libs/pyogg/ogg_opus_writer.pyc": "efecf8635bc77523624af8d088188bbf533f1d4d776e02e0bb85b109cf831515", + "lib/LXST/Codecs/libs/pyogg/opus.pyc": "74934353ae62d9a4e045d8bed20599eb8510673b050c1de98c04d90fda933d14", + "lib/LXST/Codecs/libs/pyogg/opus_buffered_encoder.pyc": "17a2d9120557bcc275daed5df76115e18eb4686a470dfa3b1b8ce17fa3a03477", + "lib/LXST/Codecs/libs/pyogg/opus_decoder.pyc": "e8019d15360166c3054769ec0472344dbe356e1daacab65ca977a4c4c8565f5d", + "lib/LXST/Codecs/libs/pyogg/opus_encoder.pyc": "f32319239e2c3c7fdec33ac5ad8c3669496f79253fb141267f7b610f5e57ec09", + "lib/LXST/Codecs/libs/pyogg/opus_file.pyc": "ab3cd5904d9c0130d61521986fe3fa87184ac29f76eb5e256dae364c1a67e0ce", + "lib/LXST/Codecs/libs/pyogg/opus_file_stream.pyc": "ba4ef4091fb7b716da21beb89e53f0ec6fef5149c5657eca80e4e823dffdd744", + "lib/LXST/Codecs/libs/pyogg/pyogg_error.pyc": "93d150539deeb9074e39975fcca50ac3062db34ac7e8e434979473639ac98bb5", + "lib/LXST/Codecs/libs/pyogg/vorbis.pyc": "1a2b79aae0d16def06800b9655c8c5fd3ebca1748159dee68035cd859c21370f", + "lib/LXST/Codecs/libs/pyogg/vorbis_file.pyc": "5b4623a89ffe784a14a21eead2eafa3d62300d661213534a110bb4981fb74fa4", + "lib/LXST/Codecs/libs/pyogg/vorbis_file_stream.pyc": "6da0416ecae27c4aaa846cd4ee36a758b859d8203b69cd0775e5ceb4c840d976", + "lib/LXST/Common.pyc": "94a9d30a846e8a38fcfa000939b772f7b76ebb368f1ad6b82c393da5731dd462", + "lib/LXST/Filters.def": "9aaa83245e5091d5ef0b6d6304e477cdd9d44a28ba9e640b12200c754101f417", + "lib/LXST/Filters.h": "fecdf1bfbb97abe8a22ad99e2a1bee6822ef86f4d0eb1cbd9b31f6867d1f06e3", + "lib/LXST/Filters.pyc": "ef094f22a9ed2ec3315f140ba82644cd249f5928176388f231d434ff8325db86", + "lib/LXST/Generators.pyc": "62ec97d015a651678ef0ee2bc82c1cdd2b25ab793476d4fd24ae532cab973174", + "lib/LXST/Mixer.pyc": "ded75fea056b239ea77b63a8e54e09c0192d8a2b69c2aad706fa8aeed3f303fb", + "lib/LXST/Network.pyc": "3e0ac48a381b5ecc5039b5bb5bdd38538859a6538f2fff6ea397952a11313db1", + "lib/LXST/Pipeline.pyc": "edd70d610d57006a5e2e76704092ef671b0b72731bc2c21848f3a0b8b1a1d41f", + "lib/LXST/Platforms/__init__.pyc": "cc8e0e4150b2cf7e2f35bd59ede2c4adb1e74339ba14cf5c4e8427b6ead1a5f7", + "lib/LXST/Platforms/android/__init__.pyc": "774c931cd70272ef8052f2a1c60d3007e7c1b4ea6fd72185c7aa60de8cdc5878", + "lib/LXST/Platforms/android/soundcard.pyc": "4433b62dd6b107e4cf8e087bce8f046a36cfe160a45242a6b796ee065d144091", + "lib/LXST/Platforms/darwin/__init__.pyc": "7141f3a9f09b929b57a478bbd8cf2dcddbffdb8330689b9c1da6ecc6a516cfb7", + "lib/LXST/Platforms/darwin/coreaudio.h": "3f2682819c61bd1f80cd528f958b49b7ca842c69f766eb86467886d71adac3df", + "lib/LXST/Platforms/darwin/coreaudioconstants.pyc": "44fd15c416a0aff45bb936d48cb0779fb1742b57684e1ed989300e1d00d72505", + "lib/LXST/Platforms/darwin/soundcard.pyc": "2e2735a5da6e53b27d0d3dc8ebcc7f667f278de97a599e01df03f59f9cd52f21", + "lib/LXST/Platforms/linux/__init__.pyc": "449ce7c5eaa09566ca77dfdb255acdd0a8b398eb46c251135098ab209e12ac30", + "lib/LXST/Platforms/linux/pulseaudio.h": "7e0ef3774b7a32d4d6c9aa7431fe2e0905fe21762472786c009ce3a654b885a7", + "lib/LXST/Platforms/linux/soundcard.pyc": "eb26efec3f11d6a271899b792376790afc1451b59fd487af3dc26c8134553081", + "lib/LXST/Platforms/windows/__init__.pyc": "df5904c27d15b68d44c829f59215bd7d3eb702d8bd60abb1af4e9ff8bc5d4a1e", + "lib/LXST/Platforms/windows/mediafoundation.h": "554f0a53b4f8e38556ac1513f5cc0ae0cb022a43698b980aba456f10f28a325a", + "lib/LXST/Platforms/windows/soundcard.pyc": "209f1f2c05c9f843fdc027667d9255086960bc60d2cb156e48f6bfb9ea2f970f", + "lib/LXST/Primitives/Players.pyc": "8388709a2b9f5649115dc71e61b85ec299c5c2ef54ce67e9d2ceaa7e5be5a1f7", + "lib/LXST/Primitives/Recorders.pyc": "e97eb18db09f49e04d813bd518860bac7fbc8d6b6d6a4b62578e0b0d3e14339a", + "lib/LXST/Primitives/Telephony.pyc": "97202a0dee1ef1bea6e1e0394b4e9a8ab208fe6c685c5fd0ff9b31b972fa3368", + "lib/LXST/Primitives/__init__.pyc": "058952aa1b506b41592fbcebdf87af8b2e99dd55ddac9ba4e20b07c0da262fd3", + "lib/LXST/Processing.pyc": "bb151136ea68ff49aa77a04da63afdbefe6e2b48b6aa8a63847dc2c37bba3024", + "lib/LXST/Sinks.pyc": "db7058635f697c68e4760d05b433a28333b19dfeb796b3cb37227dd46408adf6", + "lib/LXST/Sounds/ringer.opus": "3ebb1cd472a2a812abb305a9a84cc1846d01568bc38a9843139928bac67a7ad6", + "lib/LXST/Sounds/soft.opus": "40c27cf33fa0a68ca19e92d7ed08bd9dee1bba2cccc9d67756cda0a1a6b88715", + "lib/LXST/Sources.pyc": "908879f22c36b596a57efd67ffb41bf79d915db1d69ba36f54e75b6d1dc42dfd", + "lib/LXST/__init__.pyc": "a805ef301058878874b64c44e845c8b4cee2e9492d3abc8126a09d38a44195f6", + "lib/LXST/_version.pyc": "1ee978520e88aa98bc9e756d2da35138ac63eb861f4cd36d733a9450d9e049a3", + "lib/LXST/filterlib.cpython-311-aarch64-linux-gnu.so": "5b3b878f455311ad6b7d4b095625b60d93177a5177cb4ff524e77b4222b7f055", + "lib/LXST/filterlib.cpython-311-darwin.so": "e0f4ecd1e10ee9b3958d38eb468f0b60e1843cbfb542122ea7d00ba9957843b6", + "lib/LXST/filterlib.cpython-311-x86_64-linux-gnu.so": "17c43af4f166660494c3ecae56282f441d292407d958beeb677f44338def1167", + "lib/LXST/filterlib.cpython-312-aarch64-linux-gnu.so": "4ff2da56abbb81d04e1866d7aa85d391251789f7e724857822a405a1a065cd00", + "lib/LXST/filterlib.cpython-312-darwin.so": "385f24564e42ecdd13c986ca67cbae22409e17cecc636c08989baa4d03ce8e83", + "lib/LXST/filterlib.cpython-312-x86_64-linux-gnu.so": "96ab07bbb5f523c4034b426ef371998a343afc3fea18a6cbc534b1ef51d257ae", + "lib/LXST/filterlib.cpython-313-aarch64-linux-gnu.so": "4ff2da56abbb81d04e1866d7aa85d391251789f7e724857822a405a1a065cd00", + "lib/LXST/filterlib.cpython-313-darwin.so": "aa2335b18765460ee0e547426e8ee1b282619aaef4c8b801446221130588a3b6", + "lib/LXST/filterlib.cpython-313-x86_64-linux-gnu.so": "96ab07bbb5f523c4034b426ef371998a343afc3fea18a6cbc534b1ef51d257ae", + "lib/LXST/filterlib.cpython-314-aarch64-linux-gnu.so": "4ff2da56abbb81d04e1866d7aa85d391251789f7e724857822a405a1a065cd00", + "lib/LXST/filterlib.cpython-314-darwin.so": "08fc0727de0156c9fd52ffdd7304878a49cf799d2febd19ef8fb671fca73630e", + "lib/LXST/filterlib.cpython-314-x86_64-linux-gnu.so": "96ab07bbb5f523c4034b426ef371998a343afc3fea18a6cbc534b1ef51d257ae", + "lib/LXST/filterlib.dll": "30411160c76e9650418ddb5ac86fdbc4663e7b71bbbd6575f2232dec1fe304a8", + "lib/RNS/Buffer.pyc": "ed53fb42dfff10b179ad4084b2695b2159c48bf906ded98ef2a480797a0e787a", + "lib/RNS/Channel.pyc": "7da982f5159db3c624353f00bd1cc669975ed4d31af76a07daceb9b17cc4a8aa", + "lib/RNS/Cryptography/AES.pyc": "70fb284c54cc3d28bfd27cd11283d51f9c4cb9641aa98b60bc0ea770dd27c145", + "lib/RNS/Cryptography/Ed25519.pyc": "d7fff5c54300427b33e2861fe61665709b46d9e26c9a5b3ec08916243eae288b", + "lib/RNS/Cryptography/HKDF.pyc": "c4e6eed44580156a61b3893f5db3622c619e28e9c451ddcb76efba04c8488993", + "lib/RNS/Cryptography/HMAC.pyc": "e81574d23eb623c1f6170476be4a6f289e0577d47de153a7e93bcde43630b545", + "lib/RNS/Cryptography/Hashes.pyc": "751ef4365177eb6ae3c48e98f941104a91176d45fde6e332716dac55ff40130f", + "lib/RNS/Cryptography/PKCS7.pyc": "58c55f80b74a6ea424ef617acf469f3f606a94de7edcab31d389ac5c18472141", + "lib/RNS/Cryptography/Provider.pyc": "e094b0903f46fe5188c86c5557475a037d6c42532c663ae60dc03f0d301d734d", + "lib/RNS/Cryptography/Proxies.pyc": "ee4169feac9dda12aa767331ed50b591428adeb6c607b45e85d32c9e8eb45b2e", + "lib/RNS/Cryptography/SHA256.pyc": "f8b364fa9477a4b8441b5058865275e3d154207fb76562724e8bad1f1b3dea82", + "lib/RNS/Cryptography/SHA512.pyc": "09de7e0c445a0a17d560cea1bc302daad7940815232c040f7e1087023b63f255", + "lib/RNS/Cryptography/Token.pyc": "959c176c68fe46a0a8dda807f420899c283439358048552470df631a1673b1e8", + "lib/RNS/Cryptography/X25519.pyc": "f6d9d5ed5649f73e539c63497185efa62cd1cc31e412c0549f32951af76bf99e", + "lib/RNS/Cryptography/__init__.pyc": "2f362a34949642147d77906fd5ec5b09fad7525c994c83757f19b8adb129677e", + "lib/RNS/Cryptography/aes/__init__.pyc": "55316ec98b22c5468e0f65428b7b69a147ee195b6ab2aa8b1498d7d268349748", + "lib/RNS/Cryptography/aes/aes128.pyc": "6fec214b5b8b36a3a9473b0105dc45ae8d2742b35faf0de82a374a5184dfd1f5", + "lib/RNS/Cryptography/aes/aes256.pyc": "b5b3d12a78d2cefb5493830d73dd1eda49984c788f94296e6cdf9647749b0caa", + "lib/RNS/Cryptography/pure25519/__init__.pyc": "c5be32350a6a87e0532e38809c57e2e8e8f0df8c7036f1b0a8400fa1c874a30a", + "lib/RNS/Cryptography/pure25519/_ed25519.pyc": "3c30b53de14a46f62baabc450a322791f7245465a4ee9f8813e07cd02fd7461c", + "lib/RNS/Cryptography/pure25519/basic.pyc": "1d51e1bf4531daf5300887981ebaccd253903e9ce5925973acd155579740bb79", + "lib/RNS/Cryptography/pure25519/ed25519_oop.pyc": "4faa1376044c618c167b6529f65c5f5c1979ddfecc3aaefd49b9229418c5ec7b", + "lib/RNS/Cryptography/pure25519/eddsa.pyc": "a87952dc9707c1d22744b883c7f403fc88822dddc1986b4c788b03941b7c6b7a", + "lib/RNS/Destination.pyc": "90d33f9a2c4bafb2f535db3e8de76f67836143aecfb1adaae4d7b4a236963523", + "lib/RNS/Identity.pyc": "095535372f45391e982470299903837cf7623ccd7b309ec5ea0439cda15c57bc", + "lib/RNS/Interfaces/AX25KISSInterface.pyc": "48cfee49c7fc0eb2015fa6c55904f0b3f36cfa89db3883775ac7aaddfe950288", + "lib/RNS/Interfaces/Android/KISSInterface.pyc": "2fe1528c83ce1eb0b7a6c1043fd53325bb503667ad44f8558708dbec4b3066a9", + "lib/RNS/Interfaces/Android/RNodeInterface.pyc": "8702037e05ca141e1048121f8be6841afbd46b561221036478883c77dbd9893a", + "lib/RNS/Interfaces/Android/SerialInterface.pyc": "122fbed38ae3af5d9deebc9b415684c4b0eb328e9d3b241fe411295ff242b216", + "lib/RNS/Interfaces/Android/__init__.pyc": "7e79bf911b3dc6c471f4bf234245bdc2b23b8d64d7a33a52f514de707ab11183", + "lib/RNS/Interfaces/AutoInterface.pyc": "4ad6756cce8398627deb91bb12aa8d831c9e9acc314fb08699ecc5d1186772ac", + "lib/RNS/Interfaces/BackboneInterface.pyc": "6a1c3234e775a7e2547cbf2435ff63419c809ff06262abbca790d2067ccaef01", + "lib/RNS/Interfaces/I2PInterface.pyc": "c0ae8c097906873a08466feae7bf45721e2df11825f1592c30f5ec734ce712f3", + "lib/RNS/Interfaces/Interface.pyc": "8a8a0e9d71a3b7a92cf87bf1aa27a09ae52227dd659252cb2c831d82f023dd08", + "lib/RNS/Interfaces/KISSInterface.pyc": "ebd2a73312021555bb5187b12bb0fb161781af52b777be2bf3d3f3066325f38b", + "lib/RNS/Interfaces/LocalInterface.pyc": "4945d82ec4d41a5de07618eff0d61a268d2f1e11e300a1e69b9d197fca8cab0f", + "lib/RNS/Interfaces/PipeInterface.pyc": "4edb85d898a171b376ed1beee91334ab2e3552447c723785fab1f7c2b2bc4317", + "lib/RNS/Interfaces/RNodeInterface.pyc": "d84597a265e5918c387036f14eb57f9b3caa25f299b84bd52b7e04f9d6c1844a", + "lib/RNS/Interfaces/RNodeMultiInterface.pyc": "870a35c88bac1fa240c7bdd657490d50a836840ea07478a41b45418c42d70aab", + "lib/RNS/Interfaces/SerialInterface.pyc": "8ef78b0d0bd7a4ec2df2d2a3b5ede66b64994c74ba803a3594a7f95e3fab73d5", + "lib/RNS/Interfaces/TCPInterface.pyc": "9be88ba76b2c16c1faaccb23733762e526a9e9cce02f8e51ab890a3505dfa129", + "lib/RNS/Interfaces/UDPInterface.pyc": "146376be7098abba59f49007b51a63e622e8336fecb7a6afe2edeac267838b5a", + "lib/RNS/Interfaces/WeaveInterface.pyc": "2e593d02a99aa04ef27778976f3f9cfd2950a1d49771e028b9703c63bb6eca5c", + "lib/RNS/Interfaces/__init__.pyc": "84a76244aab715c27e2d771b6bd7edc1149f9255e104ea32e673bf56e4afe5c8", + "lib/RNS/Interfaces/util/__init__.pyc": "676139600c93a45acd30c2db45a7e13fc6cd1378fea614a8cf7d20d2f421645f", + "lib/RNS/Interfaces/util/netinfo.pyc": "d726f74ffc911d3cdf3bd7fdf5626c515671172bae601d443fd9b2fab8fefe44", + "lib/RNS/Link.pyc": "09015a1e3b8d8a69c564eae0a2303e0cc250e88e0071a27a2cb3949d86eade93", + "lib/RNS/Packet.pyc": "e2c2d1e684236c8eae640297f050f65f8768d902c6bfba1c92ebe33eaa4f54cb", + "lib/RNS/Resolver.pyc": "d84cfeb6b60fe24b591f1da56942a0dba2bdb7f80feefce718229ea3776eec10", + "lib/RNS/Resource.pyc": "54477d87f078984f14e804883f51d7079033b2593d3b0f37649a1b2d3e9de904", + "lib/RNS/Reticulum.pyc": "427bf50af7faca0835cf314084ec5eb7015613f1d808518513a1033d392960ff", + "lib/RNS/Transport.pyc": "0cbc39333c93ca3b0474cd4a204828a6e90cb07411e8030a0e8fba87053a7500", + "lib/RNS/Utilities/__init__.pyc": "6c34814585e6b9bda7132b38e527c5c77573e3445daf785fad25e9e889dfb866", + "lib/RNS/Utilities/rncp.pyc": "1be237b38725c84396c64c449f701ace6f3dccd122aa5989c6cb1e59cb5b6eb6", + "lib/RNS/Utilities/rnid.pyc": "6068062cb718bbe51af667d2d1e1cba943b885a402fc7ccab7a0229441326fb0", + "lib/RNS/Utilities/rnir.pyc": "5a99c0efbe2c2057143794c715c4211081b4b2b0c0fac1695355bb530e5dabe2", + "lib/RNS/Utilities/rnodeconf.pyc": "8f07ab11b5f30462ffd7a84f1c3f929dcfa1017e132dc46b9f62ef69dfc1f37f", + "lib/RNS/Utilities/rnpath.pyc": "1fb252e6a16a62c023d62041c768a9394a5d61c02ef24ddb65272811300c1875", + "lib/RNS/Utilities/rnprobe.pyc": "a6ee36ad99e7de0772070bbc3cd9bac32952f75d90d16ae0517fd9ca40b9b856", + "lib/RNS/Utilities/rnsd.pyc": "67589673e2808bf507fe56cf72c5555ee7d733b5dd95ad06232aed657622a591", + "lib/RNS/Utilities/rnstatus.pyc": "dec25f9cba8f12f90ff5f07680f4c00be610415a7f4d72d6b2806c95ad2b64bf", + "lib/RNS/Utilities/rnx.pyc": "a0e5e3ece70f55a8fe0bcc192ad924e4a7dd0f6f65288eca3e2c62cdbabe45c8", + "lib/RNS/__init__.pyc": "4f05600bf585ca8295b5d83080e50638c461542d690ec5136a001f200147d219", + "lib/RNS/_version.pyc": "fe05aeaa0b837505b59fd691b6ef368d168e16513b18fe656a86f62b5b9aadb3", + "lib/RNS/vendor/__init__.pyc": "2bf3713f65f2c7091d60a86d916a8d9cf187de4241438423f4d584f48c4142d9", + "lib/RNS/vendor/configobj.pyc": "b678374e3484668ffc1525b837ca2b7d4ace4436b5f568f5db08983fea2e78bf", + "lib/RNS/vendor/i2plib/__init__.pyc": "5054871843488910c86c8b939288c934a736b95ae0886fe0c7cb9c9e824047fa", + "lib/RNS/vendor/i2plib/__version__.pyc": "0966c00b447b18e2cb998a324e4c735e11ff04c657afad19ffcbcd8144898c14", + "lib/RNS/vendor/i2plib/aiosam.pyc": "ef44d5194c983b45056eb098261d19bc986696cb2f85b8d3c634115c8f060f9b", + "lib/RNS/vendor/i2plib/exceptions.pyc": "5707a5f7bc1f509c9d799760b4f9f69f11e06942afd027afa79ab8070e8be65c", + "lib/RNS/vendor/i2plib/log.pyc": "04b4d68b9206bedd74f97626e43584b4b43b2776997ec6c2b0d221aca39f1212", + "lib/RNS/vendor/i2plib/sam.pyc": "d042c9e38e1b3f1f9d2fb7bae91fe82c0a7bad417fbc9c1354cc7492df8dc51c", + "lib/RNS/vendor/i2plib/tunnel.pyc": "e8a9e1a461512ad23d96f13e3630d52667142099c2ae0a59e7c422e2a58b3941", + "lib/RNS/vendor/i2plib/utils.pyc": "181e87ef6a6c4dbb08142c473e2e0650e30572c89d2dcc0026e369b9925b4833", + "lib/RNS/vendor/platformutils.pyc": "727d528b315568fe3530f4cfb92fc498fe95b60680779d7d57bd44d8dda45481", + "lib/RNS/vendor/umsgpack.pyc": "340d97a1542131ae13b17f99852c54adb27e7fba60c9a18ae753643cb52afdb9", + "lib/_asyncio.cpython-313-x86_64-linux-gnu.so": "51725a67046cd599d66b764c90d360df4d29e7bef725d62fd8bf72a5d203d7a7", + "lib/_bisect.cpython-313-x86_64-linux-gnu.so": "972df620dbbf776689fd3f8df4ab10ca5a3076af21cd60c812f3a3517ee6c825", + "lib/_blake2.cpython-313-x86_64-linux-gnu.so": "f78705401256c665f57033c634ae28995530f16ae5d557c17f0dc128d2d09698", + "lib/_bz2.cpython-313-x86_64-linux-gnu.so": "9dbadeee4af06be11affdc4bdb5780e0e5a8d7d7f02cf75b36bcea3d74e85d0c", + "lib/_cffi_backend.cpython-313-x86_64-linux-gnu.so": "4716712759d392db6b741965c28e4310c12ace1d30af457fb1bbe6eb53cd74a8", + "lib/_codecs_cn.cpython-313-x86_64-linux-gnu.so": "f8f13fe226a45f223675aea31af6e52218ac6e383e4e555f0d4ec74f774f61c2", + "lib/_codecs_hk.cpython-313-x86_64-linux-gnu.so": "8beeaf5d2bf69cf5f4e8d66edd3b84e8c938111e43d4fd5fd1c79473dd050f85", + "lib/_codecs_iso2022.cpython-313-x86_64-linux-gnu.so": "dff007f1f0fefc89832963500102cf08922d189e1e8b27ecb75d54bd07c6f1b7", + "lib/_codecs_jp.cpython-313-x86_64-linux-gnu.so": "51f266342c185042523f9e05b17c3c7eea9fb3a259f68bd1a0525d0980705824", + "lib/_codecs_kr.cpython-313-x86_64-linux-gnu.so": "ec3fa0d99c5d841cf34a0eaa9d8f54a1b5d0041368a85eeff869b6e8aa051f8d", + "lib/_codecs_tw.cpython-313-x86_64-linux-gnu.so": "04b3d1d2513a45d449fbc1d2b8feba7b07b1b0b91edca9d36151b14d8e808b62", + "lib/_contextvars.cpython-313-x86_64-linux-gnu.so": "abc8fa37c2bf485582dbe883eac21e1a49cab32aee11ba72537e2cc3106e70c3", + "lib/_csv.cpython-313-x86_64-linux-gnu.so": "2c6ad82fe1fb34703b86449cf89c5e62378b209dd5647e5a4cd9ad394aae377d", + "lib/_ctypes.cpython-313-x86_64-linux-gnu.so": "991b63be7ff14aa4278cf662365aacfc4afad4554ed1e39865e70ce24ee96061", + "lib/_curses.cpython-313-x86_64-linux-gnu.so": "6fd228464cb6d61105059431da8f24683b1d47d1d0720473346fdec5adf29069", + "lib/_datetime.cpython-313-x86_64-linux-gnu.so": "82c83f9bcaaea38bdb374a5ad4f62e1822b0481fc6e59224813b9158d4da5cb5", + "lib/_decimal.cpython-313-x86_64-linux-gnu.so": "7eb0af22e5a866ac3cf7412bf4bd157a5114df9ac888ba49eb54a3ed61f6a30b", + "lib/_distutils_hack/__init__.pyc": "7f8a888ba104689b707fe1af06b667fae294bbeeab99b91954ac1d1a91c0ea2b", + "lib/_distutils_hack/override.pyc": "3d7372f60c3cc4996a29e5e70fb8d560b0aca8a39c98c0475a4479df78d47392", + "lib/_elementtree.cpython-313-x86_64-linux-gnu.so": "73e7848c9f900e6a0ba9bff034c5e11068bd46f6ce98a005ccce3612e12b4ce0", + "lib/_hashlib.cpython-313-x86_64-linux-gnu.so": "3f80e2989c979901ad7e9e7d795c60bcf0d1b45cd133556131a1a1c432f722f3", + "lib/_heapq.cpython-313-x86_64-linux-gnu.so": "e5abbc4e6d74608adb68ee1f6f33d7d5f1794a3e1c0a4d1753e483b8b8ca838a", + "lib/_json.cpython-313-x86_64-linux-gnu.so": "52c060b43b08e5bbc4664bb2a4a198903f67d186bc65db664160c42573327fa3", + "lib/_lzma.cpython-313-x86_64-linux-gnu.so": "412466e43956c0d8e75919e69d2ddfd37d60d179a6f379bd3ecfabef384d61a2", + "lib/_md5.cpython-313-x86_64-linux-gnu.so": "44d5cfaa0450cb65c323637dbb028a96203117cd7e0f4f1f67cc71032d03418a", + "lib/_multibytecodec.cpython-313-x86_64-linux-gnu.so": "c0b5bb3afa16605d0c8d8ed0680577763f3f886d4b67d703647858d8b77186ab", + "lib/_multiprocessing.cpython-313-x86_64-linux-gnu.so": "b0e738a5a84b9bf2bc7f6f3074ed5ac6650fd56f7d3d853830a36d61e66e68a8", + "lib/_opcode.cpython-313-x86_64-linux-gnu.so": "00ea2a7a02e8c825de215767807f9f5ae3183574e456f6e02026dccfc9d923a2", + "lib/_pickle.cpython-313-x86_64-linux-gnu.so": "6018f20614760ae0faddc236761c047548a589b973b37c8507706e1dbe9cc8d9", + "lib/_posixshmem.cpython-313-x86_64-linux-gnu.so": "8912d63fade49dd18c33c5859a27dd7816a728293a5add98a4e33aac2736879f", + "lib/_posixsubprocess.cpython-313-x86_64-linux-gnu.so": "e8d2ebf716b36c128da9f3006099e92c7e1e13940ce3a94dd16d2d907e54f728", + "lib/_pyrepl/__init__.pyc": "5aacfb2fcacb3c8626cb7e10926c0a3ded501211582c2d5fd92f03534cf85810", + "lib/_pyrepl/_minimal_curses.pyc": "6d9cc212a0b020729fe06bb31234e40e1e13fbe65ae1161a1882f145cd2a4ce3", + "lib/_pyrepl/_threading_handler.pyc": "7e0ee7f0cd00e31f3f17f09f8843b544fdbe785ab3bb7e9c877584da0629158f", + "lib/_pyrepl/base_eventqueue.pyc": "3094fb40111ed58948cefd0d26a66ecb3bebcf696a2e5fc4f8f3126911129e6a", + "lib/_pyrepl/commands.pyc": "16ef8b5c03f30dd953cc1dff1bec47d764621cb954dc493d65061bb2ec166f68", + "lib/_pyrepl/completing_reader.pyc": "b2653f6f77711ad502f5ce4bbc22035e63c6125833ded9cec129d51f66935432", + "lib/_pyrepl/console.pyc": "b3286a100ff070c92753f1e7c630439cd48557c1bb63635c2da802a5fab78e5f", + "lib/_pyrepl/curses.pyc": "d421c628d1973d0c405c5ad183e63b8c60172f2aac083d0d74f42f58a76cd672", + "lib/_pyrepl/fancy_termios.pyc": "dc6cda7ca2cf030795bdbf1fce9cb488e2fdef52e26932239d363d9ba0566e1c", + "lib/_pyrepl/historical_reader.pyc": "da281af2d986470c6dd8d56135af048f5423125e560f7892dda80e99a44b679f", + "lib/_pyrepl/input.pyc": "f0d2443689cbcc6072408199082d9cfe4cd69902d52f84365b013f36724e7a4b", + "lib/_pyrepl/keymap.pyc": "46f08fe7addd9fcc6b6d8642fcdb69b58ef53b6accef38b957b7368989757c8b", + "lib/_pyrepl/main.pyc": "1df72bbfe11cece19b11c6d7ed249236fe0b7b7f84fa92c7ea06bc5509d1685c", + "lib/_pyrepl/mypy.ini": "031601420323bb94aca7befe8dad6e9d2af13fa6994ed98c3a93ac84890a499e", + "lib/_pyrepl/pager.pyc": "4370571eaa454a98a73f0fe0fc9d27ed12649ec92a3b1ed1556bb83e069b292b", + "lib/_pyrepl/reader.pyc": "8e74707288af9d5f2a694b0d622f20a1e2660bff703a0abe9b050f8c45be04e0", + "lib/_pyrepl/readline.pyc": "744451cc88e2aa50845604ef0cc97c65cee13292d8b5b993362eb2dc77f75f80", + "lib/_pyrepl/simple_interact.pyc": "4d1c696213c126807fd560e558991d48386dd73e060d1973d0fc5b02370e7f46", + "lib/_pyrepl/trace.pyc": "4800f9d624672571005815bd6183a955275c877e9f376c092e3356b863ae44e5", + "lib/_pyrepl/types.pyc": "b3cc471e0bbb4d27ab5dc7b43480d2a368b41a7f4b854164b1ce171562963368", + "lib/_pyrepl/unix_console.pyc": "99b2d58d10e00addd7b8d237a2c7352e36cddbaa6f5fdf4e04a585f22caea4cb", + "lib/_pyrepl/unix_eventqueue.pyc": "0426f676ad67467d8ede30c64c64bec07c22208797d4727e17304c2c872e8491", + "lib/_pyrepl/utils.pyc": "012b3f07b4a9ae5f0aff1e1d8c950d69453070faee63316dece38415f75443f0", + "lib/_pyrepl/windows_console.pyc": "26ab6ebfc026d674906129500a075053b750496a0bc367acd8a1d08f37c0fd17", + "lib/_pyrepl/windows_eventqueue.pyc": "9a26d47327c4a19b287cd8f7ce452c8724335ffba673a653b26eb67e28bbf6bc", + "lib/_pytest/__init__.pyc": "9ce5027f107a0ddbd09c15ee09e2d677ec1bb9988e34c8645f116c082d8c9306", + "lib/_pytest/_argcomplete.pyc": "4114c39ae194caa3d626c0836ab8983dfe3033864aa3a2455d833e90fbe28ef2", + "lib/_pytest/_code/__init__.pyc": "8efc831307e7cbaab01b4ef165c1e0b40fd515383785ced848fae81d51c9a621", + "lib/_pytest/_code/code.pyc": "26f17d5da78fa6a2a993259d88106d0a3e66e9e712b47527434390089dfa933d", + "lib/_pytest/_code/source.pyc": "7a5753f2a5dfe08846317bfc2095cb783b49aa49ad3b67ea3244f147785abe5d", + "lib/_pytest/_io/__init__.pyc": "be8438c325f54918d0d79c2ab4c7e231ee2cd7c8b02a08d79b5fd20cf5a5d990", + "lib/_pytest/_io/pprint.pyc": "a74bf4a44099092e3d35630b6f649e626a8469882945c6172883b6c6d3e5f414", + "lib/_pytest/_io/saferepr.pyc": "48e93a0d5b0eea30d1d4cfda8cfcea61cc2b3cd702a0e671ebd52b44bd1fd82c", + "lib/_pytest/_io/terminalwriter.pyc": "fde707049f944cf525bfe8a5ec2004a9f139d79e3826863ddcab2e19c1063516", + "lib/_pytest/_io/wcwidth.pyc": "ab274b6930e92c3435537e0779aeb857472d742325ba64ae99817ae5ab8d2dc4", + "lib/_pytest/_py/__init__.pyc": "aac35b87917f464e4d4af2e0708e7058934de1c4b4ee281a0aebf877163b70f6", + "lib/_pytest/_py/error.pyc": "d4a8e165fc2b4fd4a5e163ff1adb1ed800c2c3204f69a4db3c7aca4e2024ba31", + "lib/_pytest/_py/path.pyc": "4eae11a3118681667fb24d06d6a4481f1fde56006103462765ac9efe35062b30", + "lib/_pytest/_version.pyc": "92e062094462f3d75feb1d520731f591745ddfd256f1df1a101ef20b6fd52f93", + "lib/_pytest/assertion/__init__.pyc": "fa37a7c36c304f560999cdbf734a1017f5c189a32d645437c2a070d714e07c5e", + "lib/_pytest/assertion/rewrite.pyc": "bb8eaefb532621ffefd34dcdc8bc299ac0d25648f9533852891c1e50059679c0", + "lib/_pytest/assertion/truncate.pyc": "955445622c151cd300b3792e4ae2939e89247f2a4e41cecc8e961893ed01ce6f", + "lib/_pytest/assertion/util.pyc": "8e6fb72edf0340f4c97c6ff842f26c3a32d9402a626b9a52dd8a4ec295ad4dd1", + "lib/_pytest/cacheprovider.pyc": "282405b6b61b00edf0f56ac2ee710904d5bdc7cedba282b6827d83e93d1fa9d2", + "lib/_pytest/capture.pyc": "55325015399c338c79db198cb32f46e5a20a562d1764aef5daea5d47d57ce042", + "lib/_pytest/compat.pyc": "0a699c1f83a54f6c79861e2d0fa3ef8ee3ddbbbd2f96f184d893229545f6d9a8", + "lib/_pytest/config/__init__.pyc": "90eb8b827e58a75d8dd9b235a7f2263fbabc838b2c70475dddde95e1e3a64522", + "lib/_pytest/config/argparsing.pyc": "4e751b257706fcb55484416c1a7de5d7168028e867698cff009e65f15d647ea0", + "lib/_pytest/config/compat.pyc": "bda1c874821f4fe9d5e9183da6effe6318c93ce30e5c777345c8c7c1cc0d63cb", + "lib/_pytest/config/exceptions.pyc": "9bd2ff8a86a12a44846e24469f0a03db64483e2dee6787002031250b8c2f9c58", + "lib/_pytest/config/findpaths.pyc": "5bb9ea26ed7ac8a29b31e2200e72e4dacca88448e07b1fc7e5f974b499d56046", + "lib/_pytest/debugging.pyc": "3250c9d45d9faa35300d4d11a4718f13548615189774979e0d06527452ee62cc", + "lib/_pytest/deprecated.pyc": "8def2f2f560cd73d86305f266cd326b6d4237076ad4744ee0f5c3b8212da96e8", + "lib/_pytest/doctest.pyc": "0b474942486063352998da9b698a7957101b6988adc3352ff652e921760715b6", + "lib/_pytest/faulthandler.pyc": "c45e530194225df737f7b95f1ca8495b610ed4f2d17e1b2c8637c16378188898", + "lib/_pytest/fixtures.pyc": "321be9498781cb5451f96e3f714281bb4382ee7cdf9e9f754ca13944b30370e6", + "lib/_pytest/freeze_support.pyc": "0a4e597aa5717f505f6e7e70fb079a487f897c71db6a73c009c94f320b8c39cd", + "lib/_pytest/helpconfig.pyc": "d5f9254fbc0cff74a1ea805331472871b40dde443d9090c35e08e01d0ad99fb5", + "lib/_pytest/hookspec.pyc": "9cb1dc5980e8b224516829cb63aa06579e306b782152999a3e7a51049e83da83", + "lib/_pytest/junitxml.pyc": "84ee764c5868f999f8ba06a2f8c0b7ff9e134cd502e1e5f0bbec0e1932d586df", + "lib/_pytest/legacypath.pyc": "9ef239b75e4febeb422ea221ec04653d26ebc2cfd0dee84b3081ada9069f98da", + "lib/_pytest/logging.pyc": "76261d9fa5308c4f13ac5b0d2d2fb99a4bb9391bf9650240a7e74e618296101c", + "lib/_pytest/main.pyc": "6963b26414a8712a43c0916b57ef2592bf54d4be8a1c5197b51415a57bfd274d", + "lib/_pytest/mark/__init__.pyc": "62af42c9f0e454ff25774a71d74f613af656b8a99a4f367624ce4f711a2ac9a9", + "lib/_pytest/mark/expression.pyc": "f2e803f68394f87d90eab868ee63cf105d5ab0b124f21494ec80c9621e89ffb0", + "lib/_pytest/mark/structures.pyc": "c05b7d90053884bf32f6c99152fec34dcead76befbb87f27b28d367395a51a32", + "lib/_pytest/monkeypatch.pyc": "1832cb6dd69fc88d77fa0cad2ca69e296ec579b3dd7fb3b3a0223b2d0bc56edc", + "lib/_pytest/nodes.pyc": "dc35f289fac8ee5e9c9056a1e687993e6c5c96f42329a3f047f3b58dd0c2e8a2", + "lib/_pytest/outcomes.pyc": "b16f979563a2c479630f0e4e3c4fd233402d20ee3f6be856687e5c9ecebce013", + "lib/_pytest/pastebin.pyc": "bd0ea023c771ab9bfa27797d9b87fac5fd705dbd32d3ad3a93915a55062b40ec", + "lib/_pytest/pathlib.pyc": "7511644ca2a9ae5e799627eded01b7b65c86f64e69a8c521553449ffa323a752", + "lib/_pytest/pytester.pyc": "a7388ed97655ad8c877f7b9a6f79b31e5fdda9a95cf2de31be7a8550d3a2a6cb", + "lib/_pytest/pytester_assertions.pyc": "dd646c219407bda501132b9229e6be2b67fa96ddcd9011f4f48c373d123337c6", + "lib/_pytest/python.pyc": "0d78aa47c9041f052886f4043322c580db03173f2cc8ac5ec2bacfcf5ffba9cb", + "lib/_pytest/python_api.pyc": "e02aea39c7278c79fdcc6f05de43d3006886feeb151fb99283bbf6fe6cbf99f5", + "lib/_pytest/raises.pyc": "4811b827c2ace02076e04df0434d666133a544adbe633c58088e8dbafacc88c2", + "lib/_pytest/recwarn.pyc": "de413d52ba6732bcda09370fadb0f17a0ba9fc87243abf2ecb89564fe98e3c77", + "lib/_pytest/reports.pyc": "9750ded196386350aea2b8b84333977720ffbe112fcc400eb66b4113103473e9", + "lib/_pytest/runner.pyc": "489b8471ca667385cc9bfbef2b8a6c204b58ef6ac8efa526484f69b3ffec524b", + "lib/_pytest/scope.pyc": "08dccbb770b15b3dae2fe62d651643d49995aa575662091137906e0355573aee", + "lib/_pytest/setuponly.pyc": "edf6f429a8c92e4576a370d2a709421939c72aac3d0cad41ffd0cae0d6e0c561", + "lib/_pytest/setupplan.pyc": "8f9068f51d37153f6e5e540818ec8ffe3eec04547160b5a4072f61cb27d16579", + "lib/_pytest/skipping.pyc": "8ed7015fe8200eadebd0f0b4ba9d35344f112f2a8a2f83c92cf66f485d926588", + "lib/_pytest/stash.pyc": "0fafc3f0379906defff0a440187da66e3357a5dba417e7158b6c02c719327a18", + "lib/_pytest/stepwise.pyc": "3a29f3c7d4cf077b11eb36b190694bd26b6490e426fc1da4c61a8c5fa76b3db2", + "lib/_pytest/subtests.pyc": "e9198140d2b6b3b042e75108eb9b4cfad17a304fa42ba95f2d1d5a3ad812b0da", + "lib/_pytest/terminal.pyc": "a089a2f6ebe0c13e8fb3495d1ce471d25b7210affc89c8dc2cd852d7f41a397f", + "lib/_pytest/terminalprogress.pyc": "390710277710110ea168001940a01f3979d03d89f1a8b63db6689606d158a8ba", + "lib/_pytest/threadexception.pyc": "8c7eb43abc542b225eca4416c111088fc2a88ab7b13b70942a6dacfd0ec7c40a", + "lib/_pytest/timing.pyc": "385007b45d63201bc7b2f2a81ebaaff52c38b783abd22ed50516c35b85f28e7d", + "lib/_pytest/tmpdir.pyc": "91a945e5be00d6ae78fa6aed51362a10a69210a7216e31c8fadde1ab6e6e9f00", + "lib/_pytest/tracemalloc.pyc": "f347f15f5bc8231574ee5158b99cf46264ca36eb2abce35b1e2b94f4921e779c", + "lib/_pytest/unittest.pyc": "bc318e8a401edcf25befea4736540fb26a942798dbff50071c5e816c5aeea2c4", + "lib/_pytest/unraisableexception.pyc": "855b0adf117611a7b7aac4cf132a243e5d35cfd20be2b47c573d1ca8572ba189", + "lib/_pytest/warning_types.pyc": "0a540190eef5978a83bd36635221219b01590a93a132c024b4f8a29291289d5c", + "lib/_pytest/warnings.pyc": "193bc3f2d6491043309ac9defe2ce2acd4da4a7bbac391b746349ea1f3fd3f8f", + "lib/_queue.cpython-313-x86_64-linux-gnu.so": "845ac5850526cb01be5dfa7a22dfbab6ac667ddc1d302cc0ecd6cd47e4b1b551", + "lib/_random.cpython-313-x86_64-linux-gnu.so": "ef4ea1f17f18a5b75e892f43c13a035ac87ba329e578d1ecda2b9ea9f3b484f6", + "lib/_sha1.cpython-313-x86_64-linux-gnu.so": "b96866bc169f1dcad443152a7793e2170b796375413a5c151cc5a0d6faef185a", + "lib/_sha2.cpython-313-x86_64-linux-gnu.so": "9d410aefabb567bffbdb40d6dd7c95c51606241cd176ce2db149d0502b8455a0", + "lib/_sha3.cpython-313-x86_64-linux-gnu.so": "981ceac4b8c865856989167a1957a39506f39e78806b7916b5625bd8d5a360f4", + "lib/_socket.cpython-313-x86_64-linux-gnu.so": "7151cbf809c2eb453af6b3a68cb1c50799a5fcae73a9539354809a88931f201c", + "lib/_sqlite3.cpython-313-x86_64-linux-gnu.so": "bc9e073296945a6ade1f72639225096c3e0c672933d4a2465451759265caa625", + "lib/_ssl.cpython-313-x86_64-linux-gnu.so": "940c02cfdfc0ed2163179b5bad699cf4e9e7ad6b7b95cfb606124f5a096a7e87", + "lib/_statistics.cpython-313-x86_64-linux-gnu.so": "0591dcaf3805c1b76d76f7a2b3509fb998b09a0b68a87a6d86efc104900186ac", + "lib/_struct.cpython-313-x86_64-linux-gnu.so": "87e222c32c9aaf792e63b9da638da1c11f24b8af765fe3a1ed4d5eb9d49a9038", + "lib/_uuid.cpython-313-x86_64-linux-gnu.so": "fcab30adcec4e0c3ec4fd9cd06f97e03c0bc768109df0bff3e03311675c9fa4e", + "lib/aiohappyeyeballs/__init__.pyc": "e3770eb11d98275e8cdc59722b059517355adf0c664c8f5c551eae3e216c8fa3", + "lib/aiohappyeyeballs/_staggered.pyc": "497ded282a87bfb901a526f32e6787bba5b40705b4fc5b135d794ff2a07e3bee", + "lib/aiohappyeyeballs/impl.pyc": "198e412fe25f40cce4768b7be92eec7fd7b8bd97e1fe5826fcb20aaa7ffb7592", + "lib/aiohappyeyeballs/types.pyc": "f963e38f20482594dce16f291c6cf07524453ad8a17bd5c741e50d3b6689eaa6", + "lib/aiohappyeyeballs/utils.pyc": "2239977da2752cf19a6d435930b0e32df10d2ba4081760a542e0e297a2322dd0", + "lib/aiohttp/.hash/_cparser.pxd.hash": "a63b3eb045cdc3f7a28d718079dc06f811e7945a7c07bb0e0a051a80859a5360", + "lib/aiohttp/.hash/_find_header.pxd.hash": "fe66e90fabccf825422aadee954bec380cf959da3cf30ac3cdfa4eb0c41a30d0", + "lib/aiohttp/.hash/_http_parser.pyx.hash": "8eee031bfb8dbfcad30faa6edc8ba7135cacc7765b1f83a38901d46ff5114a80", + "lib/aiohttp/.hash/_http_writer.pyx.hash": "f6dc4e87bb7b737cbebcb9a2b84639765b665ef128d0263253853ce77cb2bfd1", + "lib/aiohttp/.hash/hdrs.py.hash": "bfa21a29bb318ec750c41ce16f90233f4c7ff46deb51ef380fb6af7fb008e1cb", + "lib/aiohttp/__init__.pyc": "f6c2edac228ef2b911ba5001f4604fafa2a4909a7a6d2688750f9d941dd25cc6", + "lib/aiohttp/_cookie_helpers.pyc": "22ab6c4c38ce5b7856e9cca8b9273850cd5df3bd7cc5b4d04c0064f1d1c6564f", + "lib/aiohttp/_http_parser.cpython-313-x86_64-linux-gnu.so": "697bd90559b7622efccd2ee06cf2739f6b77ed0ce5d22af22a53179641397d0d", + "lib/aiohttp/_http_writer.cpython-313-x86_64-linux-gnu.so": "8736b519e3a8fe5e752e824462ad124821e5012069ee443e1df8550f0c2269b3", + "lib/aiohttp/_websocket/.hash/mask.pxd.hash": "634cc175d93f724de98bdf8117331ca6472f08abf0bd9e064ed6456fdbb59f14", + "lib/aiohttp/_websocket/.hash/mask.pyx.hash": "f74a30a5760cf3f90899ae0a51c3b18564a4f94bf8355301a0261e14cd41dddd", + "lib/aiohttp/_websocket/.hash/reader_c.pxd.hash": "e717f7a286e4eafc78c5b266fb1b59d7f42e7c1f1f605b4b415d8c35da94735c", + "lib/aiohttp/_websocket/__init__.pyc": "7805951be217b568209d7ed502339284758d5d31d18b832c2f2a090d24898389", + "lib/aiohttp/_websocket/helpers.pyc": "5970732739aaf9522415ac448f98f95938f68b6cbb448b12d563f5c3ead4e4f0", + "lib/aiohttp/_websocket/mask.cpython-313-x86_64-linux-gnu.so": "7b61199dcc3562746e2109fd3bff9e652a2c7607ba8b0a86d7c72475ea9dc759", + "lib/aiohttp/_websocket/models.pyc": "d94b4bec024acd8969c815d9d721d59476e33a21e7875f71077cfb7176124932", + "lib/aiohttp/_websocket/reader.pyc": "71048d60c0b79244bb3da6353d8501462f365b0a66d6fdeb0331f703a62d006f", + "lib/aiohttp/_websocket/reader_c.cpython-313-x86_64-linux-gnu.so": "fedaf70e88678ff114a0918890e552f6af40931abf58747c649c2cd56ed0435e", + "lib/aiohttp/_websocket/reader_py.pyc": "a27d41a86fd347f110aceeda80fd0406cd7e2ceb89b6c724c5f3d6be87565995", + "lib/aiohttp/_websocket/writer.pyc": "b1071edf7a49d048f9014efe3a3aa717d223da80432943bf374a1399686570a4", + "lib/aiohttp/abc.pyc": "8eb51be9dcc6795fd86f2e63353a494489c803d50e43433be73435a7df9b903c", + "lib/aiohttp/base_protocol.pyc": "388f43d774cfd13c1ed6a1c3d92a589aeee4e3f7c33a8812e434cdd2bb52083f", + "lib/aiohttp/client.pyc": "fb5f2e35bd99b502bb82defeb343639e945e7141b49f85df606c3a76f9a92250", + "lib/aiohttp/client_exceptions.pyc": "9ca276967149ea894e85ae748fd4c4d7a1addc3f4e44121fb653f875c4847e00", + "lib/aiohttp/client_middleware_digest_auth.pyc": "300342cb45d1e6085ff59eec1ee12e80a93a9cfd81e067e4950f02342a8a0be2", + "lib/aiohttp/client_middlewares.pyc": "ea5730f06d8a0d756dbbb55a010e9945cea7011b16980a1e6a02069e4f15bcc4", + "lib/aiohttp/client_proto.pyc": "17d7145503cd8cad4fdb3033326f7b4861801d6383fba82a780d306a3b0e906e", + "lib/aiohttp/client_reqrep.pyc": "5048e7cb83de87488f8887a355158923d10d5b47a0293e6bee58a1e878d2f09f", + "lib/aiohttp/client_ws.pyc": "6cec970505d5e62635d196e40c5c757f91c29fc2fb4abfb3b5849a69a020aa1b", + "lib/aiohttp/compression_utils.pyc": "a4f9aa4ed4af193d6d40aa862ac1060c5926b40c909b85aebe3f89b80d1b0fdd", + "lib/aiohttp/connector.pyc": "df2ea9b90ccde6a4303c7b89207a9140fe2b568ed8c884eeee29638928fe605b", + "lib/aiohttp/cookiejar.pyc": "c012cecd27b64f13d3466d2a8fcfb4d80763deafa15263c158d2576eab612a75", + "lib/aiohttp/formdata.pyc": "a0d00e7cfbb9c585572b096ad95840f212d5d8ed39b5331a8f81e8c7cd939825", + "lib/aiohttp/hdrs.pyc": "a940a39ca9f8ef059abbba83945236fde6bd74343952c06201b0449cd74170c5", + "lib/aiohttp/helpers.pyc": "8439e842e4a0c467f1630cf7cdf40680c681f7bd5454aae94968c17c14861686", + "lib/aiohttp/http.pyc": "c11009368d0817f02f4d456d950e681fdda16cf17164fc46235dbbe89955444d", + "lib/aiohttp/http_exceptions.pyc": "8fb64864e9d71a079a4115dc5ea419ed0be2f1859e8dcfd2261ef4aa3d791800", + "lib/aiohttp/http_parser.pyc": "407f7483dcf313c6bb82bcfe43b20163f500d1c6fa84ff0915b3d919f996ff89", + "lib/aiohttp/http_websocket.pyc": "6dfb5d805fcb5aa7eeef3cc8c1ea5f6adbc53d684149125ce6bce4fbd3ba4c01", + "lib/aiohttp/http_writer.pyc": "c78f886493708828940a4f90a5e9bdb8f0ec46202140983e03cd5b0589465805", + "lib/aiohttp/log.pyc": "3cb179125ca655be5b06ab5325dc635fd0d0771aaedb31fdcd5d31bc6336438a", + "lib/aiohttp/multipart.pyc": "db5ab1b512a2149d50c0901294afc3f23135384700fe94b8f2159bfe5218f242", + "lib/aiohttp/payload.pyc": "75002819216e62ce1db0db8bf13fe37ed2bb183661a0830e2c7097c2c69760a9", + "lib/aiohttp/payload_streamer.pyc": "ba4fcd20e3dee68c7dab486e886cae1669258ea193a663a627079056f2727711", + "lib/aiohttp/resolver.pyc": "3334292b2743c9450ef8328e76204cd76d997c93b5be108f8c0ddbe56dc8b757", + "lib/aiohttp/streams.pyc": "537d33c7386b464407e9ae9373e7a9e072faa209b70209635ae078ec17e1e10d", + "lib/aiohttp/tcp_helpers.pyc": "59c850df8cbd8b9d445597b094f9fb0f84712c62f2506466a0df189923e4a739", + "lib/aiohttp/tracing.pyc": "e4776b41f1bac0b33d51a5188e1f5573dd865c8d3d501e69f731866373c8fdea", + "lib/aiohttp/typedefs.pyc": "17b4dae74a0e93cc8eb29ecfe31594fdcd2ed69af2668cc47c9a6ba40817aa33", + "lib/aiohttp/web.pyc": "5482534081492307b7c5546c726658292417cbe37947e463ee48a98c990b4dd4", + "lib/aiohttp/web_app.pyc": "84278841ff98d35c3b8c75a05ba8a4ba2d7871f5d6467ef354857ea1b3484d65", + "lib/aiohttp/web_exceptions.pyc": "9a05a24667459b5f8dab379ae42f5afa7ba741d3945a6f38118afef688d910e0", + "lib/aiohttp/web_fileresponse.pyc": "9ae9d35f70ebbec32aab1314b64056df55d0c5a94bdeb4566645424ab9724471", + "lib/aiohttp/web_log.pyc": "aae2b20ae005cc8cfe6aeafede07c140bfd70c91b6d1d053daf41fc92dc8a9e8", + "lib/aiohttp/web_middlewares.pyc": "28e58c3b3e953b1fb6fcd9f71044d347778ad2bf26f683f72e63c03f3f2ad958", + "lib/aiohttp/web_protocol.pyc": "8462e88e3b1c08d689f5bfc79e3cc18ce9235f60dcabd6b3fe11b4bd0a9d645a", + "lib/aiohttp/web_request.pyc": "0e46a92a8da8ee26f8f5c084250e3b2b22522cb97baaf2937db9d9ed834a5fa3", + "lib/aiohttp/web_response.pyc": "5e3cdbef1484a2d527d2c077f8b3d95dcfbcbbccaf41883707eb2067aae9c901", + "lib/aiohttp/web_routedef.pyc": "8433675ddcbf0242aac47223530bba49745013d41af098df851b9401a943ba64", + "lib/aiohttp/web_runner.pyc": "866ab964f310dd93cae9c60a9e6afbb4de8eb2690b7fef901db634db046141c8", + "lib/aiohttp/web_server.pyc": "616091ffef3f802b61b1d8167d93e0c298e2f1f41706fb3bba754c22d0d6bc19", + "lib/aiohttp/web_urldispatcher.pyc": "42869f67d5d759e54dfbb41379e937afbdc21b65387efc83951291a6ac007930", + "lib/aiohttp/web_ws.pyc": "33949ca2fb770499034d37acfb656da7558e7bdb7fa71894913b9d6023a0cc4a", + "lib/aiohttp/worker.pyc": "054bb3f42df8270343ba211eb1bc3f16bd536edff88cb4147155d534baec5a0d", + "lib/aiohttp_session/__init__.pyc": "b26663cc7a58f32d6862d325ebd3cce89084fff9cc29a116dff60cdf57cd7be6", + "lib/aiohttp_session/cookie_storage.pyc": "e9ac1725eefbf45d48f5a8f7b81f9b9731706910ae94bd73693daed44d4a3bba", + "lib/aiohttp_session/log.pyc": "e49c940774d98be9e8a2035a63d937e0d83f4c60b35777606d3840ba814bd052", + "lib/aiosignal/__init__.pyc": "cddf6c38f8b6b2d4f72bcc307b7e65198d29679cacbc6401c5faffa20e3b33de", + "lib/array.cpython-313-x86_64-linux-gnu.so": "46458a5ccd09c408d484e72fa972e3f2e11d541e2f64cca6891d65d8af0c15bd", + "lib/asyncio/__init__.pyc": "125b8c3e2c65e2eef97e0f05cd924875f3f078be2f09feb9ebf6a454518ef05b", + "lib/asyncio/__main__.pyc": "e527f6dde3083ca2aa412ff65802251b9f2dd2410d61f2ab9ed1ed70f30c2af1", + "lib/asyncio/base_events.pyc": "7065500022995b6327137e7a6f634b204d2d5792f65abc7b63b05f3925f20b88", + "lib/asyncio/base_futures.pyc": "62719c71ca3be335b8eabca1bed6dbbe13142445c5a2bdcb41df311dd395e818", + "lib/asyncio/base_subprocess.pyc": "7e92aa3b6ddd93c5909c61616aa442046718dabf5537a9d0aed540a6ab3bc5f4", + "lib/asyncio/base_tasks.pyc": "156573335c587c0b703fd9cef5a195ae43f4e2863aba3a8aa31f1b456795cc2a", + "lib/asyncio/constants.pyc": "396d98b48cc0784a8cd1611cde11a1c192f293a3f3b374c772e5b1f7d9119bbf", + "lib/asyncio/coroutines.pyc": "7d1eb538d37a0ebbe3672b2e18401d25ef4597849c0bd08587bf0601c4fea62c", + "lib/asyncio/events.pyc": "d98d2118ccaa7b6ce775a286ed0cc75f54634e4b4f6f5288af85e4f94b7de73a", + "lib/asyncio/exceptions.pyc": "fce4ed55a9d4f3da50044fd3bcb01133e7e9eb2e35e0abcea230122f3d78a9ec", + "lib/asyncio/format_helpers.pyc": "4810f90819ec9334edabf5efb565b35d93852b19180a61a9c1a3dc4fdaa79d03", + "lib/asyncio/futures.pyc": "1d8a1830d3943e7a055c528f5b57edaf374fde81cba03c773a86382187839df2", + "lib/asyncio/locks.pyc": "e4fdce67190062a7e201b8f163a268b86b57a8906f980e687cd4babf740b2b7f", + "lib/asyncio/log.pyc": "fa6b0b5855285c49b7b009df334994016eb0fba6fcc4bcaa8dd70ac70352ad87", + "lib/asyncio/mixins.pyc": "a0d5c70a9776294bc70b94e5c2d0b4abecd6c28f1c20ae1a0cbef6c94a811213", + "lib/asyncio/proactor_events.pyc": "b3475d7b1c14e67becf7b2670a45a3efab7d2141397d70a7cddc49a0862b5549", + "lib/asyncio/protocols.pyc": "7eb146102c45d775524755939d56cb704f3860a43722eee294b00684bc03d312", + "lib/asyncio/queues.pyc": "a7cd931be3f76357c3f5c34a0ddf72cb35fe6adab49de8c8d70dabb39c2cd3aa", + "lib/asyncio/runners.pyc": "a3c328ba320c2009d854eaefc500baf9014c1516bd13ad2ce3f5207000f05201", + "lib/asyncio/selector_events.pyc": "0f9b51989f4f93094944a34a6c4b727b03337ef1380d192c24ee7e28bd61eb72", + "lib/asyncio/sslproto.pyc": "f0b21e4d30c910c65dce1afd1d3b17430e09e6137a3b8bdbe235d95beda7b3b5", + "lib/asyncio/staggered.pyc": "2e047c225e8d78af9268447d5544b67ed8986c0c08b46d880be558212dca574e", + "lib/asyncio/streams.pyc": "9c7088833f4b9d7915c8016597620ae96769c37dc20ddb8d3a082f2367e69718", + "lib/asyncio/subprocess.pyc": "9c2d0d508afb8de53fa8788055bce84257212fc1c5df11f3645577ae96a0769c", + "lib/asyncio/taskgroups.pyc": "4db3d02c8cccc6396c20c479c2d56e463611741e1c576a40bc33e78ae3b97dce", + "lib/asyncio/tasks.pyc": "0bb38e3a12777507f48e48aca83ef8034c6756f9b34a6465a1b3297a2f86e1d8", + "lib/asyncio/threads.pyc": "071a74d18ad314846a19fd247050dc8fe19bb8bf991b3b11caa634c1ef4c3f55", + "lib/asyncio/timeouts.pyc": "8a18b5df07ab9aefdf25c49e2284cb9e3a81e159009fce43525127ec52161eed", + "lib/asyncio/transports.pyc": "fe563a1a4b44145eb9103ea9c9eee1be1bea0fa23de5ffcaa5d1a4ff54483ddb", + "lib/asyncio/trsock.pyc": "d8ef3a6ac2bbbc2dd71f7adfef472a3de27aa204a3152e53dd67c8d269ded560", + "lib/asyncio/unix_events.pyc": "45e4d06a61a3cc1e2fa845b211a615e4de9a1e626dc06a7dab8f1a7b661f674e", + "lib/asyncio/windows_events.pyc": "a63d154497c4b50761789c2a0ee27536763f3de5d023aa2fbcb11e490c494b63", + "lib/asyncio/windows_utils.pyc": "ea3294bee0e59e24ca1a70c70322110e06eaf1d8bd1e99f946b1a2cc721aa259", + "lib/attr/__init__.pyc": "7ce1666b8bf712fd6749f45bf7404f8141b8e9ea208fcf1e3141bc7a9382a47e", + "lib/attr/_cmp.pyc": "efc1005e9e6cd484d8dfc01770f26b8d3aca9a369a100849e16e7762c3dbc97f", + "lib/attr/_compat.pyc": "578dfaa9f2aa0646ffabfdbf3f53994217780c531398e6d486bf3dcead6347af", + "lib/attr/_config.pyc": "54edbbb113eba509a8841ef60a6c9e1fe56ce43e4b7bd3fcf7dcfe84fa99ca27", + "lib/attr/_funcs.pyc": "4529d977faec714d625b2fd7dace801934fe333fcaa98ad90de3be5006e0fa29", + "lib/attr/_make.pyc": "95e78efc7f09686cfcc2fc72f182ad1a09f2f1fa43e19b6413cf91c8f359b107", + "lib/attr/_next_gen.pyc": "7d6e86e14d096f948674d0d0390ee322e2ed6156fccb1b02b0af9b1c18056a62", + "lib/attr/_version_info.pyc": "cea4bcb5c36bd0c3c610faa3de26e4407f348e1dfb3636fe9e5f065dfc671013", + "lib/attr/converters.pyc": "389d573236e2cb9bf2c57240221bf82d1b9e81a6a0c02bbc614be5f276571cda", + "lib/attr/exceptions.pyc": "69b083988eee8f1fb6a7b504748cf2f92e296ceb6001e5da7a8483c10f3485a5", + "lib/attr/filters.pyc": "03d9a20422225cac2e268b8debd3a594fe4a1517d331cad19883714a1744be2a", + "lib/attr/setters.pyc": "0df8f67da0e1e312c2340bb824e3fd8fe57cfac95000e87bc866ed9f4ca4b00a", + "lib/attr/validators.pyc": "6c289bc1a9a10850b0ace12cc27582f995c8b8eea525a1dcf23d245bfe607cd3", + "lib/audioop/__init__.pyc": "d779f763f7ee63041b2788e7926e842f9020267b6c7bf1ca01aa8aa3e7a40140", + "lib/audioop/_audioop.abi3.so": "e56051a1cdd4146183a186c2d448310593cab692d89d6e9c906b6357bf8ce0db", + "lib/autocommand/__init__.pyc": "2305b3fbbe484e5d2fd7fa251fbc047b0cb03eb3a3cf69a7767efdb70fdead33", + "lib/autocommand/autoasync.pyc": "d665e11e8febfa39d7d65ccb77bcd16205c4f913a727b60401bccb592f359b3d", + "lib/autocommand/autocommand.pyc": "e730f1ea93e94bc8c14787690ba18d0ee8e13515b7bd720098bba6bed847058e", + "lib/autocommand/automain.pyc": "bbd61db402acda81b0cbcc88275fec2330a008462e2cd93bedac4cbac64e4807", + "lib/autocommand/autoparse.pyc": "073334feb15727bda41bebb97d9e85eb25e123c2f16edd216301863f0f2630f1", + "lib/autocommand/errors.pyc": "465052424557c49506411fe6d4845b42889923f8e818e7eec26f50c361f46568", + "lib/backports/__init__.pyc": "2c8ae771fcf4d22e8f2febb1c029df963750c95fddd2f9b6250ad6432988fd1b", + "lib/backports/tarfile/__init__.pyc": "0cc5521b88ebb4fd688db9dc3ac06078d4db7cb50d909936017ede4586cb658f", + "lib/backports/tarfile/compat/__init__.pyc": "44f835fb2cc3172b2f0fe8357b665a4950791d56c1d08ba761716b01a16348f2", + "lib/backports/tarfile/compat/py38.pyc": "608bb4065ba901c775844cf8a6e7b15707f64ca387ed907eb8f3365b4fe4d18c", + "lib/bcrypt/__init__.pyc": "81ea8d4a8de4d366d376f94ccb7ce98a4e668de8186968f6c867e4a37c2a5b95", + "lib/bcrypt/_bcrypt.abi3.so": "30194720850b822529be97190cd001cf43f4577a82fb98054f88d54c726043d3", + "lib/bcrypt/libgcc_s.so.1": "137f5385f2fc44139b4c28b230e7e3298da51b04da7fccb0ec2e0a108054da1d", + "lib/binascii.cpython-313-x86_64-linux-gnu.so": "9ecc68d05241f9e2aaec02e260beb01e85706f54d464b967bdc710a0503f17dc", + "lib/certifi/__init__.pyc": "b1ac80380697fc433b362df66464d96a2a629f1f0b24ad62b87ab45f57d837f2", + "lib/certifi/cacert.pem": "a1ad5d643e21c43b5bed74c7e0891dcdb58f6af51c8ace1e4f020d654aa52a16", + "lib/certifi/core.pyc": "d4fe08b3a224e86c56dadcb9c85f9d1dc77efbf64a5b102440a30e943123af7d", + "lib/cffi/__init__.pyc": "5abc277756964e1447eef50c866ee21eb4b29dae105a9fd68ca0cb835779fda3", + "lib/cffi/_cffi_errors.h": "cd05edeee47f9bc8145be7c8da1260d0aa129091705eff111949040d9d7bedd4", + "lib/cffi/_cffi_include.h": "131866826f6acc75b35a2be37d37b40fb5e9e2b3d4915c5d36ec0684c4cccdbc", + "lib/cffi/_embedding.h": "022df71476e513b5d2a47382a7c90f716c0de7ff41575e0ebcdd0955ae884e9c", + "lib/cffi/_imp_emulation.pyc": "e2b233663c9435913d28480092dd5ba48492ea9af483af77c8497a3424a71886", + "lib/cffi/_shimmed_dist_utils.pyc": "a67c3b0d3775155896335aafb600e54493c556051e6680b924d43e912cfa2563", + "lib/cffi/api.pyc": "31446d40eed56fcbead27e8e5b92a01c0bbd486aa38a6ad2e3dae23d9b203d9c", + "lib/cffi/backend_ctypes.pyc": "1a9f4c81859f57cea3e0f4fbc4369d5969462ddc7c3d15ff7968d9b4ee413fd4", + "lib/cffi/cffi_opcode.pyc": "10ef47cdbc09d236ffcdf425203f588ab80fbe3fe583d0fc1dfdc17212eb8fe3", + "lib/cffi/commontypes.pyc": "ed21d5da9aff90b85d82d1c630e16a16174b4d8e9773605c40304dfe864ffb81", + "lib/cffi/cparser.pyc": "e57aa8cea6ff5aa6d994d7dd6102a7942c544c75908941f665df021e6337e598", + "lib/cffi/error.pyc": "f1c3ef021fa321fa0254e74626f7e4039bf3e1685574a48d986956306c64104f", + "lib/cffi/ffiplatform.pyc": "7a1d393df54633bff314bac71d6f97c3e9ea0a57150b1b2ed354c81c0910438d", + "lib/cffi/lock.pyc": "2f3fcfd64ab144fe35379e95a04bc575cf51065f3b2274617183db5c8d7d29c7", + "lib/cffi/model.pyc": "eb7c66e6ccd84880dc9a6eba098a55431d0b9daed9c92774ad97060e071057b8", + "lib/cffi/parse_c_type.h": "39dc107f033d92dababe5081e377b11509b10c1b63d8c04d74af0b625d79b63c", + "lib/cffi/pkgconfig.pyc": "6f03cec917727f9ee5627b64f5d1daae9846eb140a019ab16a7ce58058b3ab6f", + "lib/cffi/recompiler.pyc": "3fcf9288fb6cc453c8451fa4561e211f3c3353cf1c68089e56218936b1e27612", + "lib/cffi/setuptools_ext.pyc": "0229eee4cba6ee503025674fba2f37187f3818bfdf3004c74aa297456e208d97", + "lib/cffi/vengine_cpy.pyc": "76678eabf87f1eba59be19ee7aad915cc46b507d059a1cea0d08b5945d745fc2", + "lib/cffi/vengine_gen.pyc": "e1db99c8ce0756c8915de011ebb7cc4c8eea4663bbbaf8f0d044e30db8909396", + "lib/cffi/verifier.pyc": "4442789a8313ce1482ed5fa81970ac0bf4252a3cd5f8b373de328cd878ac15c4", + "lib/charset_normalizer/__init__.pyc": "2fec82e9da7a2bab346690ed6ffba5936fa87888facfdeb7cec50edc9dea3ca3", + "lib/charset_normalizer/api.pyc": "35e813531ca20a31949a2ba539a3e43a82b41c205dde9f1655dbf019989688fb", + "lib/charset_normalizer/cd.pyc": "3bcad4082e54951dc1fa60168fcb229ab6e5c8c3fe4be5a0a6de6967a0ec92f5", + "lib/charset_normalizer/constant.pyc": "7ea328da464d6708a95dd1b1b7774d4a5956497cb07cbba8e56823451fe460dd", + "lib/charset_normalizer/legacy.pyc": "9c82eea52943e10fc95682eb12061ccaf1ed0fa00ae8dd42ac192ae41d7868c4", + "lib/charset_normalizer/md.cpython-313-x86_64-linux-gnu.so": "b19eee9ad24b8ca7c0f3734527b9e99220f2af4eb30d3f1c5ad97ab88c7632c3", + "lib/charset_normalizer/md__mypyc.cpython-313-x86_64-linux-gnu.so": "8bec9abea3c9b59c234cabcff6104b67c08b643f3cad5b60b9a4a82c7b28fce7", + "lib/charset_normalizer/models.pyc": "69c93554423d954fcae8ff89346220e41d23618c9736cb0406b7785124fa07b0", + "lib/charset_normalizer/utils.pyc": "566a9f53a90be88c4200fffe2f19efb0de2ad5218a661224c482d9e768041267", + "lib/charset_normalizer/version.pyc": "96f72953986624ddcd0710ad91f7f9d7c908c37b8089c6c26c6ec2716683e445", + "lib/collections/__init__.pyc": "b9ada7cfc1e2fc545b268636b9df60621622983bb1bcc5b21afff96150543d83", + "lib/concurrent/__init__.pyc": "13cc52f582591afd766afa93e361ba6fdc982af60b6f84a7c0a79c3809f46d2a", + "lib/concurrent/futures/__init__.pyc": "1d9aa3d8ff459a8bfa737e1a6cd8ccf41b7b9bd1f5fe0624573627f509cded37", + "lib/concurrent/futures/_base.pyc": "225a8ba28ee6729fd15a75a02d5fafe8f860ce50f090fa3d03cab6a0a4168b88", + "lib/concurrent/futures/process.pyc": "d43394a758af7f82f8f8ab05d894e130c73ab08d35fa63114c235961d08885e5", + "lib/concurrent/futures/thread.pyc": "f757e632094dce8fa462af77f1ac7520751069fbf9a39350a141b53adad38c19", + "lib/cryptography/__about__.pyc": "5040c4e0ce889c374d78b0c2c0b263161645519dc23640df1558b772e2787c14", + "lib/cryptography/__init__.pyc": "e9ed5cc7c13040557d6317572974c18447f302d7e153d75bb2e3101ff78c3e75", + "lib/cryptography/exceptions.pyc": "9eecaa79dcf52884c00861a871dcd4efd4d58020c4be3cbe8974fdbabe692979", + "lib/cryptography/fernet.pyc": "2bf50cef31c21a1408aad57bcdf36bf26648b9ee5fa0e831bb80838c5afce8cf", + "lib/cryptography/hazmat/__init__.pyc": "1ce22605f8096b1738157ae98c95072e30276a292df416c64901bee0e24bfb14", + "lib/cryptography/hazmat/_oid.pyc": "314d99135c971dceb5ab709f5fb8cff029a5fd25e2c27259e399196f6f928d38", + "lib/cryptography/hazmat/backends/__init__.pyc": "5305d1d8b255cc3f9ca45a0cf2b077a3ae096fb4a9db9c605e6618c9f65d0bda", + "lib/cryptography/hazmat/backends/openssl/__init__.pyc": "c8799af22c47c3c8cea859de98b74b814292b0a5280df6550ae8c128cca8a2f8", + "lib/cryptography/hazmat/backends/openssl/backend.pyc": "d496ed296de5e79998da96c87e12bd0fffa6a3cb329687d990d513f4e86229a9", + "lib/cryptography/hazmat/bindings/__init__.pyc": "81f1c244c8413079346ac84fc8e58cca96a59eee71f040b42b4e94d38108424e", + "lib/cryptography/hazmat/bindings/_rust.abi3.so": "4bda55a10c6f7b46d0eb895f7b6e735bedcc984667bb5b88ea27a1be19cbe92c", + "lib/cryptography/hazmat/bindings/libgcc_s.so.1": "137f5385f2fc44139b4c28b230e7e3298da51b04da7fccb0ec2e0a108054da1d", + "lib/cryptography/hazmat/bindings/openssl/__init__.pyc": "d905654e5fe841b625fb961c043c45d7a327325ad8835aff023888e4d065a05f", + "lib/cryptography/hazmat/bindings/openssl/_conditional.pyc": "ad35144725ba5b4e850d775772d31694dcef92371b4dc801d7ed02e121bf5351", + "lib/cryptography/hazmat/bindings/openssl/binding.pyc": "d51e7fba0a2a4b90836397e268436b259133f07fcbddd98c6d393bd421a37a81", + "lib/cryptography/hazmat/decrepit/__init__.pyc": "97719113f127d835a0864e9209119faf339343ca6692d4c487526ee10087a02e", + "lib/cryptography/hazmat/decrepit/ciphers/__init__.pyc": "721f8dbe69240ee0956f5a98688eec72cc6c1baa5e6685aa44292bf90654bcd8", + "lib/cryptography/hazmat/decrepit/ciphers/algorithms.pyc": "e03e590b93c85174a25400b9694c386c5ad29a1f0bb9aa405f2b351c191c83e8", + "lib/cryptography/hazmat/primitives/__init__.pyc": "4932ba4cda8cc7a1677410801539f0b20e08398cc80c1286a87abce7ae64c399", + "lib/cryptography/hazmat/primitives/_asymmetric.pyc": "8b2e7419dbd2256e06dc84327359c748180c6ed515eb3d8b7d8582527ef94dd0", + "lib/cryptography/hazmat/primitives/_cipheralgorithm.pyc": "757f8914e678a576675ec253b2140e05514d7bf040be1b050f0e921241736859", + "lib/cryptography/hazmat/primitives/_serialization.pyc": "2c8debc550e51a74f6eb9fef5b5ca1334f2f28defeca148fc5a660e8263dfebb", + "lib/cryptography/hazmat/primitives/asymmetric/__init__.pyc": "c79933eba1203cc2634445d7db33f2627fc4249b6aba1deaf0e70b913f09e1a9", + "lib/cryptography/hazmat/primitives/asymmetric/dh.pyc": "48ab4fee6eceedf5ba6ba998956905b5c8531c154ea44abef5999f8312ab8922", + "lib/cryptography/hazmat/primitives/asymmetric/dsa.pyc": "9a734788bb97c3a0ad12af0a4c1f7b820e81290979a6dea95ac8ac184cc7e9bb", + "lib/cryptography/hazmat/primitives/asymmetric/ec.pyc": "254b6e12aa8c1f8f0bb1d83078e94218dd97b4d47b79124e6db761829e6ffa3f", + "lib/cryptography/hazmat/primitives/asymmetric/ed25519.pyc": "b7e8e3125641797745af916e0411adc3276f2fa32e67ec9bdce844730f63155d", + "lib/cryptography/hazmat/primitives/asymmetric/ed448.pyc": "db829a247c7aef0c9c32078ec4ea10028d42c569ef028785777ce02b4348528a", + "lib/cryptography/hazmat/primitives/asymmetric/padding.pyc": "905e2bb6aca5a594a16fb16ad90427db185a830998dcbd3a2182e48b7b0ca78b", + "lib/cryptography/hazmat/primitives/asymmetric/rsa.pyc": "5d1cb3ad436c512098012a7244118920b7fe9860c77331df5e926840edf99da8", + "lib/cryptography/hazmat/primitives/asymmetric/types.pyc": "894f00cb8a8cce769e9d83892d1424449377cf7a2f4f5696958c94ef15071f74", + "lib/cryptography/hazmat/primitives/asymmetric/utils.pyc": "f714e6c086e1915afc6b7ef72589c3cd0d7688d2e5612c003c633d19bb43eace", + "lib/cryptography/hazmat/primitives/asymmetric/x25519.pyc": "4ded3ed2ef399b4c7e1805c1b20c2cc62542e9f6429b881ea478a586973b5f0b", + "lib/cryptography/hazmat/primitives/asymmetric/x448.pyc": "a949b3fc6947c81ea5d508114ad4950851a3a9623492ce9804884b4143274a45", + "lib/cryptography/hazmat/primitives/ciphers/__init__.pyc": "b4f47de1ca9f9ee295bd594ba864a026bde9c023a497bab405b3d8147ccbd30e", + "lib/cryptography/hazmat/primitives/ciphers/algorithms.pyc": "61fb7c262b923c96c14ce936d9d35a6ff83ebf226ce2bc40e44aee9a5f3e6244", + "lib/cryptography/hazmat/primitives/ciphers/base.pyc": "14e6e2c51d3f2c435ddceb38af9c4f144825d8218f19db4116a6774791bee79f", + "lib/cryptography/hazmat/primitives/ciphers/modes.pyc": "de599d7e9adae8530c91988b77d1db329b8ffe895f7e3151f8003a815338d096", + "lib/cryptography/hazmat/primitives/constant_time.pyc": "54146fd41804d026ab5124faa7c5485e08164d359d417a03af662e408f915445", + "lib/cryptography/hazmat/primitives/hashes.pyc": "fb6250fc53045b103a7acbb48004f23dc1ee3589482750a09a5ce01e5e573deb", + "lib/cryptography/hazmat/primitives/hmac.pyc": "d80fc301f7faa2a1fd8c7eeddf5bf25ed1ef699a941eb081059fe6b6dcfbd4e5", + "lib/cryptography/hazmat/primitives/padding.pyc": "c97cc03c44cbc69f24526bd410787e3c60ead5ea2a8d7cbbd3d4bbc1641aca2f", + "lib/cryptography/hazmat/primitives/serialization/__init__.pyc": "737a6e28f8aa4ca03b2c5ba0a935157d8ba1790194ac86925afa249dd80a4436", + "lib/cryptography/hazmat/primitives/serialization/base.pyc": "3890b46f074a731961d50c4c35dfd8c09f9771aee61d6c759a0324e2d5a53bb4", + "lib/cryptography/hazmat/primitives/serialization/ssh.pyc": "69d2ce0bbc007cc85421164a9b27a73f5a55ba1fb7f22a47dfe99015861aaa7d", + "lib/cryptography/utils.pyc": "28ea9a3c4b6c1b1b8a529c51037955b4e30dc5c1a4f1134a02f500f9c149ee18", + "lib/cryptography/x509/__init__.pyc": "90eb02466fa409b39e2069e6192566032b98cd1bbf777e439be02a7f560a8ccf", + "lib/cryptography/x509/base.pyc": "427289c340355b236553078d1232f91cecdbcc284e6d244b397ddcfb6577c3d3", + "lib/cryptography/x509/certificate_transparency.pyc": "90dbbeab2c2190ac54233b6ed8d74280db3b835da40cf014f1387fdbad193177", + "lib/cryptography/x509/extensions.pyc": "f00b4b6fc2c135f2789ad447b4eb4050da2392c468a37bb0d1384fc3657f6bb5", + "lib/cryptography/x509/general_name.pyc": "c3c0df1b84d8d6e020e37d3e2c091526571056ae6949e97202a662eb5eac72cc", + "lib/cryptography/x509/name.pyc": "45b0d0b72ef32a98fbd969b6b466291edc05bbfdd9e6dcd2d22066db47a5790b", + "lib/cryptography/x509/oid.pyc": "ffe72841c7b08455a286cb81a89445f284465927eedcb9b71255168943a09157", + "lib/cryptography/x509/verification.pyc": "1d4670e54991349be608e0c499b1125f34613d0c00a651342de59938e4766b6b", + "lib/ctypes/__init__.pyc": "4302ab703d326e6c078a0fdc30303c50f379befa5e2f9d9a61eb961679a91908", + "lib/ctypes/_endian.pyc": "2146ef8f031c98ac65047fd46f80124c9a8b685114089afdb79b26a3668e8193", + "lib/ctypes/util.pyc": "4e4dfea2ed896f473d8faec5c122698bb25778c57d8bc9c01c285e7bcce99fac", + "lib/ctypes/wintypes.pyc": "46ae4ec3576650005edf89f1bf9502b450857cb556ce277e7437ee83d55f5cd8", + "lib/curses/__init__.pyc": "8f054047b59d63bbc1a1327e94cceab7f3c96d534d7d9fcff9847c14a1064cfe", + "lib/curses/has_key.pyc": "8b0c6cc7363efd1fea65929a08deeb776eca9d0d890e12c7a8a5fddb7d1f4778", + "lib/email/__init__.pyc": "43af03418dc020acca5742113f8a476c640bc4dd60b2f9649c31f4596c41c81a", + "lib/email/_encoded_words.pyc": "ffb46570be99ca3e8827cae60395bd3db8a4584d1aa9a547cd7419632e640937", + "lib/email/_header_value_parser.pyc": "0a253eac2183713a384d10ed4ecc9411aea9ebddf9ab5b15214381cb5e0ef638", + "lib/email/_parseaddr.pyc": "bf8602b54cfcb5388d09aaab47944817b548828122b3ec42a862649750621bce", + "lib/email/_policybase.pyc": "116e811fd1b6f718975a83f0d0cfeaca4f8f510b4fd006ca53d71836af2a3399", + "lib/email/architecture.rst": "f2b2ba7497fd02d13abcfc2a98099283a94b09e8b4f2c1c822ecacde3bec3eae", + "lib/email/base64mime.pyc": "018add364a4a5ff9d2eb21c279b1ed98885b8751a42a513dc09a431fb22c07c5", + "lib/email/charset.pyc": "8dc69a6e56e8f3aab02d29eb3eb7af080cdaac0a3b5fb7d5c26f09bad8ed7fcb", + "lib/email/contentmanager.pyc": "14110ce70e29c116167cc9cab6704bcb2088966e1d96eae00ec014e9b217e031", + "lib/email/encoders.pyc": "1d3db039b1ac9406a3e9ae73890f60caa19afb58461458da2a0db35753be708a", + "lib/email/errors.pyc": "20861a987c0aa41bab34ea1731896c04f98137a35c6b3b5fd435fd8c7637c7fb", + "lib/email/feedparser.pyc": "5dc5ce7cfa9dee15ab49e4bde936abd81b43983403c5c560dc9342371d523a65", + "lib/email/generator.pyc": "be4981f1165ffeaf2807931fdd8765227a9425379cca8c7ca21e1b5deffb39da", + "lib/email/header.pyc": "c106830742c646f4c1e16597294b92ff144fe42538312ec5b96df94c94d7bcbf", + "lib/email/headerregistry.pyc": "62104032594baa2c8af7d7748f424148cdb0b2dc04d0305f00ac83a28e1652c5", + "lib/email/iterators.pyc": "ba748cdf5cabc34fcb7d8bccddf2e57684cdbb08e65087b8f7fb06b6192bd039", + "lib/email/message.pyc": "e35de5a6a89314f7774910dc7bc16617bbd82bfcafe162c1ce3ed1e438a01c7e", + "lib/email/parser.pyc": "65ade732f3c1f29c37725539d087a191d1de284f3b07fdde876575be4e232362", + "lib/email/policy.pyc": "0afdb552d822d0447a0bb3bcdde983fcf6c57a48a280be34ccf136626c09c57a", + "lib/email/quoprimime.pyc": "6c5aa66d61ce4fc021a8f97e1b3eb0cd83fc3d1139c62dda7f5aca044dce0e2b", + "lib/email/utils.pyc": "cde45e8d88e35c2ce925adc1a048b7381e529e9e62912117cab69db5748c32f6", + "lib/encodings/__init__.pyc": "511f4e15d17125e705c6f31d4ead0e25ea9b9fff1ea04ec55b560bd711d26714", + "lib/encodings/aliases.pyc": "29b030ea1e4db25738cb2cd23320295a485b9c13bd7f134883691df378613e71", + "lib/encodings/ascii.pyc": "85b4aa4163ecef918436a80399fceaf91ad827a8886a41102c267ae6246d3da3", + "lib/encodings/base64_codec.pyc": "1126393f4682fb3c570287e296b8fa99a7a924d6a89595cce2cefb06a469b0da", + "lib/encodings/big5.pyc": "f4fd0ad7fd8d6d53e32109f8ada85b7d5b025df9e9549ed52d2649d2a54153bc", + "lib/encodings/big5hkscs.pyc": "15a3486177d9c0b820e1c20efbc6341a756869b457ef34cdd85da98377a4e3f0", + "lib/encodings/bz2_codec.pyc": "02e5e2b96dd76a162d800c69054c446838ef2906d852eb56ce2ec895ce681b99", + "lib/encodings/charmap.pyc": "75c8f16db3c39d6f640c2691119fb47d567a2061ffd64cbf7e4b2faaca38f25d", + "lib/encodings/cp037.pyc": "e68993c7270cfbd9aaef6d383e967b161666287711086fd45c820fade526ab73", + "lib/encodings/cp1006.pyc": "fc5482b8b5a81bb6e4d374628ff737f2115bcf3a181bd8b109983fdb9e61547d", + "lib/encodings/cp1026.pyc": "ff1943ca1d24435dbccdaa0f9c1d0fe67d4d497334259079a4100306dc34a174", + "lib/encodings/cp1125.pyc": "9b1095bc186b02503e310b677d6bb487964f91dd81292f08dec08a3925555b6f", + "lib/encodings/cp1140.pyc": "efde679bbb1efe79f5d7f915a509a50d833cef3aeb089544b208a4feacfac1f2", + "lib/encodings/cp1250.pyc": "9df7b179e98b710f6878bf7b9885a261ab17f179b7af2c1416ff59a7a546acb1", + "lib/encodings/cp1251.pyc": "4d3ee8019206e06473eb93f07008bc7bb633f37e8dab2584c68ba73fa699224a", + "lib/encodings/cp1252.pyc": "aa002ee24a40634790bdea8b0d363a26b6eeed631446a4d5b081e912b6b9d4ba", + "lib/encodings/cp1253.pyc": "de3da6dbfc05ce81a617a67dc2f29d3a3b87b4e7589be6ff6f8a09b85d27ae66", + "lib/encodings/cp1254.pyc": "f5b9507febec176bd9babba00488cdcf4795d2c7fe23c0c83f8623b531a9aaee", + "lib/encodings/cp1255.pyc": "7d7debdd4c11f0364f97ede13c26029e6e042e89ea8238bb3a89576581ce883f", + "lib/encodings/cp1256.pyc": "3f00fb2689a17688c8833a98b5a2ee20194fc5951829c10966410f21121a6de1", + "lib/encodings/cp1257.pyc": "1d6d3d9dfdacd23c6fde4545c422874abc95c800d8c74f3c3279312129b6b4d5", + "lib/encodings/cp1258.pyc": "cc598cde3a73abadca4eca4ffdd7cc303a9d32ea639c6d3f8c4b5fd89a19cdba", + "lib/encodings/cp273.pyc": "31b3e72225fce2bfe274ca66042bc5edd61829ea052ba3999c71eb8c22311268", + "lib/encodings/cp424.pyc": "9f222f0ec6e2fe1153b1605a043b3085a3d7b9a09032131ab1460e57ed62479b", + "lib/encodings/cp437.pyc": "09791d8784d0fefeb2408668b1ce790a08b961e09d77bde97c87aefeb0e78973", + "lib/encodings/cp500.pyc": "9133aa286795986d748c9614e4efc226be5cac12df61e5bde88a1597002d5eb2", + "lib/encodings/cp720.pyc": "f0a2e693e692067cad947d24dfc9e7545d806ba3f1d5c28c8742c940a8c85c0b", + "lib/encodings/cp737.pyc": "2cfdd530aa05b7d2238c2c1f8989c4c88e91ac9b90a49f8c92e2a77907c6b1c9", + "lib/encodings/cp775.pyc": "d8fb7e7dc97e95bca3d50d6b00f93e4283a69ba134fd873471f7718225895e56", + "lib/encodings/cp850.pyc": "58d28428c423abbdb60b7d6a73d010680813a2ee883a5338ca9b528d8553e0d5", + "lib/encodings/cp852.pyc": "ba5df766080eb5437e434cc05ec217be3045ca26ee18a9fd4f8b838f80db0fb5", + "lib/encodings/cp855.pyc": "211127d2e9a36d5c7ed328b6338d246f9525280d1db97da0ac3241efa483c6b5", + "lib/encodings/cp856.pyc": "c84a287e7e2024dfe30f1395fa0f4fb376ee6683023af1180bc2c8c933c25e26", + "lib/encodings/cp857.pyc": "6a180d1e89f3b814cc51a7fad135c68f3cb5df54b3f56ba2e369d4adec030a02", + "lib/encodings/cp858.pyc": "acf596858fdb5f55efa44c9c3be6fa944c9cfbf238da452b5c0853449ae53514", + "lib/encodings/cp860.pyc": "5fa76ab68ca3dde01ea91f6911a226af50c0f934cd76ddf564236ee9e49e5f71", + "lib/encodings/cp861.pyc": "84f99dafaa7ea3d9287ee8705cbf6cd47ac3ebdd449e314c86c1fb0ca363239e", + "lib/encodings/cp862.pyc": "a9f63f4f7e7545cbb57bf4b0b5a353f8cb6eaf80bcdd12b8d7e12042a9779274", + "lib/encodings/cp863.pyc": "443d0d918723f38b866da367166267909fac7ce2e71c5b9d1f7789a89b2c7222", + "lib/encodings/cp864.pyc": "afe841991ee417e457938f3e42d941fc8734814935f7851e383ddc3c017041d4", + "lib/encodings/cp865.pyc": "36c01bd0f3af27054ba00b509a5b92f8767df7619c6d6c71bb3a925d875840c3", + "lib/encodings/cp866.pyc": "857e65b6a04669b5fd84daec1a63cd0aa5e1c09cf09b8a56ddc9462d873a562d", + "lib/encodings/cp869.pyc": "7551ec7b969fce39d01fd0993c8353dd5a894250f6f1fa2ff8d1eefcac8a45c7", + "lib/encodings/cp874.pyc": "0d38275d30f26fd61957e8a62927a8dce980d4870dbc23a9cd4a5a843f82d03c", + "lib/encodings/cp875.pyc": "38b3fc315d23146880b72be05c0828a09fddbbdd52256f99a357ce277312bf39", + "lib/encodings/cp932.pyc": "ad24265b14056c4ee5af96b9f6efdf943859503c8ce2e9547ae1035044412282", + "lib/encodings/cp949.pyc": "e30832884957b745fd08acc7ecc54edff0ae6fc37a0a3308c0ad7c6bd834dd81", + "lib/encodings/cp950.pyc": "8e14e463ecd6ff14600c3882045f6ca00c29f55ed9f71f4f0b7cd4c0df7ca459", + "lib/encodings/euc_jis_2004.pyc": "ffbcd915892904d30e01f6968271feaa4bb3fd5d4027144db30ad8a52f092708", + "lib/encodings/euc_jisx0213.pyc": "31fee0530a2d34d749d69e96aa29f553cc7c18f887bf79c34e641553ee6a12d7", + "lib/encodings/euc_jp.pyc": "ae09801344a7d699e4051ef3595cef252424d975b93862b5101ff8c76d551bc3", + "lib/encodings/euc_kr.pyc": "316ab80a00802503e78a6f38c194b5602e5331db20a52fe3cd023caba025f80b", + "lib/encodings/gb18030.pyc": "f212bc4067c068b41acfeb89c391318bbf6bfa859a3e071c10589be9375a35c4", + "lib/encodings/gb2312.pyc": "1c1184b6d0aa0c553e8c5ba9716a8d19c6ddd173ef3a2f5bbb4d83068a69152e", + "lib/encodings/gbk.pyc": "a507aa6602359065834164d1bc85a1fe7f99c3cf285347eeb678b510782fd82b", + "lib/encodings/hex_codec.pyc": "610c7484d6bf645a6efbc64bd7dfdf2efd16eeb9c08562fce9746270a9593939", + "lib/encodings/hp_roman8.pyc": "49ea7e73a9c2863e59a0cb3a5fb0bc916fd2ff529796fbd99e995d0ecbc6e6bc", + "lib/encodings/hz.pyc": "b838ec5f2057bd42d86b842f9ea20fb38538f8d9bfa731e9c04449b88d9bdb7e", + "lib/encodings/idna.pyc": "3448451d693769812dd84261cafdf9049aa2ff5cfc43e1d5e21ebe016fec88a0", + "lib/encodings/iso2022_jp.pyc": "1dfbf5351869b86fbca712f032a7669d15d59021ac2aafd0261345749e005dcc", + "lib/encodings/iso2022_jp_1.pyc": "edc3836858855dcbd80170d4bf22be16d502c91aefc8d871abaaae79be63328d", + "lib/encodings/iso2022_jp_2.pyc": "85ade0baa1a143e1e34c879a06e27cb509b38978c69f8809fed2a09a2d3d9203", + "lib/encodings/iso2022_jp_2004.pyc": "982ae84e56bb31bf3cfccdb349c21c91247beb55f15bb24c4bfacf2be25bcba1", + "lib/encodings/iso2022_jp_3.pyc": "a8e9fee8d0ca97d9a01ce4423c69d80dec26c0f404693b6b1be748c4801e5d65", + "lib/encodings/iso2022_jp_ext.pyc": "e0085098dd278e4881c6c65448267fc38a2207a25ac89dfd641bb92afa29fd62", + "lib/encodings/iso2022_kr.pyc": "6c05c59a946809074ed954f56e6d3194806e2f70c215aeaf2397581e751343a7", + "lib/encodings/iso8859_1.pyc": "91390871c96ef1d8d21e68d4865710c068d9a778028a743d2cf2d0abb7997823", + "lib/encodings/iso8859_10.pyc": "539ce8db5b59c5934e1487c30cfc670bdf7c9dd7ae7f2d6db85c9d4e6bbb578c", + "lib/encodings/iso8859_11.pyc": "cca4b4e525620bfb1910ad6308453652c6728e1a81599d5f46cb1b2ababfc876", + "lib/encodings/iso8859_13.pyc": "4a5d5206000c9cda3e434be430f5317fb090f141f16b951e5066c30541d6bbb9", + "lib/encodings/iso8859_14.pyc": "d8548e78ef97bc8f58c36328b735261a05044d6c37dbdd3a0bc92fe6216d4b63", + "lib/encodings/iso8859_15.pyc": "1c752c0413f2aa1d2f574bdef4883dd3cc2bc276fb8d7dfd21b1cf0efbcc709d", + "lib/encodings/iso8859_16.pyc": "7e4b4ec79073e56940aded51705b991f4940659e247886e21c8d7ec93bdc1afd", + "lib/encodings/iso8859_2.pyc": "470525f101c80d50df300ae5c1887ab6edbdc345ac19c68bdfaebb027ad2c96b", + "lib/encodings/iso8859_3.pyc": "9c6c6c85ee8b9e17d2bd9ff69a46fbb1cd83200482d5b2af4fc4b9cc548991d2", + "lib/encodings/iso8859_4.pyc": "265feee74e4ff142d6e26d913200e836f6461a4c910c3e3b3bfbfb618d01487b", + "lib/encodings/iso8859_5.pyc": "505986fbb8292ecad3ec8380840c95576b96ad6b1ae04100b106dcfb334e7dd6", + "lib/encodings/iso8859_6.pyc": "ac8231cc493d1356ba13b6b1b76206a3b696a27381b13a36543ee141be7b23d0", + "lib/encodings/iso8859_7.pyc": "ab4c01fba265cfc666f6e5b8d2f2f4da9a63321521250c78d956dd774ff5c37c", + "lib/encodings/iso8859_8.pyc": "116670cc032ee02703ee9dc1686038b99f44aa2650c2b59f30c33bcb38215620", + "lib/encodings/iso8859_9.pyc": "4cbb27bcc36c2f097755187edfcc2947ee607cb0a661c9429de0340c4e77e8b1", + "lib/encodings/johab.pyc": "6c7c26118344c5e6d67173ae44cd42355f69dbab08ee25cee995b12a8e80f66c", + "lib/encodings/koi8_r.pyc": "40022e8a11fbce93d9ddd032ad534da1d95be8f5220542db915a182ef8c4969b", + "lib/encodings/koi8_t.pyc": "a0667a8eceba104a270c66ad8b15be9801b0b2af5789cc3cc1388fd153ff8999", + "lib/encodings/koi8_u.pyc": "cf239c702c6c6c3ef7c721ed254e063cd7ba3d014dfa26306e741f63778dbdd0", + "lib/encodings/kz1048.pyc": "60f8fa71ef8c66185aacb3c1afe233c06e26afb4fbe8854f2738b4de2a1079ed", + "lib/encodings/latin_1.pyc": "5204ed88c326dced22f7a071e3901de823a60c1c55e2f0c9396beda8fa840e39", + "lib/encodings/mac_arabic.pyc": "982cd2e8668956d577c99a021d46a2c790b85db6999fa062ea33f4bd43b88f8e", + "lib/encodings/mac_croatian.pyc": "c6f4ab7e0642015a37b5f99753b465e8204ebd245eecbfc99080e21c680c366e", + "lib/encodings/mac_cyrillic.pyc": "1f90db7ea725d027ff4e0215528ba72d43608ad8fde0e2315c0d1204592fc4f8", + "lib/encodings/mac_farsi.pyc": "be482340c12530526276e5f6c917325f221d4ffa0a7a566837b7c5c231d3a636", + "lib/encodings/mac_greek.pyc": "c6c32e02962ceb92aa2732cdbccfa8091a0e8a32180316850b91e2da5ad4524a", + "lib/encodings/mac_iceland.pyc": "3016aaebb7990e4a24ddc51c1409c582f88446b745100b1f4d148460e50a2a06", + "lib/encodings/mac_latin2.pyc": "260b3b2a74ef0546460e45dfe4898adedb8ab3c9658a2babe3cc57e3fab247f8", + "lib/encodings/mac_roman.pyc": "f3ffe35420d0f6b015c352f39f7322113da2926213f42fdafe90831cc9fde8d8", + "lib/encodings/mac_romanian.pyc": "49ca89cb92e25abf55f897bba06a53feb98d9cd8c41de730abcd8448dee86e0e", + "lib/encodings/mac_turkish.pyc": "953eb68f7709a6e10b7fc0b2ec0cdf02c1e6d9c5a3893ac21adafd7778bf9152", + "lib/encodings/mbcs.pyc": "53241f7dcc92158d651a7a88aac5fed0527d85ceaddea992928f4d252c9af157", + "lib/encodings/oem.pyc": "87092ad0a2f640506dbec48858bc711b42cb9f623f8d2aaf2e0486c618796803", + "lib/encodings/palmos.pyc": "33a0244013cbf2ac9c0d364859654b01e06ea0ea0fd39c992526ed40d514596a", + "lib/encodings/ptcp154.pyc": "6bbe231075d0628b10abc8ce8fcbea3ab0f13c131690e3bbb96d256fff17849a", + "lib/encodings/punycode.pyc": "57da62ed4b0971c9b3d7aa189e4fc63d040c8627909853701d64815a15f16cc5", + "lib/encodings/quopri_codec.pyc": "5d0dd205491ac2e074342f0501d70118778d37fc3c06a4c021ceaf762fdc3079", + "lib/encodings/raw_unicode_escape.pyc": "87eae53ca92e90dec6ca73b8028598a56dcf7ed24957c90a4763419ecb977dbe", + "lib/encodings/rot_13.pyc": "fe71dda8742eb20a84ee9b5c00ea151269c91e06d068d208ed5bba9c114566b7", + "lib/encodings/shift_jis.pyc": "e4fe396a99013a47f4f35fed76bbf1765006dd973c3f0facbde2d03683744fd4", + "lib/encodings/shift_jis_2004.pyc": "f9971fb6008b93028563ca63a10e3ac954ca5a7ee3c6ca25bdda428af42cb91b", + "lib/encodings/shift_jisx0213.pyc": "21bb5b82c2de82f087567900c7c821a32ec3e8f9e62a52057cbd8afa63aeb9d0", + "lib/encodings/tis_620.pyc": "f84bdf1fd1340ef032dc79f897fcad94a40c5da2cdb257a5d0053180298b2f7a", + "lib/encodings/undefined.pyc": "591a039b58bdf55c378b911838c5aef1f3f89f545a996a2ff6e0aad11dc7b22c", + "lib/encodings/unicode_escape.pyc": "2f0c202a5475cf8c152f3bf7f75a8a4ce83630f2193cba2359a93285df815331", + "lib/encodings/utf_16.pyc": "6ed41a335b5ebfa3b671853803d011f54b6351a70af24d8127cbc30272d75aad", + "lib/encodings/utf_16_be.pyc": "7c6d1a7745553a727dfe58b87b058b7ab9505892648a466ec6f3cfd779cfc55f", + "lib/encodings/utf_16_le.pyc": "bbabd696c5502e9419859dccc6d75c6de58da225c8ac1fe87581e8e039a297ed", + "lib/encodings/utf_32.pyc": "7a3d494a3d8a5d17018799c4395f4cf99dbdc4d26398f92501052deea5ada83c", + "lib/encodings/utf_32_be.pyc": "b0fa77c493623bb10366853edb8d3c3eaccb8b6b9a2638749f3b3fc6408e6c11", + "lib/encodings/utf_32_le.pyc": "bf767e8d4b38416280328ee3dd21f1a5ee3e834efb61034fa2ab41038a895a98", + "lib/encodings/utf_7.pyc": "e8798005731bbe3630fa511393644c4b3d9685ae26a0bec287ee6dd5e176e70a", + "lib/encodings/utf_8.pyc": "c63d47f0711ef28a1d29f8a4af32080c754aa3fb5caf3dbc21ce036ea6275ed3", + "lib/encodings/utf_8_sig.pyc": "f4d277baebe36240c4c724d5541ead493e81c21f25d89b2de4cd6d509b8cf7b1", + "lib/encodings/uu_codec.pyc": "236f4c508610a5e2e48fba802530b7fb6d16e79dc6762f02222bed6b02c1c768", + "lib/encodings/zlib_codec.pyc": "d01a005a4c98e069e6525934b888f5feb087f9a18b88d87ac38bce52cc45bb17", + "lib/fcntl.cpython-313-x86_64-linux-gnu.so": "2734d1e09ab16d63287b03ddc0647697e77eb3ee795c36f6938cea3f8e8545bf", + "lib/frozenlist/__init__.pyc": "3e3dfdcdea844606e7f9be3dd69f3e77a837c8d239ce642deb0db5507ede54ff", + "lib/frozenlist/_frozenlist.cpython-313-x86_64-linux-gnu.so": "4fb57635221abb8360185ca93de3ba7b8f78d93c0cb070722adad243958838ba", + "lib/frozenlist/libgcc_s.so.1": "137f5385f2fc44139b4c28b230e7e3298da51b04da7fccb0ec2e0a108054da1d", + "lib/frozenlist/libstdc++.so.6.0.34": "f3eb617c6c2b6f14db1e113aee0406afd0c3e47d753eb0e854adc8bf9a4d86d6", + "lib/grp.cpython-313-x86_64-linux-gnu.so": "097825f73cc224df50d4efd33fd0e0055ce95087ff7fb84cec4f0efdc3487b61", + "lib/html/__init__.pyc": "d2fb865f9170cc81d4a16320a6712d9b81b1e6be72ecc70752f41c43b84e0bd9", + "lib/html/entities.pyc": "a26f249e0019017df7652bb1543181692bdc8715c4733115fb7491bad7cc52d8", + "lib/http/__init__.pyc": "4e7d012aa620ca6d0c6f98dbe05be12d395a4914ec0b11cf36da01fd66aa0323", + "lib/http/client.pyc": "51979abe9a7d5d55310294c34e0c3a21db281667dc0d2df2dadb5959398a2cc7", + "lib/http/cookiejar.pyc": "3cb2c5c8fd7d04e8fcdf06ddd35a6624efca9cf7228e7dcb8638b32cbd655e4a", + "lib/http/cookies.pyc": "6ebad245818800b00cb1180fc08df622beba24acf949d3cb719fc7210fb3b498", + "lib/http/server.pyc": "989364c9265dfce753642f685c1ff5ba6dc67ff525ef751206ef0280b812b51b", + "lib/idna/__init__.pyc": "8ffc5650b4971d8854e307329eb80957d175cf4b595b8961aa5962e868942681", + "lib/idna/core.pyc": "7f0836740146c1bf71d857c58685fb89909568239dc7c083df630cb16eb56143", + "lib/idna/idnadata.pyc": "1cae10d46a8251014d4c20acbcc6cc372447c8730e3e2fd13153909412dacd05", + "lib/idna/intranges.pyc": "2aad7d44123e089a7f73d68fe9297cc5d9b75dc9639d7f71cb16589454f764b9", + "lib/idna/package_data.pyc": "b9d1ce4255c69eb103bb9793db6a7a14964b71a51c2e2e645d9041c80b89007f", + "lib/idna/uts46data.pyc": "e8672055afdb0c9b37fe6c4469d7df378670be3a335fc5ca6225760bea54a000", + "lib/importlib/__init__.pyc": "22a9ae9badf96d7d14b2dfc3df437f70b499d13a2703ec41abd03eda4f847470", + "lib/importlib/_abc.pyc": "7df0b948bbdbc9ccd1010fb9a0c84694b0cd659b367cbe574d1df391ee3f26e8", + "lib/importlib/abc.pyc": "ab50b07964cc74fb954982c5719a9f6ca1e9780f40ca27ea76075ba706878488", + "lib/importlib/machinery.pyc": "ba4e01d789969c50a8133347d507ad46c11f08428d74673317f8dc493e59b4fe", + "lib/importlib/metadata/__init__.pyc": "c86018501b28b7ca5a031498fd16c106db007d25897abf2c453e5ae5012ffed6", + "lib/importlib/metadata/_adapters.pyc": "3d6461cf1653be69cb13268f8dd7884c3e011a39389a5bdbee18876c7e2af90e", + "lib/importlib/metadata/_collections.pyc": "f67ac41169e990ef6008a81a2ef19b825aef56ff9314e3a63cec4bbbfd1cd2f5", + "lib/importlib/metadata/_functools.pyc": "192dd2e83bd7f45801f5853af67ef3681324a918a7dfec836b186a1b5bb2eaac", + "lib/importlib/metadata/_itertools.pyc": "b4a5e844889fa8ef3ec1e9275aab5ed5418c560eb264be20dbe54cf402757b07", + "lib/importlib/metadata/_meta.pyc": "89e3ea11a3541356d9fef9bfd86320b91904dfec92b2a244170ab1f0c83574f6", + "lib/importlib/metadata/_text.pyc": "c916acca4b8a05859a1c8aea3e55c77a66a229e8099cca8db64e1a2c6be1036c", + "lib/importlib/readers.pyc": "984866bd579d9d5fff19ff44643dc33638f907f3103b73a89684e1493c285391", + "lib/importlib/resources/__init__.pyc": "579c03c7eef91dbe93f488189871178ba2dfcc6315e8cd7a036fe6d419552946", + "lib/importlib/resources/_adapters.pyc": "a55a2e0b0349a542c670655447f8b7db43a2517aac60f8f1cec70981017a7306", + "lib/importlib/resources/_common.pyc": "20bb1d45febcee2092e1939d27a44ea32505a748744b7ae8b1f6b9be0213da42", + "lib/importlib/resources/_functional.pyc": "2615910591110b905c188df898e7991fb56355b223a640046c84cf002bc52f62", + "lib/importlib/resources/_itertools.pyc": "a2a5900409afe5ea7891924f26b01a174c53720cb5766227adb2b175a7737793", + "lib/importlib/resources/abc.pyc": "57c071934625f48a3bdf52940400648d7361fab99656347b0c4458b52ff0fe28", + "lib/importlib/resources/readers.pyc": "a4bf9f48c60f2a75c9c6eb811ca3e71c4b27815f894dd4149531c6b30bd22093", + "lib/importlib/util.pyc": "77d27dc69a6a0f20bdfc53594b222e3c2dabfa2b9707a7f133147fb57369a846", + "lib/importlib_metadata/__init__.pyc": "55ed566f7e4d69d475d2e5cc4c6e63dda554bc62ba0ba3454e24e8ed3663ff2b", + "lib/importlib_metadata/_adapters.pyc": "3cc0717c0b0d9eeba2321266f57074f1ed1d801225588ce833d83b7014d5f2e6", + "lib/importlib_metadata/_collections.pyc": "483aa25420a23e13b8c75045ca16b2f466fa906c37d436c5b04a05819e8e182b", + "lib/importlib_metadata/_compat.pyc": "c507162cf523605c8612bbf29267ac9713a3159d51488f6f2a10c9f9c88e925b", + "lib/importlib_metadata/_functools.pyc": "663579692d59c12d18240daff74000fb7c0283570a2352d8b41c0d893a2a465b", + "lib/importlib_metadata/_itertools.pyc": "53ce762ae7bbcf6100058b0ed22ea70f4a25e4b3514d1d1bbb39fa49cbe6e465", + "lib/importlib_metadata/_meta.pyc": "f2dc4d4b7ba003a7f4e126579a8853cc6a56ed2e17574ba9f9779c6cb74da62a", + "lib/importlib_metadata/_text.pyc": "f85d16673dd0128336a80c8561ea663e112bd432599004c8b9cfd7e677422e3d", + "lib/importlib_metadata/compat/__init__.pyc": "1021b3d48bda3ff9862d0c511356d0c303211fd8e89f0727851773e16a218fc1", + "lib/importlib_metadata/compat/py311.pyc": "7e013b094add40ac00b26fda1cfdbc4457fc8bb1829e62cd48b30879f1843a96", + "lib/importlib_metadata/compat/py39.pyc": "f4067e346dd73ae1a7adaafc06b0e86e6464f01d3820c2056bd95cd0256e3e39", + "lib/iniconfig/__init__.pyc": "fb06b735587f75c4c115910f67742343eb30425835828d1d7ac97fd0e8b24656", + "lib/iniconfig/_parse.pyc": "c1e57f05c6714471acd53d5cf65473e398accae7d18b5a2780f3561d06e7d269", + "lib/iniconfig/exceptions.pyc": "882cc0427f3845f42bb1b654217bc5f7a8a6570d124ce4d73fd032a932ed67bd", + "lib/jaraco/context.pyc": "f63fd48a0b09f1ad5fe59ac334f2af23e39ed71679b011eaec1e1ba4cf8bd0c5", + "lib/jaraco/functools/__init__.pyc": "d539b6213ba2830fa2c84259dcbc343cad909ff602814232ca88bb417b748609", + "lib/jaraco/text/Lorem ipsum.txt": "37fedcffbf73c4eb9f058f47677cb33203a436ff9390e4d38a8e01c9dad28e0b", + "lib/jaraco/text/__init__.pyc": "4f39e775e39d102f4d30a703974525838e1f7ef7c1ae0b1611005684bb97c10b", + "lib/json/__init__.pyc": "a743e4ca070006a1351e9f41ed42f4a9c7008f81d11004fb4a65d884eb302c90", + "lib/json/decoder.pyc": "d91ebc5eaf62ea3c6adafb6bb88524ebbe60bd90ebba5caf0482080bc42f4091", + "lib/json/encoder.pyc": "30b9ee965500cd9acee983284c56c0ab3f807ed459d4b05b14c1782b7bb14e28", + "lib/json/scanner.pyc": "8b007a541a3a1d2b98224ac75e0a021b946f5f1c7c0b8458ee4969e0b893c6b6", + "lib/libbz2-a273e504.so.1.0.6": "2acee2df9bb0831e1a3d96a5512401c327f1797190f4119d3489f055fd34c9bf", + "lib/libcrypto-85e6b9d2.so.3": "7826eb7cb6635decd07716e94c9b68c21c78b66ad201dfbf555ac8ffeafdb9e6", + "lib/libffi-af4ed708.so.6.0.1": "c096a87d15318afc47510938992571be481e29ea82d49895a87322fc1f412f3d", + "lib/liblzma-004595ca.so.5.2.2": "f105629aa48d03620791da98c781e77ac5843723f681fdae5e870e85feed7ad7", + "lib/libmpdec-eba35878.so.4.0.1": "3fcd8b2298f1127812f9974580820afa18bbe2dbffe9a70d4e735708f298c6cf", + "lib/libncursesw-7e1cf128.so.5.9": "ade5fc012a8ba5ca5706a45d75fd1d2d8c03c53094cfd02c9969ce79c099bce7", + "lib/library.dat": "1794a90e19985ee2dee89f9bdffac8dcb3676e2555db9469384493d14708aed5", + "lib/library.zip": "503b1a45a3fddb2cd91004b63aedd61adb8a6f66b5b6782e6012748781abb570", + "lib/libreadline-2c5f7b8d.so.6.2": "d18e6ae0f60020c59da3cdfc99072139621796979ddb856177336c0524bd2752", + "lib/librt.so.1": "f9d5adc794ed3c8e471322dc00594bec7cdb41a91826fea5f84cdffdf32a0108", + "lib/libsqlite3-01ca9f0b.so.3.51.1": "3037f4feb728a56fdff8471db43646511162890ac9a574b514d7855731509558", + "lib/libssl-8c54fafc.so.3": "30888eb384c5db0a61021bc6c370e70dd88ef182d18b4a9d5c63ce3b84b7c837", + "lib/libtinfo-10270e32.so.5.9": "e1676f7e9545ecbec991e229ea11fc4f6a245a4d828be90422d6e3923ee738a5", + "lib/libuuid-f64cda11.so.1.3.0": "652d0d569e4ffdf7d2f8091d0b06ddf4498d5aaa3c7e5abe40c30678ee25a1f4", + "lib/logging/__init__.pyc": "423fad5e1b21361a37131788a398729fb519bed5823bdf3c4c2330c3570c232c", + "lib/math.cpython-313-x86_64-linux-gnu.so": "9254d145161812011d0edb28a61c72d3b906c472ce14d4e17b984f98ff159c37", + "lib/meshchatx/__init__.pyc": "55a439f62810e53fe62d7fcecaff9991a5ce0cf551f6181d6786115cfc36c796", + "lib/meshchatx/public/assets/AboutPage-0IhYgVnf.js": "be97f886fd21bb730da22f3d86dd395c7bba9ee607b59320a399dbb82a089d81", + "lib/meshchatx/public/assets/AboutPage-8fEiI5uK.js": "ea611e6c05060ab6113a5257fe1567289edcac8fcf7b8296f31b43a62deb4a39", + "lib/meshchatx/public/assets/AboutPage-BKLttI6i.js": "b875d7ee84f7f21916109e655ecdbc9a2aea276e9dcdd293ea4df5ac984f6a98", + "lib/meshchatx/public/assets/AboutPage-BMjlT6TK.js": "a819b1bd3cd16a9e724526f1b70e1e3b9122dd9e06593907d0205a4efe117cdd", + "lib/meshchatx/public/assets/AboutPage-Baol2fuy.js": "68e8abd9d0a1f76f8ddd0b33f2cbb4ff3b9ab7091ef561565c5d73967a50db00", + "lib/meshchatx/public/assets/AboutPage-BcCaFooV.js": "d963caa627219ce5688dc4d713711033e2660e5aaa48540295db17d24a5984c7", + "lib/meshchatx/public/assets/AboutPage-Bn9rvwVK.js": "a6b193ef20eac72b320ceca8ebcd4bef596dddb493e96be21763f1d58bcbebbe", + "lib/meshchatx/public/assets/AboutPage-BzBwKHSG.js": "f87555d7df8436a3ceb96229c75a9e577854c7ae83370d9e0b6b492d76831285", + "lib/meshchatx/public/assets/AboutPage-C9JNCYeR.js": "e89333d84a9e990e25c89dcd4cb14604087d6c3f06b162e79a69a1658d7a31d2", + "lib/meshchatx/public/assets/AboutPage-CHatkEki.js": "b790af35e013a477024c26cbcd8579ebcb319aefce9a1ec7fa695edeafe9e897", + "lib/meshchatx/public/assets/AboutPage-D4r8SBwq.js": "38fd9844b860a9f32e72e89027313cc136e139d451bdee39fd971efaf77adef9", + "lib/meshchatx/public/assets/AboutPage-D8YSes0g.js": "a705ef6cb7bbadcdcca2bc95fc41eb131448d1f639ef1ada24ccf4ab4a876784", + "lib/meshchatx/public/assets/AboutPage-DAC1QiAp.js": "20cd57b43a7b3f84ff35e3c3b050d52eb5cbe17f222622176e8458c8c6aeb96a", + "lib/meshchatx/public/assets/AboutPage-DCeZPdz1.js": "d488356ed2d2c4cf6bad1dc1a76fac40ddd5cf8ae9f15c700a2d86266be2990c", + "lib/meshchatx/public/assets/AboutPage-DDJYGtfQ.js": "6824866eb30a454bf1ae261e399af0794334749f3fe9a4b57a4aba202d27764c", + "lib/meshchatx/public/assets/AboutPage-DrUL2TvN.js": "a085bdafd2fcc7f374a8a44df7210b485fd887e373f77f7c992c6b32ffd980c1", + "lib/meshchatx/public/assets/AboutPage-N2UDxc2H.js": "7d112575b42b15e099768502474e9351dc6c6187c7746c93baa407941eb16ab6", + "lib/meshchatx/public/assets/AboutPage-cO7wDO0p.js": "52a488610c8761150402c5fc97a3fae6fe8ae0226a9e3fdeea48349948e1902e", + "lib/meshchatx/public/assets/AboutPage-jCiPes_8.js": "290f1087991d8b33569e8bf9b3e94646c0c3ed0925186086dc19b5b00b1be40c", + "lib/meshchatx/public/assets/AboutPage-mT6yCyKK.js": "560e6a3f5ac5837a50005ee2bf022bfbe081bea4edf5a2bbdb858cdc4c2913a1", + "lib/meshchatx/public/assets/AddInterfacePage-8U5lyEuC.js": "a54d4e83b86185c420ff1ce8318ad3d5d1e0e7f770ea76a1136e4ccf63440690", + "lib/meshchatx/public/assets/AddInterfacePage-BCtbSofF.js": "58f202f4dc213f5fa1e24d04c3a43896ffac4a6a4ba84252a1ce3678a7c23e03", + "lib/meshchatx/public/assets/AddInterfacePage-BMaqdHgt.js": "405f581dddb488a46a1a38edfac866ad4fe74341d7a257176c65c2fd380cf0c6", + "lib/meshchatx/public/assets/AddInterfacePage-BTcYysxX.css": "61dc0b5468c223aaff8acc47626e4284e72e07262b5a0a19d36707888f7208eb", + "lib/meshchatx/public/assets/AddInterfacePage-BUgU4mHN.js": "0e93cbfc04d75845850fe092ad62a3728070dc94f41239d8031a357dfeab23f6", + "lib/meshchatx/public/assets/AddInterfacePage-BZsc0GRV.js": "719d721bb9d8ede61d49eb952ba97921924a64c5f78cf287b8b6bf6cdb72387c", + "lib/meshchatx/public/assets/AddInterfacePage-BdMCP1YI.js": "204a083e1dc0cc14eb6c6a4576c623d64c79b0a873a0fffecddb5eeb794118e4", + "lib/meshchatx/public/assets/AddInterfacePage-Be5myeHR.js": "4d018cd57da9cec137655ca974763ecb13e3291ab4c58b8abc68663f09a0aadf", + "lib/meshchatx/public/assets/AddInterfacePage-BmsAxVL1.js": "7fe441daea357e273d99cf203bb3a04639765e94905d78346f3a74784873c3fb", + "lib/meshchatx/public/assets/AddInterfacePage-BqSlOb8S.js": "ff15f4d2720903de44609e10ee2161b315d2285d1b4420f02318620f2a3ca248", + "lib/meshchatx/public/assets/AddInterfacePage-BzRcwDV6.js": "c8b85385f076fd7137a02c0104059492de64500281e54c809af820dc4c24de04", + "lib/meshchatx/public/assets/AddInterfacePage-CHsX34aM.js": "c0c86def1cf79086fcf251f5bd56ec72e8a3943cd96fc94f1417bcf67a1ba6bc", + "lib/meshchatx/public/assets/AddInterfacePage-CK7nWyjv.js": "42f25fcc18cb40dd0546b65c5f167aacbf40348b9511a43ca98bac1d6e307ff6", + "lib/meshchatx/public/assets/AddInterfacePage-CYk70Bnr.js": "6e71d5bbd13d27dd77b08ecebef797d946d5b5336923acca7f62e6d050eddffa", + "lib/meshchatx/public/assets/AddInterfacePage-Cp0aXqUn.js": "ded3735137237672936d6726ae6d75a091ad2a96e625192db1129ee657a1d9c8", + "lib/meshchatx/public/assets/AddInterfacePage-Crr-YNaw.js": "2cd4c836089ea6aae5eed770e32616cf953a38ea6385e817cde4796d81aba9b7", + "lib/meshchatx/public/assets/AddInterfacePage-DVuvwyDC.js": "4037e6751c12ff9db02915ad9f782fdb7729efec3a16a3fad6e313dd578e8145", + "lib/meshchatx/public/assets/AddInterfacePage-DiEX5AfZ.css": "03ec87be159836fd2f2bc256a1cf6c19a206e6f0b6b17e3ae4f7ec6891687a08", + "lib/meshchatx/public/assets/AddInterfacePage-Dk6b4P9D.js": "6940d4c0d65b20b9b4d5c937fdddee735c5c4c3df657a45f6ef62517c65309b0", + "lib/meshchatx/public/assets/AddInterfacePage-Y5-VKBIk.js": "bf511802432a98c3bb2408bf9edfb6d75c1532a6ee26a7e6f38fb04ab02beaa1", + "lib/meshchatx/public/assets/AddInterfacePage-udEolizH.js": "ce6eb44eea6d61b67562e9d69092634d7383dea1c4bef0a211f7dad7ae223462", + "lib/meshchatx/public/assets/AddInterfacePage-zIW8kofQ.js": "a97fa4b221e628d246be8420d0c2508690fdc1c80d9140949c1b17a72a603f06", + "lib/meshchatx/public/assets/ArchivesPage-3ZoRbsmi.js": "fde1c3442c645107042a8689e613225a9432926ccdbe03bdb75450fd50e6efed", + "lib/meshchatx/public/assets/ArchivesPage-7LB1KeTH.js": "a22c8b1aa71747240dae715b155f4a1b47fe6c303fa57b9d57b5b4359c4f6532", + "lib/meshchatx/public/assets/ArchivesPage-AaES3-lS.js": "f8bf7a93042bdf6b6532106886afd1455ed14fe0246589441e2b22af89f4b13b", + "lib/meshchatx/public/assets/ArchivesPage-B15552h0.js": "443edf93cd2f63ea6c3223ac2ba6379321a06b32b9a25a2966523df5fd85c8ec", + "lib/meshchatx/public/assets/ArchivesPage-B8bIEMTn.js": "2c4f39ff0cdebfd0f306aa40bd660be0f2a401137cac8d9188d462974b047edd", + "lib/meshchatx/public/assets/ArchivesPage-BLofx5Zi.js": "e9eea40e43079084781a8df397c652b52b7049252b282e779cfb629b34abdae1", + "lib/meshchatx/public/assets/ArchivesPage-BeHVXSmu.js": "7fdbccaa7c8d9cd2ba710824d278978268a0fd5d31ad43bd84f27a0ad8b9e725", + "lib/meshchatx/public/assets/ArchivesPage-BoD5FNM0.js": "74ffd82412d7f1411283ce2a328d69f3afa1de6cf8327ccfbfbdb7d248c4b328", + "lib/meshchatx/public/assets/ArchivesPage-C1yHbXva.js": "485a6363fd0229c6778b45a96121145006eadc3a4c1f531ce1264406a8161759", + "lib/meshchatx/public/assets/ArchivesPage-CJFohVhF.js": "d6bf0fda552c71fdd9912ac5394401301ce71900bfacce94df8bbf2df3b0efb6", + "lib/meshchatx/public/assets/ArchivesPage-CPxaPYQo.css": "f8cf0bf5a3d3c7c61b339e4246174b90e8edd0f01fdc87f5fd76e99c32b1bd5b", + "lib/meshchatx/public/assets/ArchivesPage-CjWmGi3s.js": "9f9f6c9f1476e44525aabdc1cf6d2e1c6b2ee841fb85cd5a55e767abcc0930b0", + "lib/meshchatx/public/assets/ArchivesPage-CreAUQ-V.js": "cd57436865376503b20a3263b1b014fc39ae59102910aca718f1979f57a5067f", + "lib/meshchatx/public/assets/ArchivesPage-DCznv-zV.js": "d1a2a730f22790ef535db226771f70735cdcf14ca21104ed762e98153eb01641", + "lib/meshchatx/public/assets/ArchivesPage-DQNKVWWo.js": "8be434387e152fb31cbbb5b32c0cc4b7ccb8c63784f80cc7163a11e45c8240fb", + "lib/meshchatx/public/assets/ArchivesPage-DfAEykmy.js": "df01fe9cc5b6013e2a84907fb923edb87e2a22bd821b65638d1527ccc84bfc30", + "lib/meshchatx/public/assets/ArchivesPage-Di-dIsoJ.js": "bdc86a5ca40adfcf7fd09da7f88450c0c77e65209b9ee0b9133511149af5cfb7", + "lib/meshchatx/public/assets/ArchivesPage-Doi98rCD.js": "f91519241562cd872d3784d793a283864a131b8f85a3c598e58750abab64d400", + "lib/meshchatx/public/assets/ArchivesPage-DqLN89ND.js": "70217190b4b707c524563a537bb08ee6a5976e80296f59185639fea3a55a05c5", + "lib/meshchatx/public/assets/ArchivesPage-MQE8c1mh.js": "14d23fadb15611de351a698a2ba4629aae6db1f254398a351812b07dc2b1218c", + "lib/meshchatx/public/assets/ArchivesPage-SegXm3vv.js": "aac23f598e672781342506f453e9d573f7924162b8f9f219f3664aae564279c0", + "lib/meshchatx/public/assets/AuthPage-B8fvh-c3.js": "ef3b4603f62ae490b274b10b69784d2cb305cabaeb25494d5832e5801b45295f", + "lib/meshchatx/public/assets/AuthPage-BQii6kbQ.js": "5e46fe0dd5d098071ed41146c0ccc60a209a62039fd481ee1915c5395e1c53ef", + "lib/meshchatx/public/assets/AuthPage-BScK_nq2.js": "a227df74dd7e182188fd8d5b0a66b6e915695ae7dae21726a87e6fd3d7e3a563", + "lib/meshchatx/public/assets/AuthPage-BWX5PNrJ.js": "f5e9e870e3c059a7203def71892fcd4603d3236e2945e3d4fb75bcc8a2be585e", + "lib/meshchatx/public/assets/AuthPage-BagJfDyo.js": "bfb4fbd35bbe9dc6b50d9b8f1ba93109df451750ca3f662618580a3516ab4528", + "lib/meshchatx/public/assets/AuthPage-Bfh9quB9.js": "da133fbe8bb18280d2c53d14853d6bae92786b91237297967ec2fd4507c46845", + "lib/meshchatx/public/assets/AuthPage-BytNkU35.js": "1c1c7fb89f0ef26f26bfab5e20275e838d3e16bfdf6394840785d94ddbbff160", + "lib/meshchatx/public/assets/AuthPage-CFC1s3eA.js": "a2c0f1f63836817e708a94b54ed4c66620a46684cc53e0c7b69d8de5856642bb", + "lib/meshchatx/public/assets/AuthPage-CIDofeln.js": "c6087eb9c56f4350fa098ad1e1d978045244c08382f3483b12880c03768bc36c", + "lib/meshchatx/public/assets/AuthPage-CbO-FPqt.js": "40b5a6050fde24bae4afd6597e33ec1d01a46577613956e3798cc2ba9b969177", + "lib/meshchatx/public/assets/AuthPage-Cl_ZNA9t.js": "de9b317c4abb001603c5434af2f19b7167c2feacc826cf828a0c1bb5f3833929", + "lib/meshchatx/public/assets/AuthPage-CnLp5Bef.js": "ab3beb2fbe4a68f9a8e790655cd3a164f25c814f4146632e7a47ec90ee933f0e", + "lib/meshchatx/public/assets/AuthPage-CsBUr8cw.js": "70f63f63b6ec11c27baae6b832f371e85ca2ce6394b29271eab9d717f6da4ac6", + "lib/meshchatx/public/assets/AuthPage-Cuw13OWi.js": "c9ff77da541874cb4700f1723136ee746f49506162671cbc2cee4b9f97fc9c5c", + "lib/meshchatx/public/assets/AuthPage-DE_R8ybi.js": "65b917ee43a2b8e24d78266a688fa6bb7e9709997f7dc1a5a351ad18f6981c95", + "lib/meshchatx/public/assets/AuthPage-DPOdVS_2.js": "313265c078c81380fd4f5c59611c8afac6aab58e86c95016a55fdee8533d42f5", + "lib/meshchatx/public/assets/AuthPage-G6XYwO3I.js": "e690d7c33cac1460e97230c971009cc32082e5be7929c992a271d8b87af4c641", + "lib/meshchatx/public/assets/AuthPage-XSiZwR92.js": "a3641bde2eaa53c066c108c4f5a186497631edbd4b75b32b8449e46ee718573d", + "lib/meshchatx/public/assets/AuthPage-d0SgjC6f.js": "913b4001bcff6aa1a0c09493294be92101d1a2fa43b3aa55fe2fb13da87c4d4d", + "lib/meshchatx/public/assets/AuthPage-mqiDR_K5.js": "516d1705303c381461be758da87a3e9ef065809bed5d2588d4841d8df8a88f68", + "lib/meshchatx/public/assets/BlockedPage--w5BAQVc.js": "afe83111a422725f289dfc6e2ceb04e37e6e30ca2cb5bfd94a062b5ab7a1725b", + "lib/meshchatx/public/assets/BlockedPage-BKlUYsLN.js": "9acc91d041d1592316cf7620ae9fbeab79cc5e16970cb162c9345a1052570118", + "lib/meshchatx/public/assets/BlockedPage-BOvzaN_C.js": "7d6b544b81c5113c166616d4fb3dea5f02036b3443989d947553fd03af44f4fc", + "lib/meshchatx/public/assets/BlockedPage-BQwf8_om.js": "b2c148b9f9142f82d56033258fcac4af4fb761d3cc61587016c37d3b4480678c", + "lib/meshchatx/public/assets/BlockedPage-BSMLtAQF.js": "8cde5e3b110c9b2d5123d7939fb7ba9b8bf1679e853ed27ec8aad4ab0e5e1089", + "lib/meshchatx/public/assets/BlockedPage-Bb8MI4BS.js": "bd992e2c9e7a5346b00bca857800a023b8f2c9d159f3aac8e8d22bf108d93b63", + "lib/meshchatx/public/assets/BlockedPage-BbR4aTPm.js": "3cfa7a06970b0f7a143436239720cb04bea09e16393a453cd59019d7c845f2fd", + "lib/meshchatx/public/assets/BlockedPage-BcyInvbm.js": "6dfe1f392487ded7f2455dc75497b5e588c1e8867b667990c2cc038a4a3a5b21", + "lib/meshchatx/public/assets/BlockedPage-Bl6NIBrb.js": "b8b36625b41a0156a4819c9abf392734d4030768dd3c7c89b7f72c93421db8c0", + "lib/meshchatx/public/assets/BlockedPage-Bogen_i_.js": "9d7ebb2b710eaf14e769b444433748692759c8662d22aecb498e8fa5289d28ed", + "lib/meshchatx/public/assets/BlockedPage-Bve9i13H.js": "4ae68ec7f8f4b7c2a17a086c4d68ea247cc9fa55b5fc12a07660162b4c0b388b", + "lib/meshchatx/public/assets/BlockedPage-C70Xjfnm.js": "d12008d486e83ea90dd21583c3b9af0f323af2faa04831838ec4403925786c91", + "lib/meshchatx/public/assets/BlockedPage-CPTT-CSB.js": "cad34fe06f109b33e4ae7b1cc796fbd7a2411d93f689f5521945e4bf70d99546", + "lib/meshchatx/public/assets/BlockedPage-CUTBR0Kx.js": "39cf9f0af4bc86db7fa3d5bbe3d2c97d901b3e034031278d4f0bb48d18d6c024", + "lib/meshchatx/public/assets/BlockedPage-CUv4mTjv.js": "551d31be0d5b5306335be88df76ed1dd8d013ed980b48fd4dd07702cc8903346", + "lib/meshchatx/public/assets/BlockedPage-ChJxX-YD.js": "fbf75b23bf09b612f8f9bd0a80d03e7ae1ed88095963635d6d24bcdfe94c8859", + "lib/meshchatx/public/assets/BlockedPage-Cj5wW2JY.js": "aa8223bf9f1909465b89b22f76749a991c39bb783ec27b423bef12b0a6b2cf64", + "lib/meshchatx/public/assets/BlockedPage-UO9kbItm.js": "51cd72d47cf9782036188b0ca22ea85fbdb63759a0adbc3a7f46bbb881a35270", + "lib/meshchatx/public/assets/BlockedPage-fglMXFtz.js": "edfbefbc2caa6fde26004a5eda5cc41ad27ac1e3b63e9d52bd365301934601b3", + "lib/meshchatx/public/assets/BlockedPage-nnfC_qop.js": "0afd8a8d1ac138accc46df7e0e3cf480fbc4f0b84cdf712aa14d3bedc9f17fbe", + "lib/meshchatx/public/assets/CallPage-B9A5VbTO.js": "d4a90455473540966994d4404557eeecd37318ebefc4787b31f12e244fca3cf8", + "lib/meshchatx/public/assets/CallPage-BRIKPbmi.js": "fe836a0cce17b7370e7deb03cb8bcaa4272bb81251981eb4047263951b0c8388", + "lib/meshchatx/public/assets/CallPage-BqqYln35.js": "b9b149e7a963374a939b2b6e5e66c75eca77906eba091441599e7be0e573de61", + "lib/meshchatx/public/assets/CallPage-BwAxhKKp.js": "756ebc63cb1e87d716d8d46d47380bbc1e1f10de8a6a8c469190b91af4ad11f8", + "lib/meshchatx/public/assets/CallPage-Bwf3B1oK.js": "930180e1a993f6252e56a9d74ffe99553fc652341944ef2e549638a987f5beed", + "lib/meshchatx/public/assets/CallPage-ByNY39ve.js": "5f4f0fb49fe376afcfd491661f7d9959c382a3e9c453901ebd2797f1804ed740", + "lib/meshchatx/public/assets/CallPage-C5kSsHhI.js": "73c6790c08a44d3cb9131b4990420483fcacafad90d1c58c04e92837d7ab046f", + "lib/meshchatx/public/assets/CallPage-CkKTpT7n.js": "bead262cc1028fac6fc7660d854a3db3f383cabe202e9667c94580e71ba53ff7", + "lib/meshchatx/public/assets/CallPage-D4jb_f8Y.js": "2ff9e913d7e05765eed2db1beba525cc17f17eb6cba0ec4bd92bd3e167b76e55", + "lib/meshchatx/public/assets/CallPage-DAGAK42u.js": "4e0045609ef9b149388d2987d51fc58b22ed12a3382cbb228abeb0d532680862", + "lib/meshchatx/public/assets/CallPage-DD0NVwu4.js": "750449435b386e063260c66e8f601de78270cb333d0f5c476c077117da21e02a", + "lib/meshchatx/public/assets/CallPage-Da055DPT.js": "a4c3f0c7185ecd3a88cb40f41ed9bd46c1fce904d920a252e7e8046827f32f75", + "lib/meshchatx/public/assets/CallPage-DcfOes9s.js": "b45be33fea18b0ccef9003690e1411896ec9a9e9913d92d2ad2be17d777bbd33", + "lib/meshchatx/public/assets/CallPage-De8paHKH.css": "8f3c50ad7162d9ca7f0738bf4714eaca03b36f1f609ba158b7d8d7344e6f7ad5", + "lib/meshchatx/public/assets/CallPage-DfOmVy8A.js": "7eff0286f3df1c2d74284ba9241bb5919d69947a7775cd717725fde5804cbefc", + "lib/meshchatx/public/assets/CallPage-K4yaGC9s.js": "c996db74e2c08d8f08beffd464565eff597d96d1ae75a74250a5bc28bd08984d", + "lib/meshchatx/public/assets/CallPage-dxJwwjb1.js": "02c8551f07a3c93cfbf5f7af1d682dbff5247876bf8ea1b322a8560c89947b10", + "lib/meshchatx/public/assets/CallPage-iNLpjZ37.js": "2ecdf1321a3382783e66df5dd61e4fffb210c7a2c9d8c34be236f279d53a2f32", + "lib/meshchatx/public/assets/CallPage-k4WQa0my.js": "453bb574d9473f8238a5dd0b8505dc98843cc24f0ab6aafa09b6ee7521938acd", + "lib/meshchatx/public/assets/CallPage-pUEXQpMp.js": "8de02a002921ae84bbd595b4ecab0df71649b5fe21bf359f71348921b263026d", + "lib/meshchatx/public/assets/CallPage-yAxsVFe7.js": "83cf69b23964fa3dbf4a0cffb0caf7af66e4a289d2d586763f3ec296082c45e1", + "lib/meshchatx/public/assets/DebugLogsPage-4zJ9O4eQ.js": "9d4653a52e93befc50cc6edcb19c08920411e4f8364a3854cd697be6bccdc063", + "lib/meshchatx/public/assets/DebugLogsPage-5UW3nsMS.js": "a6e0960ee21d89409dbbf0e9b990d1984269bb9fb9468873645d3e1391b2bd49", + "lib/meshchatx/public/assets/DebugLogsPage-B3SOBo9X.js": "a3d20f64b34b7a217a1cfc0f525547d31e5c78072233fb782d44bc1590e1f60f", + "lib/meshchatx/public/assets/DebugLogsPage-BNl6PdKw.js": "095ded4961531b67392ef7127f5cfa91459a5221464f2fe2e8c80eea5f9e6795", + "lib/meshchatx/public/assets/DebugLogsPage-Bn8RD8Zg.js": "5a3e958cfcffd6ded7a45c719827cc400fa9a018d666ef96fc9fe4ceffc57265", + "lib/meshchatx/public/assets/DebugLogsPage-BxPvNzLG.js": "16d67d2d2a4d825360c077d7529565958506923b539436bc756398304bba8bd8", + "lib/meshchatx/public/assets/DebugLogsPage-C0L8VN9V.css": "7e293009b33eae8b7b2ebdbc0b37b7a6c7e10d980f9399145ddbbc171bdbe6f5", + "lib/meshchatx/public/assets/DebugLogsPage-C6xFRLE0.js": "e9d2213c42749b082dc182c1e190314f5ba52f6bd88ee051f9bae285ffcedd95", + "lib/meshchatx/public/assets/DebugLogsPage-CDvs1-mH.css": "c974af1f0bccc095e14ee2d34861daf60fc8b5af95acf50c18687c48ad132a23", + "lib/meshchatx/public/assets/DebugLogsPage-CP3MkkCv.js": "c762f17081abf972b557e111546f666033d304cf0e67374d95e08e0e05d17206", + "lib/meshchatx/public/assets/DebugLogsPage-CZJEcwRM.js": "1aa967b389ad8efe5d529ad13a2b4613526f185c358a43412070e7a1349f91c4", + "lib/meshchatx/public/assets/DebugLogsPage-CcJfflzG.js": "3f650e18c92aff0ad7ec979d4b4d2f2ab335944176b00eedaf22c74af1b27264", + "lib/meshchatx/public/assets/DebugLogsPage-Ce4ZfS-b.js": "019f27cd38c96ca22f4a4c2b8831cf6d6b5fe4d66caefd00f11e60cd22400068", + "lib/meshchatx/public/assets/DebugLogsPage-CevruSTZ.js": "3bd5f85166055f20c93cc52ff2127701309f4c6339f22fe2b9e62449fa25af1b", + "lib/meshchatx/public/assets/DebugLogsPage-Cs9qaJhW.js": "d246ade48fce67dfcd40621f4fe907415486d801480a0c4e52f4e74a5a96397e", + "lib/meshchatx/public/assets/DebugLogsPage-Cy8As8Ax.js": "998ae00f250b91067b7060bdfc380580e4799114b53ac391aabdd60a4ea91143", + "lib/meshchatx/public/assets/DebugLogsPage-D3P9cvkP.js": "1a0c5af94a21032a9d48865ab471131b32fbdc3a66a316e85e6dbaa730792141", + "lib/meshchatx/public/assets/DebugLogsPage-D74Sftux.js": "97ecc1b085a5284fa375a039457c3b4c0e5c55aa0c425b2aab06156d280b5df6", + "lib/meshchatx/public/assets/DebugLogsPage-DehBhZqo.js": "80e0cadc8d7d66a1a896cc9fe1b69b1b0627be083393b2d32c4678645f61eb42", + "lib/meshchatx/public/assets/DebugLogsPage-Dn0-LMnJ.js": "b68d5ea0b6fd21006400f3850137bd8de9f740faa39407b64d837029cc9ce86a", + "lib/meshchatx/public/assets/DebugLogsPage-Dzy3VE6l.js": "3a8dfc210519a32fc18817a28a03bc765429a063a2ca689b8ac9273d4c7b5265", + "lib/meshchatx/public/assets/DebugLogsPage-gQY3fUF0.js": "147125c86aa4fcdbe729a86f66787099c5f0c5ec9b6ff407f280f1f841efd1f7", + "lib/meshchatx/public/assets/DocsPage-2_adKWz5.js": "e5b89209f8d2a62c89e263469111f0a2d0d196b6879d96d4d6ace990d1a08e07", + "lib/meshchatx/public/assets/DocsPage-B-m7mgh5.js": "f8b24884d2240fea52c8c8213195745aeb25b2ca8b77a773de4e47532f567dd3", + "lib/meshchatx/public/assets/DocsPage-BEg7eanQ.js": "36ff4f8aaa910e62c8b5e0c1369952cc4376eb8dfee455eab2fb2da90ad34803", + "lib/meshchatx/public/assets/DocsPage-BKOCiRrr.js": "f2f93c9dcb1d75d91d9bbc6c91f50f44a8daf0407b4a449fc1d7a9f54c4beeff", + "lib/meshchatx/public/assets/DocsPage-BS52EMoo.js": "49d15c52092ee5bb639e04ea3a043955a5ae65fa51abe02e1f26fa8e05958ce6", + "lib/meshchatx/public/assets/DocsPage-BTY2zrzo.js": "efac452791ae3f908f1a01ae071bd47380038b86f63ce67b2ded287ae5c81f10", + "lib/meshchatx/public/assets/DocsPage-BXX9iq1d.js": "9a6a297a95504b6b32fe96b6f09ff3b756ff4ae3e5f73a8a393f96caa270a515", + "lib/meshchatx/public/assets/DocsPage-BstDjHTu.js": "389e9c0144ddcf099fead7044caf9d75a178b6eb7058701f3d7e61ac59460101", + "lib/meshchatx/public/assets/DocsPage-CNRrTRn2.js": "bd18fab4cd464a806c56dce2e1bfd4d42892a5f6e89d4cef9bf09bbec9f5b570", + "lib/meshchatx/public/assets/DocsPage-COB1YgpN.js": "d3efa697d7e41103982dfdf907bbe71185f5d3737a51c3deedb227e34f34393e", + "lib/meshchatx/public/assets/DocsPage-CYi8pzEM.js": "907e925475080cf1e4d92740d00281c3581d5afb149822c17dddc00950b37e79", + "lib/meshchatx/public/assets/DocsPage-C_rhvfLw.css": "8fbae748c54f0d0898d860634da36f5b8556351db68d72cc1a6824b2b5fa8d87", + "lib/meshchatx/public/assets/DocsPage-D4LG5S_A.js": "88874fe49a120f0fe8a302268f22871a7d13ae3d4af568d05d59c3c6bbd962df", + "lib/meshchatx/public/assets/DocsPage-D9i9itaR.js": "8696f8038aa7e16f50ea7260e5954c47af7b8b204dbebb821e4487608d3753bd", + "lib/meshchatx/public/assets/DocsPage-DKNLCnf3.js": "a144235811aee1e8e77c7b6edff3660233f96308edc87b4be8bc68e39c5a2266", + "lib/meshchatx/public/assets/DocsPage-DZnaYyVW.js": "63daacfe84767a03c02ae3b21955b0ea0c5b2b4df39017f532f07bc23aede3e0", + "lib/meshchatx/public/assets/DocsPage-DcP31Aw9.js": "9a37b54e11a8fcb5562133a3e4dee291cea99e846e45ae7c93dcf5d7e428129f", + "lib/meshchatx/public/assets/DocsPage-DfBdX1MN.js": "6d8816b65a3ea61eed13a19f4ae976fe59355b5b79db89d499385fc03c3c1847", + "lib/meshchatx/public/assets/DocsPage-Dq-wqU-E.js": "1262db491a0ddd6a242267d58856707d1de4c475b1353b9371b17aa32685b562", + "lib/meshchatx/public/assets/DocsPage-DrRohStP.js": "2312be0223d4949903f600dd264928c304896bb141d93e6592070b9153be7f87", + "lib/meshchatx/public/assets/DocsPage-DxRL1MsW.css": "2727fa188637b6cb7e9a5f854bb64f00052ed63731865bf349b323048e20d948", + "lib/meshchatx/public/assets/DocsPage-ddW0eLHn.js": "7d0a9a47baf19596d8fe6d0b7212afb76cff464031a63cba6f9ee209b40d2e49", + "lib/meshchatx/public/assets/DocsPage-hDlg1Y9s.css": "49d69be6aa44d8d062396fad2278d54c9d1da81d18d5a5b9d5c64d8329a3f04b", + "lib/meshchatx/public/assets/DocsPage-yrWtkKMx.css": "a0c64c62a6e8cf347bf8720ef650cec044115cc70782a64c4e0755409c48e050", + "lib/meshchatx/public/assets/DropDownMenu-BRb-5XM2.js": "0fdb2c12b97d1405c07be38da940815b2302f951418c1cd501a86a69f36e79e1", + "lib/meshchatx/public/assets/DropDownMenu-BSIRDIhA.js": "280ab9ee2aa11071e4835ce1b7064c3dd25649aef321b11f25cdcb42f8835a32", + "lib/meshchatx/public/assets/DropDownMenu-BTUTU14_.js": "dab91982ba3e31220cf86dba63202015c4fa6c91cafd28cd3764f1a2130d0374", + "lib/meshchatx/public/assets/DropDownMenu-BV2CC1ni.js": "00dd4f073a965582f227b43cd04c836791323d1e958922457d32698e5a711b73", + "lib/meshchatx/public/assets/DropDownMenu-BXmJSeiu.js": "9e22d613436eedb7c468b6386597c162928fb1cb3a0fcb04d6fd0fdac3a47377", + "lib/meshchatx/public/assets/DropDownMenu-BwNpCqI2.js": "3b4a947ba178592addd831612cf2566c4f8fb270ea7f23970ecf49050c2639b8", + "lib/meshchatx/public/assets/DropDownMenu-C3oTXFDX.js": "45bfdae74e0a7208bdfc1cbb8a0ef5b476fd38fa87c26034e8ce3f7425bc269c", + "lib/meshchatx/public/assets/DropDownMenu-C4IqVjVV.js": "5825129c0341007a531725f77f8d9c9f9ee0adc2e1be1dd817fafe6e03961c33", + "lib/meshchatx/public/assets/DropDownMenu-C9ic1-Kp.js": "c9e1b41300d8bd68e2362331821ca1681203f30a098faf76b16ec9b78eeaf332", + "lib/meshchatx/public/assets/DropDownMenu-CCJZnVsh.js": "e5f950f69e9153793b9aaaac57ff0c37ea2f3b4ca29754237e4d7030059325bc", + "lib/meshchatx/public/assets/DropDownMenu-COST-XEn.js": "474565edab04754aeaf1f2af6cd5d4e4aa8aba47f5aa624209d76b42b00f2081", + "lib/meshchatx/public/assets/DropDownMenu-Czu8e35G.js": "d458923a01f011a92bd04b5b7d8e3a6711b23821fb0ff30491d80a9497d2a466", + "lib/meshchatx/public/assets/DropDownMenu-DE52OS4K.js": "2d777670085486fa390e57c19ef9f818f8cc4f68766d95992201972142484fd0", + "lib/meshchatx/public/assets/DropDownMenu-DTkGrpcz.js": "c902ba83ac75299c8fae12753b8cafd1ab08943d3d51238db7beebe7463a26c0", + "lib/meshchatx/public/assets/DropDownMenu-DiaJpxda.js": "013d798b58e1ba50da4355ef1a70799005cd72e75a3a3b42440ff9fb59fc9e90", + "lib/meshchatx/public/assets/DropDownMenu-Dt4WcFld.js": "c84fb19e2f12e38aba20d8dff358cc5bf0f4b962dd0e25e3ffeff9fd31329b66", + "lib/meshchatx/public/assets/DropDownMenu-Dtgo4qDk.js": "77e94d3864978537c1dae82c8f92cd11f778bdda1f0ba9c0f7d45fb4c0ea53d7", + "lib/meshchatx/public/assets/DropDownMenu-Muyb_dgX.js": "a24c874efd47d0e5d6aa87ee98f0249f7b1bcc1ef714c3af8410062c4bde056f", + "lib/meshchatx/public/assets/DropDownMenu-OitbrUhj.js": "0aee8c48585c6e8a63cf1c74b6f938288e0bf103c0bee051d2f710d66ea9f261", + "lib/meshchatx/public/assets/DropDownMenu-ePZ8FLXc.js": "87cf5654c0d3a008b929a51b78fbe17c1870c3dac140b0ed753080ba8dfd7642", + "lib/meshchatx/public/assets/ForwarderPage-ASnZ1fk9.js": "7f236bfc466b3f1d7c7c708a71bb9e63a9f4df478f6c8f3ba8a4a5fb7b0978bb", + "lib/meshchatx/public/assets/ForwarderPage-B8iqJoSA.js": "ff127d7a026595be6f57034f2326749430eecf56a27b9c314b7f55a652742430", + "lib/meshchatx/public/assets/ForwarderPage-BMLJ8L8K.js": "74c1ee101d3458860179c6bea6764d658c6b865e99c8c3f980444fe507e95768", + "lib/meshchatx/public/assets/ForwarderPage-BRot3TI7.js": "9544d8f26f4479e386f429680d953494cc754cf13f3b71dc797f42cb8082aaf4", + "lib/meshchatx/public/assets/ForwarderPage-BYX9iOuW.js": "53f8838207db7e588cc6b8e8fbdd2acdf9474d8ea89af9703d78c0474b22351c", + "lib/meshchatx/public/assets/ForwarderPage-Bh0rnH3g.js": "76f3f0accff62acdbb77e4c8c5a1d26746d0b3e5efb8568a4a79868d1ee5e0e6", + "lib/meshchatx/public/assets/ForwarderPage-BsOm3cTt.js": "330665ee3b4e3c2fd5a52e55fb66ff655faaf94ac462638d877e834e9005c429", + "lib/meshchatx/public/assets/ForwarderPage-Bt0FsK9I.js": "a1c0e218aef1f0cf3743aeaf70c78d46e9ad0061d3947d62c2b1800842bc5922", + "lib/meshchatx/public/assets/ForwarderPage-CBP8CERR.js": "7ae9ec04800f07619bb1e929f09bc2e46d80bd4274073380213077a7055fcd2f", + "lib/meshchatx/public/assets/ForwarderPage-CHhMqC1Z.js": "ed8ce04c20195e56b4250e31fac01bd42190bc6262701f2700dbcc0b8b1afe1b", + "lib/meshchatx/public/assets/ForwarderPage-CQq9bhew.js": "b6bb0a2be97e33b41823464e42086dd33337a9b5a85b57d234e6d9f667f11170", + "lib/meshchatx/public/assets/ForwarderPage-CbhYpLxX.js": "adc51db70a275fe19deaee1aabc4bac2df85d5677915cec0d554bea5fc8cd759", + "lib/meshchatx/public/assets/ForwarderPage-CguUvBJJ.js": "a3aa0d7f2995ebfb0ee52537cff5b782ca032b8c9eb396327ecfb68ee111dd0c", + "lib/meshchatx/public/assets/ForwarderPage-CnvdX6oJ.js": "b96d61b7742e46407d42a2ba9e5f26442855bdc76f2b72414dc98c5d33d8adcf", + "lib/meshchatx/public/assets/ForwarderPage-CozsIxph.js": "1059df94b80eaee93b4b6da6ac381864feda3ebc4df685b08c2f1b7f1bd8f8a1", + "lib/meshchatx/public/assets/ForwarderPage-CvBwYLAT.js": "72180d2d5dcd43842eda609a9a10f476fbf3590e338f354a224324cfecd0a42c", + "lib/meshchatx/public/assets/ForwarderPage-D143y7qD.css": "c58183223cd2e32a62ab89be2dae42b891a01fc94832abcf87df2dbff8374b5a", + "lib/meshchatx/public/assets/ForwarderPage-DF74u1Mk.js": "7ef45302504af0d69e4606e8deeb76f17c4fcbc22234511102e2c5f9c46ef0c5", + "lib/meshchatx/public/assets/ForwarderPage-DShkAayA.js": "75753c0e310f07963b34d2dba65c80f44327e87dbbe880dd4ad58d9604bca561", + "lib/meshchatx/public/assets/ForwarderPage-Y7chGBck.js": "0c5efa10fc520c03ec748f80e59a10f8c8a6c8542f9032e8d495e1f3d627dab1", + "lib/meshchatx/public/assets/ForwarderPage-Z0455sJm.js": "abcd71db6571b1eb9b33c8d3c0795a562f0a960c5e1a4a9ed92f3d151706cf83", + "lib/meshchatx/public/assets/IdentitiesPage-2u5Olo1e.js": "dc8bb5d634d244eb401170bbcf5ca96d9aca886d542998fa0f7c6949a73a8b49", + "lib/meshchatx/public/assets/IdentitiesPage-3202l5tg.js": "6fd6e09cbae3288e2d421deaf960fb6bfa807685612297b5e49a886df85d5d04", + "lib/meshchatx/public/assets/IdentitiesPage-6a2u0dbv.css": "955a6ccae0fbefc482b24ada826c8a3f3005980a358ac9ecfaa461d078d50da5", + "lib/meshchatx/public/assets/IdentitiesPage-B6Ryy6cT.js": "eb46b7f3b6519dc9f6d47dfd5caf2c0432d3f71c1f204b02efe3f099160decd4", + "lib/meshchatx/public/assets/IdentitiesPage-B7rMKJwT.js": "a3321e4ada43934ea9c0a49e1f5769e34f88459debc782bc3cd51d7593beb114", + "lib/meshchatx/public/assets/IdentitiesPage-BBn2a3pF.js": "9869c8c075800e1a49f7a23b5c25d6cd5f89d3fa9892dbb3480db355b857dd45", + "lib/meshchatx/public/assets/IdentitiesPage-BD4TvGn4.js": "6b35f365d95b39e27cc7656dc7a073a9ce190d5a6e4cee843dee745a2845a860", + "lib/meshchatx/public/assets/IdentitiesPage-BT8t-ScD.js": "538e27d9b02a2bad13b56f926bb72c6500e8c6f56f6778948c70cc872049905a", + "lib/meshchatx/public/assets/IdentitiesPage-BYvn1GRy.js": "5d7cfbf16828a8be6509135f0261e719e43f09f366c6dd2877d37dcc149d6a4f", + "lib/meshchatx/public/assets/IdentitiesPage-BmUB8ygV.js": "f7198ab68c28ff6e7761632a2b0e547b919eba4790973aeceb78c46ab142140d", + "lib/meshchatx/public/assets/IdentitiesPage-ByIi0vE0.js": "8a12361618c8a15ed6647ff1bf92f5d9c8ca535fdf0bd47b22386e41eb6d4c61", + "lib/meshchatx/public/assets/IdentitiesPage-C1Sqy8sn.js": "1c98bd91885c79c991a68aa49700659c2c5083d2687b2795abd52fa7ea825b94", + "lib/meshchatx/public/assets/IdentitiesPage-CFFXsLLv.js": "7c53af04f56e8422e9c169f05602ff43ad8565da025a7be41c1684470883fc0c", + "lib/meshchatx/public/assets/IdentitiesPage-CGgBXv9v.js": "6dcbf64447789963e7e83e880162d52f417a2b3afd0a35efcb84c0e76037b85f", + "lib/meshchatx/public/assets/IdentitiesPage-CqU8xv8N.js": "13bdf898258cadf1b237dcaeef4b342ccb8b32d4d5ff6f655d3e0e3c8624029c", + "lib/meshchatx/public/assets/IdentitiesPage-CsDlV8Ey.js": "9ce634bdb2108792f1c2f1adeb06ecf80fb52f9c3c023d2bb83435abd75b871b", + "lib/meshchatx/public/assets/IdentitiesPage-Cz-Lldsg.js": "20b1e9061348169b31dcc7a2dda28495946b57c291f9af1ae8c171a433a4d0e7", + "lib/meshchatx/public/assets/IdentitiesPage-D2x-Np_g.js": "000fd4d14140f5e939a971eb85b2adc3cb33747fa85fa27490c002cb6cf3b75f", + "lib/meshchatx/public/assets/IdentitiesPage-Da7yzPOK.js": "77c314f43a647fdc64ebc84bc0572832023d3ead55c26135d8e73967cc1cec14", + "lib/meshchatx/public/assets/IdentitiesPage-DcQ25KvW.js": "9c73fb8c7906e36ce19da94be0658dfc4b6205d90e358ed1f85bde3c957ef8d6", + "lib/meshchatx/public/assets/IdentitiesPage-DgA739OZ.css": "64ff5fa2623696104b41f9d70010c4700307fc77d8851f0fd6a38e13df926f22", + "lib/meshchatx/public/assets/IdentitiesPage-atAVP6Od.js": "242bf7c16efb2d6e38c4ef24791a7de2ce1e362bf51129503fb843747508e264", + "lib/meshchatx/public/assets/InterfacesPage-4MWHd8dj.js": "14b9ad609180af4211beecc2dd6bdc03aa769c30ae0a8777481918fc02b4d100", + "lib/meshchatx/public/assets/InterfacesPage-B300_rSy.js": "0e6f6c305d1f3643361307304701a4a3162af9af3f8d9971e3321d6c54a3cf75", + "lib/meshchatx/public/assets/InterfacesPage-BAUi3br-.js": "ab9d664fdd1c9c0671074d8db6c3efd68e8fccf7885e84d75cf76df33a2655d2", + "lib/meshchatx/public/assets/InterfacesPage-BE69gBFL.js": "f54210b1b611f17cdcf1ad3530b6bfa05df9751518755b32e7cc0a8b86c02f48", + "lib/meshchatx/public/assets/InterfacesPage-BGTCDXHz.js": "0a2330c449c6abacdb5292d0b60d1248b020b81945d67178754b545d396e6ff3", + "lib/meshchatx/public/assets/InterfacesPage-BPjlbmnf.js": "11a0f91d1a7bf462cabf22ebed6201f908d00e95f03db799f4aa4b969a558f04", + "lib/meshchatx/public/assets/InterfacesPage-BW-HN4Ty.css": "c1bb16c277c10876ee2e1b3c170aee4129d69078ef64fa8a1cdc256213f79eb5", + "lib/meshchatx/public/assets/InterfacesPage-BYPjrZcT.js": "e3080bd373af904971e3f00c7d7263c186a0a57516cbb8f0a222d4213e378a35", + "lib/meshchatx/public/assets/InterfacesPage-BjDKDL9X.js": "1b3eae8280e260cdcfc9fc5b3fe9da188f9094efecb0bcc958d772174d497afa", + "lib/meshchatx/public/assets/InterfacesPage-CA8G16Gi.js": "c6af69449342a56592151ec3e768c829763989f2753dc5a3fabf3c5ba3f70862", + "lib/meshchatx/public/assets/InterfacesPage-CDwvRlY5.js": "0ad1d3f4550df6c0e8476e78f9461102b11d7d3f33069a2bcc13e48438cf02bc", + "lib/meshchatx/public/assets/InterfacesPage-CJb8W80l.js": "48c9ca5acba4399b805a3d9ce94d8c8f9b3b18b45e87b850a0ccd7a7d79ba0bf", + "lib/meshchatx/public/assets/InterfacesPage-CKI4gY94.js": "e8ee4a65e71c7607b5dff78f3220253ec83697519ed1b1147fcadf88573a0566", + "lib/meshchatx/public/assets/InterfacesPage-CYmlWTfK.js": "c22b12853a76517e5b1c5ae4eb45115283ad4b1d7373a1b28ec166a5d1a46db3", + "lib/meshchatx/public/assets/InterfacesPage-DdK02uqg.js": "b3435163b32495ce97529aa8551137f478c4b026bd40069c127d9c0ea6b8bbdc", + "lib/meshchatx/public/assets/InterfacesPage-DjKGl6a9.js": "bc94f216c405ddcc0b15cc9d76068d4e8f9224ddfc42bec581ac747c77e6ca22", + "lib/meshchatx/public/assets/InterfacesPage-DlDyC-7K.js": "06ba8d692481ebd666841757d09817434f732aa85c6177924be0d523b8961cec", + "lib/meshchatx/public/assets/InterfacesPage-DylPN8vf.js": "d65ea3603bc16a3a52ab34225f80d4610b22f9a27e2c6be0bd8ad6b7155361dc", + "lib/meshchatx/public/assets/InterfacesPage-cVtkeZQp.js": "7043132cde70233b1e79845396fbb00d7307f8d293ee095131b4be7c920fc487", + "lib/meshchatx/public/assets/InterfacesPage-fQMOZ4y9.js": "15368c12a9801a265237d3f3bf8b82033833c215b486b7ba45f566caeb9eaf9e", + "lib/meshchatx/public/assets/InterfacesPage-s-bbz0cT.js": "4d0d337c473046a6427528cb1c942d3f405e5d3f1a4be56260e7fdae4318a18d", + "lib/meshchatx/public/assets/MapPage-B0XYXEb_.js": "0b2865d8cb6abf6141b728d858e310c572c75972ae534b84c82cbd6964b1855b", + "lib/meshchatx/public/assets/MapPage-B6E4IMGb.js": "2ea7e8547d4bdd512fdf213c3e4e262e9fefe4268ac0830f4ae8e6e70059c23f", + "lib/meshchatx/public/assets/MapPage-BH_84XDd.js": "227048268485cc3e2539dfee1bd2034751da3b95bcbaf734068c0f0e324ca949", + "lib/meshchatx/public/assets/MapPage-BJq0AFv1.js": "1d379b48d6f5502f3ba4af4a56d29adb387171aa546008cd5b22c157fdfce088", + "lib/meshchatx/public/assets/MapPage-BLd4rfbi.css": "ba3e4e77c15d60098baf9097fa691e517a06d6caddf69ed1a03a5d8617a58c8d", + "lib/meshchatx/public/assets/MapPage-BPQ-qtZn.js": "f735ca520d41e7839dd398fd1e1e58e4ff3ce629f85e3ecfeb37ffa604cd7957", + "lib/meshchatx/public/assets/MapPage-BXb3DCaj.js": "4bdeb6c11209f0851ffa56320016c969909825a0fd928310702809c6c2ce53ec", + "lib/meshchatx/public/assets/MapPage-BZ5D-xHr.js": "8ddee5ebafcee1cc7e62cff2507951a69100d0116a6b0fbe5cd05e6be50a41d7", + "lib/meshchatx/public/assets/MapPage-BsSuGB7U.css": "363b6a79d3006ec1f9d7408f68d1e74a4913f7d4c2fba8b5f9365ae22ad63732", + "lib/meshchatx/public/assets/MapPage-BscXmA_E.js": "f92d188c4afc28dbd0a36a1fd0b9070bc64d90707fa0d2eefe0cc6f869428a7e", + "lib/meshchatx/public/assets/MapPage-BtS0PlIc.js": "420ce457cfbfe878bc492f55e23958d94213251e7930a21f549b48fc91f83c1e", + "lib/meshchatx/public/assets/MapPage-Bw5IYwuF.js": "02ed3ef11aac8d4166699a2892b8000d1dcaac7718052628607b3173c6046f16", + "lib/meshchatx/public/assets/MapPage-CMFf7rDs.css": "6ac1628fd5ddfdecaed27cde430856a39876ceff82b7ffe81e2e71c275d174c9", + "lib/meshchatx/public/assets/MapPage-CT51EQsq.js": "8a15a6349c46440ab2b0ef88827de3b87d187798e5b95322a5543293be1fea2d", + "lib/meshchatx/public/assets/MapPage-CXzhmmQE.js": "b9e431d440b3a93fc4f29404ee301c306a07fbe9883e430040ec0d4a94d1a565", + "lib/meshchatx/public/assets/MapPage-Coz2HXkW.js": "94722dd14c824edec7f4ad474afe4bf6a97e8716529feaa6efff071301f46f69", + "lib/meshchatx/public/assets/MapPage-CvnvsezB.js": "4cffa5d8b88e29a32e1282154bb99b5ee927430e7f703571a15a5ab6ec57f65e", + "lib/meshchatx/public/assets/MapPage-DNKwPg3D.js": "c7ae2ebbbaf1c63e4434aa1e038e7c8863177b067259ef2ee2c855c0e699a45b", + "lib/meshchatx/public/assets/MapPage-DrAjZhQB.js": "4fd9573942b463b55a0fe2b71d53e537714699d759a385418bfa6ee14b60f7e5", + "lib/meshchatx/public/assets/MapPage-Eo71eMvW.js": "ee05b8df42b77309edd1dc7b2e03dc0091d5cb62b7466d252c5c0e4a39e1b266", + "lib/meshchatx/public/assets/MapPage-MEfcwtYj.js": "bcceda5970102ee5e1402fef2fa4e4c7b95b7e9e713cdab1be1169d1c778cbc4", + "lib/meshchatx/public/assets/MapPage-V-HR1n5s.js": "2f1495c1b9965707392aa18b5f29d8e8e31679c1a5ea44acc711812ee2edb689", + "lib/meshchatx/public/assets/MapPage-bENFa5lt.js": "feb4e79151ae8f33ce45a587ec27f4b378faf84475bcaa0a1921859def670cbd", + "lib/meshchatx/public/assets/MessagesPage--b4Wkkmz.css": "f7570ba32576861d4451c7258b68b2b3a6c61f3d0d20b3f2d31e608e11700337", + "lib/meshchatx/public/assets/MessagesPage-B61ii4Fu.js": "496cd8b3c5d389764a3e7190adeb3535ab10406a6eae0614b4950d1c9c95a65b", + "lib/meshchatx/public/assets/MessagesPage-BF2U2VwR.css": "cf00bca52630bbfc7778444cc22718191f4e88716db7d88f0b93bb543ee2ca1f", + "lib/meshchatx/public/assets/MessagesPage-BVpsGmWC.js": "4095c4084da602868c0940bd85327d92178d6cfdfaa8e5bd4aaf3439782be3f1", + "lib/meshchatx/public/assets/MessagesPage-C88C1Xta.css": "148fd8eec5e7599cc138f4351df7a92046ce0d6798f725d5258869683d63dc5e", + "lib/meshchatx/public/assets/MessagesPage-CAEN_2MV.js": "1f59035de93b2f8655a58196fcc4f98477ea20b443d83dc2f099890c1580c7f2", + "lib/meshchatx/public/assets/MessagesPage-CNFsm2Fh.js": "2e24f98ef452bb49c086431a6fdda90691ef76fe4ad69bb7b1c1a1dd6f0bf7d4", + "lib/meshchatx/public/assets/MessagesPage-CQNx2QWQ.js": "6ed122ce71e914b539bb3dad4834ced5163e5b9711db6c7be9eb859bf9c09dc0", + "lib/meshchatx/public/assets/MessagesPage-CRDsD-DT.js": "bf646c9a91a7a1a832fd31ebc1c33ad38bd28c761489b3f14f9215cc343cb447", + "lib/meshchatx/public/assets/MessagesPage-CUmqFQTq.js": "a769783cea4371cc89dd49243dfd4bd9cc460f10c36f7366c93d82fd22f88843", + "lib/meshchatx/public/assets/MessagesPage-CxK5eF6i.js": "a9564996fefcbe6cfd7141f561e19bb6a92c47b29a3dd34ed9d61cae478f98b5", + "lib/meshchatx/public/assets/MessagesPage-D7cLbQ9T.js": "b5ccdb25280135468a730292797fe4ddd7f6e28d22dfc2997c9ec38d974832d8", + "lib/meshchatx/public/assets/MessagesPage-DL8Ws2UA.js": "7c0e33cfb316078145a42028ce94922d2626cc800484e5817a2c0d3f236524a0", + "lib/meshchatx/public/assets/MessagesPage-Dh3eLASI.css": "570321b3601218331b24078f06c7b40cb7e2e739afd8111bbffd4606aa0b4e04", + "lib/meshchatx/public/assets/MessagesPage-DhZT4s8A.js": "ced00fde1a1401059fe352e4a3bf411c9afd77b474da4ad89d21f724ccd31a71", + "lib/meshchatx/public/assets/MessagesPage-DpjT4gW_.js": "ab47d8b2e4908f30fa123b1e67276705e6d62289a3522df8e6fc5a76b336eaa3", + "lib/meshchatx/public/assets/MessagesPage-Dqh-J0Od.js": "ab22c9f13eb0d5876e01d68ec0f45204884cbf4ffd272ff87905004c48451e9c", + "lib/meshchatx/public/assets/MessagesPage-Du-48GAP.js": "79e0f9f3d430554ce42b234970f606f23dae34951f385c2a9356507a9928f156", + "lib/meshchatx/public/assets/MessagesPage-DvFnDOIP.css": "5787045f5c79d86259fde1fe5c8b3fb5e39ec73c7ae819817426309831919ab7", + "lib/meshchatx/public/assets/MessagesPage-Hu-e3LT8.js": "08b878369365367dfc2268d18d7301477e9b3dab4eb8dc0955ce84ce41d2c0e9", + "lib/meshchatx/public/assets/MessagesPage-NF3gl6RX.js": "36880373b540cb128d1711302d94071a8bbeb7a771bad705a23ede89cc3c9e50", + "lib/meshchatx/public/assets/MessagesPage-bEGvW-60.js": "cadc06961d54d4c25b54193fa2b458f4b085cb1f6b977d230590459b81f09c29", + "lib/meshchatx/public/assets/MessagesPage-jKakSR6S.js": "0ff478841e8836f0a25e7dc735d3a70993cbd236c599a0995bfc56b06ca12779", + "lib/meshchatx/public/assets/MessagesPage-oFRIoqSr.js": "0aba7d2d1c6c9ad26ebcf2790c099da6ca84e50b9a1b8e633411a70f645a9bed", + "lib/meshchatx/public/assets/MessagesPage-pwpd76Ze.js": "fa1a2b018ed960752a3e2d194a10e57df5b169a3904111c7f108ad95b315a5b2", + "lib/meshchatx/public/assets/MicronEditorPage--WEqT3jg.js": "bedba40e087a5784a1098d6b7aae29c0a5a8463909cc88f813f900a654b2af7b", + "lib/meshchatx/public/assets/MicronEditorPage-9474FCyd.js": "0f5b634bd5025c9aadefd61968cda8d7b2931114571f879b4a9045a8268a1896", + "lib/meshchatx/public/assets/MicronEditorPage-976EAUIE.js": "e4e3f9fcdfc251a0a120f223651c84192c565d3ca83ba53b304952f9c945b1f1", + "lib/meshchatx/public/assets/MicronEditorPage-BBK1A7cJ.js": "7c836c05853341cde4fecfd845e241f2e93627212a88592bf059eda1f4121698", + "lib/meshchatx/public/assets/MicronEditorPage-BCfmF0Wu.js": "0d999ec2b7df643461725ef07ecfacf3956ee00d6eaddf71038735f3601aeaef", + "lib/meshchatx/public/assets/MicronEditorPage-BDnlIDRb.js": "9fb055f8d44e813c000203d0f70e6479028619341a40a29bf97af001e0f8e70a", + "lib/meshchatx/public/assets/MicronEditorPage-BEdSGsGl.js": "73f89cc0c3ac2afc2a349b70b10328d3dc3f978a057806ef6facafb1e2ca6062", + "lib/meshchatx/public/assets/MicronEditorPage-BH3qvvuF.js": "d08db84c0e551de6932170d4e61f47eac2dee80cf8a426f6528ae3835f8cd0c1", + "lib/meshchatx/public/assets/MicronEditorPage-BPN_tKAj.js": "c9de06c8c5fa69545d090cf4735cc36789580cf653ea4c157ffe6717f71de649", + "lib/meshchatx/public/assets/MicronEditorPage-BljohsXU.js": "08e17145a05c7487d8d27df6aa4f44b0a51d4511c02a7cda84a39b2e4ea0b789", + "lib/meshchatx/public/assets/MicronEditorPage-Bp0OQGCk.js": "0f5f283ea6649fcb729e97b2098a9086b9bb653a895e742ebaa26decae65ecf6", + "lib/meshchatx/public/assets/MicronEditorPage-CdnSK4Uo.js": "a010f2c15924f8aef47907dbdf81217ae3a0fa6915cc9996f63d009b4a1d55bf", + "lib/meshchatx/public/assets/MicronEditorPage-Ct9TtKxc.js": "31cfd93234267adbb1c5f58995f767cbb449a3145a2b45925bfc3d1b78a58171", + "lib/meshchatx/public/assets/MicronEditorPage-DD85pikX.js": "1a35027d1104d65940feb305d34e32c86a43f8be6cab8a90217629efc7db4682", + "lib/meshchatx/public/assets/MicronEditorPage-DIIopU7C.css": "0be40b9c9ab8f83f00ec13cf9fc10e64919159ff7216c4372a51d56846894c09", + "lib/meshchatx/public/assets/MicronEditorPage-DRot3z-g.js": "867c7187a1e4f0dd77f5e891cc2187b977d0dd5d217dfcf3702bdf2157f42585", + "lib/meshchatx/public/assets/MicronEditorPage-DTspJuUx.js": "2e75831a4a7baedee6bdc62c8d23460a2da4d5d680a566f397a5bf843675bc7c", + "lib/meshchatx/public/assets/MicronEditorPage-Dky2E00O.js": "dd81f19e9c6b24f2281bcee3b6dda33271739d7e9dded6963c8d5134bbbc3266", + "lib/meshchatx/public/assets/MicronEditorPage-DwnzZIiG.js": "d04289bf13209dc38bf468b251574367539c343409863b3a5a7c0ad6a6c0035a", + "lib/meshchatx/public/assets/MicronEditorPage-WPZtDcMa.js": "cecab947536885253b085a126417bfff9005a2c860891900c389a225a30d2a3a", + "lib/meshchatx/public/assets/MicronEditorPage-r4qbXEV_.js": "bf6a408d57acb7bc2b7dd870268c5626ef7a612913c96d39a6ddc2559d7b00ac", + "lib/meshchatx/public/assets/NetworkVisualiserPage--VwAGE17.js": "912200e3d8e05aa651d0923f954f865a821e9725feaed761c0b4d3b7d671fb7e", + "lib/meshchatx/public/assets/NetworkVisualiserPage-6HbZhKrv.js": "995e639984fb1e476fb0cac9958961a13bad35b5c78bd93d9007150308bd44dd", + "lib/meshchatx/public/assets/NetworkVisualiserPage-8ldrPBdg.js": "3aa7dc00f60dfe7da6d8b89f19ac2782e5da1a50cad76f85a12626437629a08a", + "lib/meshchatx/public/assets/NetworkVisualiserPage-BDZxaSEp.js": "cce59294587c2a9ec808d3e1b987d77b4894ad1d560e126602f4a7ab1165831f", + "lib/meshchatx/public/assets/NetworkVisualiserPage-BloCX2-J.js": "7f740fb0be6d44d87007ee53deced22e59c97a362f8855cbc8920f24c81fce46", + "lib/meshchatx/public/assets/NetworkVisualiserPage-BtNojdhI.js": "a7d40d0e0f9ab1a9ea61fe29b71332dc84e9e57cde7e088ca2b31e5cc750e6e5", + "lib/meshchatx/public/assets/NetworkVisualiserPage-BvE1g6F7.js": "259df4f4b3142f5d0ea8118ed921028ea191e9995425edcb21f8bd8f4bcf7c6d", + "lib/meshchatx/public/assets/NetworkVisualiserPage-BvtorWAa.js": "87979f662e9e4b1cd7446bc7d52a7a2d4a9c2a21f0663fa44490ca400ee68298", + "lib/meshchatx/public/assets/NetworkVisualiserPage-C8FN5v1Q.js": "dd52a894134bc261d28daecc1e81bf63dfd282fa52aa91c6cc900c57c9802915", + "lib/meshchatx/public/assets/NetworkVisualiserPage-CBTVsRc-.js": "feb5e5b7ec33c934a6ca1f24e089e7c449a061597a749762dfefef35e06397e7", + "lib/meshchatx/public/assets/NetworkVisualiserPage-CN0_L7zc.js": "6aa642211adfc6541a0fda2000e69f3a0fcbf3d3d24d19b5387fe86588841185", + "lib/meshchatx/public/assets/NetworkVisualiserPage-Cr4wxUcz.js": "ff9258c107ca71d8e730affff883ad765b35584f532770dd467790f163dae33d", + "lib/meshchatx/public/assets/NetworkVisualiserPage-Dn4VoH5z.css": "7d0a1e2356c59fba617e055c685a2eb25fbbb7b720cf631afc7a11b1bba34eea", + "lib/meshchatx/public/assets/NetworkVisualiserPage-DscY03Q-.js": "e6c70fef298e1ebd676a7f834ba1072fe436fea1a4b5e0c276fb735dc7e8697e", + "lib/meshchatx/public/assets/NetworkVisualiserPage-DtS-D5Hu.js": "b4e64c4d47b3dd0afa2c6a7bcf67bc8a0587f0c95c05922f645034aa9bb05eb9", + "lib/meshchatx/public/assets/NetworkVisualiserPage-LIs4u1pt.js": "7d7e553f04575225659d6ceaa018ac999808d9f6ea7e60abd5c456533c37db2a", + "lib/meshchatx/public/assets/NetworkVisualiserPage-Z9_V0oWs.js": "fd14a74bc258d981747923b12c77eb2d34f7063e87c9d2c0979f3f2d78750f56", + "lib/meshchatx/public/assets/NetworkVisualiserPage-ZF3d6qt6.js": "3417e5e80b6eaad815bbaede43bd7aa674b7f7c94a698c5145d9bc185e2ddd37", + "lib/meshchatx/public/assets/NetworkVisualiserPage-bODOn8Sk.js": "410d83434602664b68c62e5795509d9c814b2dc2e1a8d6fc68bd3380adcd8c4b", + "lib/meshchatx/public/assets/NetworkVisualiserPage-m92CsmaM.js": "2718c0c31bcb5551ea1be5901e3952b2a26d0ec90eac4a3ea15acdf5952b6995", + "lib/meshchatx/public/assets/NetworkVisualiserPage-veyxCtSv.js": "ac2fb50a11f9ffd94467f29c83d93e2cb7e866686324aeefecba60f5497123d0", + "lib/meshchatx/public/assets/NomadNetworkPage--nZVf6wV.js": "6da1a86a34cf1e7b6c0bb0937d126ca48a7723b19d13bbfbfd8869983cbbc22d", + "lib/meshchatx/public/assets/NomadNetworkPage-BEqPSuu8.js": "bfea82c51f2e9ca1c78e8825f9652e7d495d7feec707be97cf9377165b5e8f4d", + "lib/meshchatx/public/assets/NomadNetworkPage-BYwb_6pU.js": "695d3cc1b51e9b0b2c29fd09d7a900d8513b8030dd2f3b84d20745fb377fd8a8", + "lib/meshchatx/public/assets/NomadNetworkPage-BfZmUe0y.js": "d6aa4fc064f83f595929497cde4ae7fddb3f1bf7f222f5075c36dbb718bb3654", + "lib/meshchatx/public/assets/NomadNetworkPage-Bo8owhTU.css": "1f5299f7bac61900cbfaeaaabfd6256df60aa7be98986301a6e3e52b84ba6998", + "lib/meshchatx/public/assets/NomadNetworkPage-CUUy1oU2.js": "e280cc7e6ad16735c69734cca855902a6d27619e55fd029cfc7995a9f638a88b", + "lib/meshchatx/public/assets/NomadNetworkPage-CWAnzZ1T.js": "4a8a368800a8b4b392a7bbc96fbbe25fb8169c0376dd6da637ad02c4278bb23d", + "lib/meshchatx/public/assets/NomadNetworkPage-CYSpqOgP.js": "62a3398b493b3ced17ed1e5c43c3a0f461cd6aedd6472ce62c49717e59c10887", + "lib/meshchatx/public/assets/NomadNetworkPage-CamExDiU.js": "11045fbc6450f3964b31cf3672717b97ec758903b76898d14606a5e97cd5aa0c", + "lib/meshchatx/public/assets/NomadNetworkPage-CodVPnoU.js": "22cced8c83fd77a6fb07bdc64d6683866e07b10e7f0c8af441a5e2f35245e10d", + "lib/meshchatx/public/assets/NomadNetworkPage-DFZNgTOH.js": "9c33dbe7d486dbc69b5f648b546a7adc20a6b4bb891dd3d005329475cae02dc3", + "lib/meshchatx/public/assets/NomadNetworkPage-DMPAhzup.js": "bac6cbee021c9a6abe918d136320d47c2b7045cbd74f09cb4d05103dab3d8129", + "lib/meshchatx/public/assets/NomadNetworkPage-DVhS4FAr.js": "e4c02cb86ef491ed688544cc1c5ff8e555d4be7c318000edb51441d46df46abb", + "lib/meshchatx/public/assets/NomadNetworkPage-DcVc1rHg.js": "5fdeba15fdbf851e105db4ccea70cee8ba82691eb31015c0a00a763a3f9a19e6", + "lib/meshchatx/public/assets/NomadNetworkPage-DnB6nLtl.js": "186869fa630e44007212160f4f39af1a4e7f865ca51ea1f75a2eb943d2dd2143", + "lib/meshchatx/public/assets/NomadNetworkPage-DsSzKmA1.js": "efc383c8fb6ed7690388c4ba242790e94461a9cb8c4ca4a9c64478338fd65044", + "lib/meshchatx/public/assets/NomadNetworkPage-Lmz1epzk.js": "6751a0618c9e70f96555627c2d99a1de182a5f64a3d1a8cfa5bb48a23e41118c", + "lib/meshchatx/public/assets/NomadNetworkPage-MSgWwiBK.js": "f27cd7706a29f5ce8a8f24bcaa95b7be2d250ecb09dbda1dd8ed97ac07f3e73f", + "lib/meshchatx/public/assets/NomadNetworkPage-QTjm-B6C.js": "cdbf955e3a5742a5891b0fcb32ca900eff8fdcfdc8cdcc10628dc45a459890c8", + "lib/meshchatx/public/assets/NomadNetworkPage-VPo-EVAj.js": "f2d82299408062ef154613716b3bb3c48a09d2d2918e6ba2ea1c72e2c8c31086", + "lib/meshchatx/public/assets/NomadNetworkPage-tfP4kQ4u.js": "648ebcff2daa09aa170c266c689d2c9d172441ae89ba558b93d51b4c3812089f", + "lib/meshchatx/public/assets/PaperMessagePage-BNCpEUaL.js": "37e7da26ed299d23062c931c33b995451bfc28809bbdbb8461da05e628944a08", + "lib/meshchatx/public/assets/PaperMessagePage-BaF3Ut5B.js": "b28563c579d55ad363e115f4786ae9a24fd572fabe076a71af790ca5709d37aa", + "lib/meshchatx/public/assets/PaperMessagePage-BrAvwrKv.js": "cc9b8c171ed0a44a11e45c99d980a408a923afe7836388da60eec03b8125fa44", + "lib/meshchatx/public/assets/PaperMessagePage-C9k9SS0q.js": "6fb204be6abe32835eb3b590b6112f172c527c47776cdaad60c03e08e5c1e562", + "lib/meshchatx/public/assets/PaperMessagePage-CC8g-I04.js": "d8d4dddb5565ef0ccf868c5dc4fe64d78431a72203a0ff6fa43fa39a8cb0b036", + "lib/meshchatx/public/assets/PaperMessagePage-CE9vlmu4.js": "703ed77290fd3310cba4f3edfc8a11ec6600823ee0c358e38122ea6bf7c055c0", + "lib/meshchatx/public/assets/PaperMessagePage-CPzgyW2-.js": "059d204d8231a79330b020d3d16d1c56ef8592a230a0e5daad17ba22ee4f4d88", + "lib/meshchatx/public/assets/PaperMessagePage-CR1V2V1Q.js": "d696929efe4bbf5f429bcd81496c976205c7c3f825ece4a0b8cf989a16de4454", + "lib/meshchatx/public/assets/PaperMessagePage-CR2WQUUT.js": "cbea36eed1fae62c181af7125fedfebcdabcaf67d4a1eae2f4b399e6ff233198", + "lib/meshchatx/public/assets/PaperMessagePage-CwTlYRnA.js": "6f1a74dd40d2c2e554dd6ed398b63049780afb905d71259613de8732b44e6d32", + "lib/meshchatx/public/assets/PaperMessagePage-CxO-Nb-0.js": "1cbdc4089c95abd1bb1262f7c5b3479968ca1d515e87bae541cd2aa8d90ab6fc", + "lib/meshchatx/public/assets/PaperMessagePage-D3Cx3Pe6.js": "8d032d4ee0f767899b1976e017dace4dcfc9c6141ed70d06b3a0d822dab205f3", + "lib/meshchatx/public/assets/PaperMessagePage-DC0KnRM0.js": "da6c5b1cb130119fdbc72e1276256f5388d97c48ef3351be403018b2801f5468", + "lib/meshchatx/public/assets/PaperMessagePage-DGV26OvG.js": "6ff07c8dc9a5f67a864a9582b372fdddc29aac387143fa3a204cd5f8af77c7b9", + "lib/meshchatx/public/assets/PaperMessagePage-DUbO946r.js": "2e7ef1df4126acfcde0a3aa55e90ae840a170054e9c481d632df1020a1078fc4", + "lib/meshchatx/public/assets/PaperMessagePage-DWEk-OOr.js": "e1732d589989226b7fe67ad22cf6b538f5e582e9a7a163c21fd014f86b7675a1", + "lib/meshchatx/public/assets/PaperMessagePage-DsjRDU4I.js": "010eccb77a7163b29ef8453231c2c76c7b2dd0bb48a637872fcef95c98033631", + "lib/meshchatx/public/assets/PaperMessagePage-DsypBSmg.js": "30267a6d3b2aebfdb60cf840665c9189015b3d108478ec1a5200bf224cfe1478", + "lib/meshchatx/public/assets/PaperMessagePage-iD5rlYTd.js": "d23ae2b554b231ecdc7ee34e0cfc23a92a2837ed2387cb33ba285dc2c0d10a51", + "lib/meshchatx/public/assets/PaperMessagePage-mJGpcVHl.css": "bf27a06adc2d396d3bc30145ad14051877a21ada4435ca8115283bba69e7db60", + "lib/meshchatx/public/assets/PaperMessagePage-wWLADHMp.js": "44cb324770e919fbc456a9ca3684eb6cb9fcabda4cd654a60182b18281af63d2", + "lib/meshchatx/public/assets/PingPage-605oZnat.js": "cae3acbfeb55381902726b96bdf364dba3b89aa7267facb73d0449c12376cca7", + "lib/meshchatx/public/assets/PingPage-8DCvEeij.js": "e897d5276b2b301b090b43575e583d511e7fcc00386b6aefa27328919d0b7451", + "lib/meshchatx/public/assets/PingPage-B1nA7XCv.js": "0a467a82e0a785ea53151dd6b898461c5408b8072935b9f0074aa367f12e5d8f", + "lib/meshchatx/public/assets/PingPage-BNNtwpel.js": "4ac6d361cb8abb2ba5556f0f00b9717331db905846c46a4b521544daec515e99", + "lib/meshchatx/public/assets/PingPage-Be1jI5Ws.js": "c70fb31837f876b55d53dad392c039413150e704d7a701ba7aeaedbb0c5166bb", + "lib/meshchatx/public/assets/PingPage-C7D9ck95.js": "522a2dfb346b45773495bd8c672bae359d6e2486e8fb03170e79718486d65951", + "lib/meshchatx/public/assets/PingPage-CA_r1-ZQ.js": "b5044ffd384aa56366e0bc67880d0961eedc686a75bef0ae7ec8c727a61faf93", + "lib/meshchatx/public/assets/PingPage-CBeqTAu8.js": "d9d5e70f41909e28a730022a599af6f00c8ffc077785909458ba9e94323a03f7", + "lib/meshchatx/public/assets/PingPage-CYN3BZxh.js": "ec69a104a389bf8b99e05deada955bb8b768d52c8e1b641f26053c281e7cddcb", + "lib/meshchatx/public/assets/PingPage-CpQX1R42.js": "00719d5d9932cc8b56d071eb5263098dee39c44e07ae73e88a510691507367d7", + "lib/meshchatx/public/assets/PingPage-CpVPR4vQ.js": "c3343fc90293c7884b2fc97248c2df7730d3424542ed995733480f1eb1a3b6aa", + "lib/meshchatx/public/assets/PingPage-CvqXFI9h.js": "9dff7fca0683fb0c11a962d050536c9e367577e97833bd75901ef5b57fca746d", + "lib/meshchatx/public/assets/PingPage-DFZmoCHH.js": "9438d54dee0bac8361b2addcc66c749ba5f9be81da06015663f3bf4ebe11580e", + "lib/meshchatx/public/assets/PingPage-DP51KWFg.js": "a7102d863bb393007c655cd34e7d4f3131367d1303ec2bcb3202ab355bf7fb35", + "lib/meshchatx/public/assets/PingPage-Dxnwuj7k.js": "2e4e5577fc06745d21f293035a41fb71e37ebbbf30cb11c93738af37e9d48434", + "lib/meshchatx/public/assets/PingPage-GbQtaXL7.js": "3c18baf3a849db5d8293d54cee7159fe2a8d853cf4865827e90aa067a6ee730e", + "lib/meshchatx/public/assets/PingPage-U4P81pR7.js": "652a19ef53a979842e38ee1910b196cb09a6655e16ba1b653b792bd798c39674", + "lib/meshchatx/public/assets/PingPage-jV34_kWA.js": "3f1971ea08110ecbe8aafd5d2391cbd774315048c13381626fc12ab6a901946d", + "lib/meshchatx/public/assets/PingPage-q8ykEogI.js": "2b8044568df6f10ac934b45944e17479b16b74fefa58ea1ea96c64e118519462", + "lib/meshchatx/public/assets/PingPage-wGol-jpK.js": "80a2d4b926ad5ce5810dc9c23de5ce547cef8b33e2fe688003170fa8d9446857", + "lib/meshchatx/public/assets/ProfileIconPage-BD8um3u5.js": "d8539b579d44bf5241e0bd3a0de2e112d4ec22c76139222ff67cdaa626f00873", + "lib/meshchatx/public/assets/ProfileIconPage-BODy1ADP.js": "98e3006064df0e54dbc8b82e94ad7f2afc29ac3529114d6930358719cc243980", + "lib/meshchatx/public/assets/ProfileIconPage-BWQJwqVh.js": "e9733ff0cfbdd95b46ff8bec57a20603a2b2a4cab080e0eb13b988c9121d8bce", + "lib/meshchatx/public/assets/ProfileIconPage-BkGnbcAy.js": "26d75d8beae39d0efbff4f4274eb592d0cd8708f6940e4eac2f54d308694dda4", + "lib/meshchatx/public/assets/ProfileIconPage-BtfXSHS1.js": "e42d424139f7177ea67e9cdc6c6d17022e8366a1a2ea919924faee97a2a13a22", + "lib/meshchatx/public/assets/ProfileIconPage-BuLRxDLh.js": "4ab27a738d6c86b6570a92efae3aa95b62d05ff19c63db04a12ddee55136ae67", + "lib/meshchatx/public/assets/ProfileIconPage-BwLzG_fH.js": "93d54bfa9a1bd718fa4cac24b54944ad678158ffaf57a941f773297e1dd67dc0", + "lib/meshchatx/public/assets/ProfileIconPage-CE-MQVgM.js": "418e440cec8d731f57f638ca4a4c7e104dbe1a655bec6e87569f67f81cfc3a65", + "lib/meshchatx/public/assets/ProfileIconPage-CGj4CTqa.js": "e4294feca7cb8edb9c6ce2ecf776538efe62ab8ada4145c382637251e38892e0", + "lib/meshchatx/public/assets/ProfileIconPage-ClZ6J3JQ.js": "4b5dd8253e715db5650144ac9097a9a45afadb2cc06a538a39766dd3ce6beb83", + "lib/meshchatx/public/assets/ProfileIconPage-CpEQ7Yyg.js": "9dceb67d757e79c807d5f1dbf1849f478b9eadee21eaea9dfa92be2e8c123dd1", + "lib/meshchatx/public/assets/ProfileIconPage-CzfhEjEM.js": "ed580980d6d4d365d98f467e56a44e884e437d1ab006ddf38dfcaa32678c92cb", + "lib/meshchatx/public/assets/ProfileIconPage-D-tHvyk5.js": "353890704a641df34db34882ca061db9a76cfc2ed69b80f2a31207798c5fdba0", + "lib/meshchatx/public/assets/ProfileIconPage-DDfbIMis.js": "c3a8d462fe4fc6f1756c5257baa8252ebf5b824366749da14f14e3354212e9a6", + "lib/meshchatx/public/assets/ProfileIconPage-DcqQYExK.js": "005bed1af7252eb57c1bdcd6afd591fba77f126a42197c6f201be00832433b82", + "lib/meshchatx/public/assets/ProfileIconPage-Dq31ODIj.js": "cb0928b38f7d94391c96d8110c966ab49345aa882cb133aba6bcf849dee9d427", + "lib/meshchatx/public/assets/ProfileIconPage-DtLNk3ld.js": "53706e3c730a11cc0157da441fb35890f050c28092f4e787a750ac4075c0b8e0", + "lib/meshchatx/public/assets/ProfileIconPage-Nafv9Djw.js": "6ffa92b0a3549b66ace1ed267184daccf439e2c827335b869b39620bc88881aa", + "lib/meshchatx/public/assets/ProfileIconPage-e3G5YCSe.js": "9bf5f5ffdf1fa88cac8b054eef6907a700a70dfd0fe3495559d0461e82c34f2b", + "lib/meshchatx/public/assets/ProfileIconPage-lXDI5s8D.js": "f68d3d8adf327846a4d1644d967a2389e37d4f7aaba49f10aa5e5ad1288ef938", + "lib/meshchatx/public/assets/PropagationNodesPage-BcSeS9Oh.js": "6c2cbe7ae57620f030b04cb755054d791419e6b11b1282473d836949f6b4ed29", + "lib/meshchatx/public/assets/PropagationNodesPage-BpDBsaK9.js": "1c3bcfe5b31344ca6769192c9f8ba5cb275d2a36337a19af39a45f1646d687d2", + "lib/meshchatx/public/assets/PropagationNodesPage-Bs5QHHR4.js": "fb7dbf624aa0c5808dc32194044a30aebbe55a5773410b164b34819d0b523ed6", + "lib/meshchatx/public/assets/PropagationNodesPage-C29jypnG.js": "1a402cfe6ac25cfcc28d3bd7604ce7af5650f42dacabc9043a04f146f0fdf3fb", + "lib/meshchatx/public/assets/PropagationNodesPage-CFB490RL.js": "b14819a49885b54e9a290581521362552289221c38f1971fcbbb1c1cc0dbe1d2", + "lib/meshchatx/public/assets/PropagationNodesPage-CfkUQJzn.js": "46f2690d94afce7b9a26898ed22e736a82beb924f9d89d83555f0ad4adbbfb62", + "lib/meshchatx/public/assets/PropagationNodesPage-CrySA9JB.js": "950545402f7f96e64670228dee6756e2810cbf063d739eedc2a946a3030beaab", + "lib/meshchatx/public/assets/PropagationNodesPage-D-VHRWQh.js": "b822e5b3e57e790d21c2f50bd0d60f2ecf13c0d5a08a88da6b6103bf7250c4df", + "lib/meshchatx/public/assets/PropagationNodesPage-D1EJyBZo.js": "f212cd93629abb4c1f2dcb121ba22473c792969d3072d039a9f79511efe457d8", + "lib/meshchatx/public/assets/PropagationNodesPage-D41vW7jg.js": "c301a492a8ce193a55593b9a593d6babb4e1185909055e1057e83e555bb0ab4e", + "lib/meshchatx/public/assets/PropagationNodesPage-DgRJ3NNC.js": "18d710653e439d2be54e883a24284e616edd48279b8162b6d4d5a04a47c97482", + "lib/meshchatx/public/assets/PropagationNodesPage-DjvSg0ye.js": "df2b4f23c70912ba06a0d6dd969a7e8c6408c9d1e9e263dc521b6572b863f7b3", + "lib/meshchatx/public/assets/PropagationNodesPage-DmXJ1PHO.js": "aa7273a38e9d64ef28bd0401e6e142147dbf8074d20ad288846855bd087b10c0", + "lib/meshchatx/public/assets/PropagationNodesPage-Dzh9c-1R.js": "044407b1accfc35c00a98096cb390ff01c4f3f6e705e47e9623113c0d2480ff7", + "lib/meshchatx/public/assets/PropagationNodesPage-PivWmPbY.js": "29b8070e2f1c4c74bd5cb9ba908a8fce6b220d98f28c7de161f0ac140b84fda1", + "lib/meshchatx/public/assets/PropagationNodesPage-QdoqH-DF.js": "b2841eab2f4ba9015647ad52320fb9db007fbb21bf870f5b00adfc6d852e5598", + "lib/meshchatx/public/assets/PropagationNodesPage-aJ6q5dH_.js": "3a5ad9e493aeb28148fec23ecbb96126dc38ecb3a3491c1d60a24388342bddae", + "lib/meshchatx/public/assets/PropagationNodesPage-dBBjMlwj.js": "d5ddd0e826409f2c500918bf14fc43483a606488c48e3bf12aa3ef7f7c3dc96e", + "lib/meshchatx/public/assets/PropagationNodesPage-uqS_uhdD.js": "c7562fc2d49282b1ac3f65979921775cea32851ff4d208eaf73b0d438b144dc9", + "lib/meshchatx/public/assets/PropagationNodesPage-wZWgAX0h.js": "a7d6ec9e4562e2e09226bf34552164433a715133494d00d03d5a81bd008c250c", + "lib/meshchatx/public/assets/RNCPPage-B4w8obKN.js": "d84eb4b02e52c7efbd4ec9fef1e438a4d04e320fe00c408e25c8f7d582a6a7a9", + "lib/meshchatx/public/assets/RNCPPage-BNHm9MT4.js": "aa6d05aa788088669cb42a184572a1e657e2fd3752c46cc0fd9d56d41dfab2a1", + "lib/meshchatx/public/assets/RNCPPage-BZmPFdcq.js": "e40f5ceeb86d56eec72029be77a0303ac69ef70ad22bda2721516efe5458860f", + "lib/meshchatx/public/assets/RNCPPage-BtJWBJUf.js": "320592191ec00d0aa225a6f055750272e22c0711cfe013476ed5bf2849adec54", + "lib/meshchatx/public/assets/RNCPPage-C51Rhf4B.js": "ce3a3d8115d808737e25d75b853f1c99a294b239a37efa1697f8af3027617bf1", + "lib/meshchatx/public/assets/RNCPPage-CLVdPZCs.js": "ea9408eb8b1f709bff1001288975f1b939c495f17bcf72488497fc77948434db", + "lib/meshchatx/public/assets/RNCPPage-CWuifO8N.js": "5ce0e2cfdb777e61ce9f2741952597576c8a6ba5373dde50e4c09aa3ad146169", + "lib/meshchatx/public/assets/RNCPPage-Cd-_YgyM.js": "945b90df6d16e164ff5a411df9718ca7864276d9da5f74f0f60a57667919be5c", + "lib/meshchatx/public/assets/RNCPPage-CrlLp6sn.js": "14f68628e9aa2a669cede34bebf7b5ca41141d5fffd44d9af298695f6783c5a3", + "lib/meshchatx/public/assets/RNCPPage-DI7MX88L.js": "6638e5b1847e9c4e6ef6e1ceec14aed7576da2a68ae4e8bc5720c14e21bf99ad", + "lib/meshchatx/public/assets/RNCPPage-DLCuqLGc.js": "394b53b1d265847926b5ae568991780e1ef2b90cd69cd7afd8ea5caf5af6b55e", + "lib/meshchatx/public/assets/RNCPPage-DLRqUp5O.js": "284c7222030f948aafc5e3f28a0713acf124ce9433bebeef9086c92cfce1e84d", + "lib/meshchatx/public/assets/RNCPPage-DScEWctG.js": "4eda3b5fe8e143cfae990e276e1000aff19e03fc6af2641e23767381c59386f6", + "lib/meshchatx/public/assets/RNCPPage-DjZnwIhz.js": "833cd918a561932fb6ab58094e2420ccba8afacbef727b947ab10fc0ef0eef9d", + "lib/meshchatx/public/assets/RNCPPage-DkRYbHe0.js": "8dc9862ad7f7a77ac7e523e559b517298c734dd061065b5ad225699b7e28b917", + "lib/meshchatx/public/assets/RNCPPage-DmJzoask.js": "6e8fbdb27c643ba75c2e2d0a35c3061ad5faede25dba0cb430c2ec0b48c93ba2", + "lib/meshchatx/public/assets/RNCPPage-IAjOvgS3.js": "34475e562c053b1aeeb51ddc7bc17e187b0bac4f8e244f1de716a4de6d27f992", + "lib/meshchatx/public/assets/RNCPPage-Vazu-YB1.js": "90628311410d963b3db4c3887d692e7b281c1f15340426853a9b09698f468132", + "lib/meshchatx/public/assets/RNCPPage-c0FDPWtf.js": "e19b0d7804856c5257b53f1e6298651e928b0ad8790600c1b602c5a3530174d4", + "lib/meshchatx/public/assets/RNCPPage-n6SAd7z8.js": "11a6ddb12363253ac02cde23b12c6c350899ca1a11a457949c5a3d713420d0d0", + "lib/meshchatx/public/assets/RNProbePage-B4l8yxQP.js": "d608a7f434672ab7dd29793610b58085a9ef0117757175e70f3d9ee95d02d0f6", + "lib/meshchatx/public/assets/RNProbePage-BIk8vXT2.js": "fcf82ca4dc1afa8f3b418a030bf3d6988fce9c515eddd789536fff8b1f750eaf", + "lib/meshchatx/public/assets/RNProbePage-BKIWaXrV.js": "5e96a825ac3b3432874384ae49c0d7d5511ead8ff92d9754da0e2ee04b225834", + "lib/meshchatx/public/assets/RNProbePage-BPocFDc_.js": "7bb8c8ce6c168b539c11fab16583d4efd98c4584fb212091806789d56cd3bb8a", + "lib/meshchatx/public/assets/RNProbePage-BhmRwqjI.js": "339030561bbe2ff01e8e965e53e4b527251d9cbcc1722f35714180345d3dd0bc", + "lib/meshchatx/public/assets/RNProbePage-BidNyS1i.js": "a2e0f2ea394cf1a5030caebd4590e936a97f5aec0e7d5ca109c850f6a50f2e39", + "lib/meshchatx/public/assets/RNProbePage-BjKRvght.js": "f100b868ad40c2a64a29aa99fcb0c5abaabf0ac551dd538ed1abe87d59b5d02d", + "lib/meshchatx/public/assets/RNProbePage-BvM_mqle.js": "34cc1ab6077855ddff0d69b7f8bac4eb574ff67e7a590f0e4935c0ae416dfe19", + "lib/meshchatx/public/assets/RNProbePage-BzdcUd_3.js": "dd27703b77dd21ddac38bde4ca6edf4ab53346ce1b819e425fefe52f766086a5", + "lib/meshchatx/public/assets/RNProbePage-C4UerEa8.js": "a11dee743d699b68332088931b4059028e71e0f134ad830b121bc846c579511d", + "lib/meshchatx/public/assets/RNProbePage-CKfF2j6U.js": "a1ac77ecb045cef88a123c49a2e9d51df562a674d02ad58b11d184a6480fe457", + "lib/meshchatx/public/assets/RNProbePage-D3ABqDbl.js": "881a386c7f66bbd0a52bcd1c87318341cc3d9a2bfa8005b46f535cae684f8899", + "lib/meshchatx/public/assets/RNProbePage-DBadiIiD.js": "f304272b3e6dd6bc1510f7132f3b29b437ce5dd6c4ec844f41dba80007a66c6e", + "lib/meshchatx/public/assets/RNProbePage-DaNPh4kV.js": "5d77863939deaceeb5672d82fed43698166bcd3b2dea06e09da6ed89d6b537d5", + "lib/meshchatx/public/assets/RNProbePage-DdT2pR73.js": "703d83f7334f2d973c3a1107463de732e626aa7541d97d70580cfbf2606fb5bf", + "lib/meshchatx/public/assets/RNProbePage-DpJgKra4.js": "5667f806e57c3eb3bdcb3d7ccf9c9d53200968c6438728b14628be191d1251a3", + "lib/meshchatx/public/assets/RNProbePage-JTwuc4jR.js": "6eae7a3bc772c335e647bb886fa88e091c48c38e396a98d0a7a1de8167e4a52c", + "lib/meshchatx/public/assets/RNProbePage-f3FJuUps.js": "24f588621a7ba733067e0cab9f87031b8de144e3d9f707c21eb7002dadaba4e7", + "lib/meshchatx/public/assets/RNProbePage-hYBvGAJW.js": "c77416dadba9c37c0fa96b07099fc649693d0fdb29439e0a4c1672e139b0277d", + "lib/meshchatx/public/assets/RNProbePage-pZHdmx6n.js": "de5b8e59636c2bb4e16c968c78c85354b4ad2444a32b4ea9ec52f11757e1d94e", + "lib/meshchatx/public/assets/RNStatusPage-BEByD0uG.js": "8b9b4eab8e483c3ff9ee5f0268b5f61a847ee82c616284b5d6e8c44a0c2adfe0", + "lib/meshchatx/public/assets/RNStatusPage-BLUgxsr9.js": "181956b34a29f769f3e3c4a593f3ad83c1767a1a024773d51279d4d5f3205f0c", + "lib/meshchatx/public/assets/RNStatusPage-BMKr50iV.js": "e6493c806b2066cc915c2b3dc077b398f2393d2aaeeb3f3e02647a65e2905b3e", + "lib/meshchatx/public/assets/RNStatusPage-BceiBbcN.js": "3b12a91d98cb48e82f02e7544aef46073cbee13d8b2ff081c41c7ac64648b6de", + "lib/meshchatx/public/assets/RNStatusPage-BdHwTC35.js": "72a4808601d35076078be711d988459d3202d560d1149844b6548d2242f3da35", + "lib/meshchatx/public/assets/RNStatusPage-BdytMz1p.js": "7c064e4a2ddba253abe1b83d34783392625e6232ffa077eeb1b656c1be5bd59c", + "lib/meshchatx/public/assets/RNStatusPage-BrGcmhTG.js": "d2414c00cfed6d4c4280d95792765b1d75d7d09f84392c3dea3fea78ab5bbede", + "lib/meshchatx/public/assets/RNStatusPage-Bt4n9T2V.js": "0e65f9f5ed8f93b68b76d36831cf9f1e0d847c9e31272fecaa76da1578fd29a7", + "lib/meshchatx/public/assets/RNStatusPage-Bxsv2zmp.js": "838a611d479b56733ad854c2246db5987d2a0d0924bfdce41602b4af9cd0ed9f", + "lib/meshchatx/public/assets/RNStatusPage-BzMMLgMU.js": "09d3397a3a86ca943a4391ce9c536789eac066ed17db29497d23e7b2cbc0c62d", + "lib/meshchatx/public/assets/RNStatusPage-C8bB1KWP.js": "a2d07ffdbab07d003ca7ae310012cd2c2a463e4aa4ac45b3647c77e647403096", + "lib/meshchatx/public/assets/RNStatusPage-CW332LiS.js": "b79932f83bafd4cd80977cd546926919e5194e709e93ae05c192cc59e77b8594", + "lib/meshchatx/public/assets/RNStatusPage-CWOe58fZ.js": "3b36994a5b6e887c1f1fed3361414aa5f9987b758716fd3c0f69e51bc0973dce", + "lib/meshchatx/public/assets/RNStatusPage-CYMG2EzP.js": "8c0f303cc1673da4c4da3de9f36cc1e5e713543fdd9a379aa39be5ef1c157aa0", + "lib/meshchatx/public/assets/RNStatusPage-DHVEJlF1.js": "062867d170eee11cb1cce527b710d5736003e7d74a4896e053fe121beed8014b", + "lib/meshchatx/public/assets/RNStatusPage-DHhXEvh5.js": "5894df2e4273208476cc1f88d9f027de224c61a4abbc8b0a697bdcae1e60dd32", + "lib/meshchatx/public/assets/RNStatusPage-DTAG6m-B.js": "4b8564acbbc45104a50dcae3186ecf210cbc4516b721c29bbf0830fbb37f4d81", + "lib/meshchatx/public/assets/RNStatusPage-DyHIMWIS.js": "7c8371dd3c400a31cf0795e3befc0481cfdc24a03d57f1e55eecdc3d7dde5007", + "lib/meshchatx/public/assets/RNStatusPage-LNxrqC5V.js": "0ff1be162d4b5c36fe66994164f4606f6f7dca4be994909d3a648207ccfff86c", + "lib/meshchatx/public/assets/RNStatusPage-nP-NnBNq.js": "42a63d8ceb7eda9196589ffeb151bfc5fade25d6e5b4ab60c05fc26693275435", + "lib/meshchatx/public/assets/RNodeFlasherPage-BlEe_16U.js": "aec2b876192ae6d3a8d023fcf389ccf5eab7e7b9fe08ce242de427ceedffe0ba", + "lib/meshchatx/public/assets/RobotoMonoNerdFont-Regular-DyU2aSNn.ttf": "3357fec1cce2d30c9a547ab35f5bd1742c005ce6343096427750bdf160be0a8d", + "lib/meshchatx/public/assets/SettingsPage-B2NvFceQ.js": "1e3f221af2616af7a0289612f8023ded731106b07e1e30339f03d5d24bd53379", + "lib/meshchatx/public/assets/SettingsPage-BQUh1tUa.js": "817973d93d98e4bb34ccac5dba8587801192e8a0b7fa51be1017008bb0151550", + "lib/meshchatx/public/assets/SettingsPage-BTA4iAYq.js": "cb85dde7aa0476910bf0dcceb0bad242a1648f05a6288e67bbf2a50991318380", + "lib/meshchatx/public/assets/SettingsPage-BUGPHwtI.js": "32e696172462d5baba26443be246224e55b69770880a2d3ac5a8fd5483cf8c11", + "lib/meshchatx/public/assets/SettingsPage-BWB2qV6C.css": "6e1aee2c65ab471e2a4890178ac10f88c3849a59e2c0aa4a8b0c571e1b50a240", + "lib/meshchatx/public/assets/SettingsPage-BaHpJhSS.js": "110bb4a3563a16ca0f9df53fbe9552f6a0f93012141a23a9a4f27eb8cac461ea", + "lib/meshchatx/public/assets/SettingsPage-BlPc9PlL.js": "e6bf5a61abeabaadf9cc8c1d3868a3cf1e9b2615db3d691cd30e0b605fb4e67c", + "lib/meshchatx/public/assets/SettingsPage-BmssvI6y.js": "c9108a55864e8f2088d4708b515f5172b78102ded19096774271b79ff42fd427", + "lib/meshchatx/public/assets/SettingsPage-CYfLWd5w.js": "01ca1f7909c2adc7cf633386bb7f9a96182c4b1497f7bc1bbe2db3373e7ac440", + "lib/meshchatx/public/assets/SettingsPage-Cb2_nZRb.js": "89042a562891d54d72057f05974c83b898ab607f3a8025a9248fd6c105cf4898", + "lib/meshchatx/public/assets/SettingsPage-CnxrWsZe.js": "c9dc0924b67e643038c95a85448cd50d24952bbe93ea4e8ad5d19a31aefe335b", + "lib/meshchatx/public/assets/SettingsPage-CtjAXkUk.js": "8469127b83d144af1a7feab00cdb9ad815fe5477c5c2f8d9f73808a5f9cc7156", + "lib/meshchatx/public/assets/SettingsPage-Cz0lg0G9.js": "ae091a131d1df1224c04e831c84bdcc639886735975f4ffaf3e25cd1a3d2f442", + "lib/meshchatx/public/assets/SettingsPage-D8v1LYHM.js": "edbfdac8b0fff4002a028d4b0d6f0a4f7e59c018841e63933b5d566d582b25f8", + "lib/meshchatx/public/assets/SettingsPage-DNNaUueI.css": "94a4efae5d8a2181edb8c0084c6bcd146fa5883d458f087c3595185ce8613d9c", + "lib/meshchatx/public/assets/SettingsPage-D_ODgYVz.js": "5b5d35973c93c935f9c731cbd09f8a672bb9e5b58c08438a86e2c69bc50fa859", + "lib/meshchatx/public/assets/SettingsPage-DdgbM7p5.js": "3594fb935e9a5588d2e72318e2eaf9e852dadb4a5034166e2073058387a1498a", + "lib/meshchatx/public/assets/SettingsPage-KhrqUKXb.js": "9060d18dd1bd03b008a2405fe3fb27e036c3f09b255680b08d7130c81db734f9", + "lib/meshchatx/public/assets/SettingsPage-MkP7lVSP.js": "e7ea5e652fb54bed4779fc8db322f715d1cc2dfb831f3f607bc261e8c5f415ad", + "lib/meshchatx/public/assets/SettingsPage-NdYUyyj7.js": "025db968ff36975cf2daed3f4ae5b16018dfd45236087d765e4a9afaaa6ca6d1", + "lib/meshchatx/public/assets/SettingsPage-Z2YLdAhU.js": "a7e64da0d50c60ec1b1fca6f0ff592d7d685895dc0c599a06d03ee1b9a6b243e", + "lib/meshchatx/public/assets/SettingsPage-_E4HIBwX.js": "d4d7cac2313b0a543615e58506f690f99833c883ac6d2b4ee2b26e5956a14275", + "lib/meshchatx/public/assets/SettingsPage-piUsDFph.css": "749db426c7e6ac1908c73a6c0a09f9cd69fb1138958d043c026359f5d4dc73b4", + "lib/meshchatx/public/assets/Toggle-59RCn4jY.js": "e190819576e499d02f118d1df8c06db03d7be266558d0100e6d3872398ea1beb", + "lib/meshchatx/public/assets/Toggle-B23P06Ql.js": "1b5e45f32cf433ca71e96a12d516011acbb087587b916709e3d1fefa6d64eb67", + "lib/meshchatx/public/assets/Toggle-B55QR0su.js": "02950f5a68b6fe738e39825dc7dcc5c0afa82677227f723d2013006f978d3a41", + "lib/meshchatx/public/assets/Toggle-BHYEi1VG.js": "6ac766ce0ce10d61e286f0256b6f31fd95923571e8afba7e05bbaccbf6c5800e", + "lib/meshchatx/public/assets/Toggle-BIziF9Iw.js": "bee87aa9038b535997584f6a1692d54b673e78d40e4781719bf652b8359a03aa", + "lib/meshchatx/public/assets/Toggle-BJ3cL4O6.js": "e8b719abef326ee4c5a98c6b32604ed50c0eb2b169d0757039be55980d59b68b", + "lib/meshchatx/public/assets/Toggle-BOBxd7lv.js": "9da76aac7f4801dfa49585425c45ee1a41d870730fa86aedba2d300283dad3a7", + "lib/meshchatx/public/assets/Toggle-BrG7ascc.js": "395c73f3f1c433d3766fab564eed61ea3ba1e895ed7f16a6777c86b4163fcf07", + "lib/meshchatx/public/assets/Toggle-ByyvHWcz.js": "2ae6a710b117555f6b518435c2cec1a8698077a4e1e3bc0237a0e52cc00ab0b7", + "lib/meshchatx/public/assets/Toggle-C1eJWi3P.js": "28a4d307b0747821c42e1effa69f2483cc33c8a058dc0961d581087c92e5531d", + "lib/meshchatx/public/assets/Toggle-C7yZtT8y.js": "4a31e89c1740bf907060cda0ae313fcc1fe6dffc9e931385a52718bbc743620e", + "lib/meshchatx/public/assets/Toggle-CDqze-uV.js": "581f0b6631799fe8351eb639eaeae77fbeb414797ba376425f59c93faa70286d", + "lib/meshchatx/public/assets/Toggle-CfxT6VP3.js": "e32283617de5e6488b5104bf4a976265fa8edf562faa28bcc8efbfc40e972a99", + "lib/meshchatx/public/assets/Toggle-CvZO6wRO.js": "2382f825d23591b759638762352e216867c3e16bcfb6de05b848ab7cd52377e5", + "lib/meshchatx/public/assets/Toggle-Di6uCFp1.js": "6cb9e7aaa5f99c1935653b5d67cd3e4955e68280a80e3d3524b22a33627715cc", + "lib/meshchatx/public/assets/Toggle-DzZB-Ca-.js": "caa25fee9d0e1639382fd21ac5874c0cb404791ab92c98575153e241a47e53df", + "lib/meshchatx/public/assets/Toggle-KICF86_Z.js": "73c5d62feec43e4689a84d08d172ee564ec127e8d23ae707206220f245feabd2", + "lib/meshchatx/public/assets/Toggle-pfLCooS1.js": "d379760972f52e18e054a447e6010aeeac1d2c011aaaffa5dbd154e5f8c81649", + "lib/meshchatx/public/assets/Toggle-q0STuMn3.js": "84d6968318b4d0d3c2284ceed841eee6f44e9c51a803de564624474b1a9b34de", + "lib/meshchatx/public/assets/Toggle-qWK8RBtX.js": "05664494a7771378dbc527ce656d0c333a8799b9f9dd0624b43c6d0926c3f584", + "lib/meshchatx/public/assets/ToolsPage--Z10aTLi.js": "5a2361fcc06573315270a10bbeeb16984d0bd8c3cf56d7deb5135b10879a9afa", + "lib/meshchatx/public/assets/ToolsPage-B0FlDgbf.js": "3ba77f6b36b4bddcc2df5651ed87441762ccafd8c7e78fbdd94a48a76412fe6f", + "lib/meshchatx/public/assets/ToolsPage-BAorvmOt.js": "a2a09143a3421c068aeab24efdaed1e7145e3748d1c62f18bc8678620efcb1f0", + "lib/meshchatx/public/assets/ToolsPage-BE5NkXQB.js": "0a278f92cdbe177e13ca9fa6cedf774698f3c9f6b6f4e690cb3c5bb9a8ff67fb", + "lib/meshchatx/public/assets/ToolsPage-BPN9J1bu.js": "b85977f856521310e5eca3524d655323afbd4c52052637b49d5a98abd8a2867d", + "lib/meshchatx/public/assets/ToolsPage-BY5bRSRr.js": "2391ed3b659feab337ce254a150a8ba798a409ebf8139569b3ee8d5fd735cb45", + "lib/meshchatx/public/assets/ToolsPage-BgNfJ8fh.js": "57546c75f72bf14e66c4769da529a4b7cb95f88ed7f2dd2127937aeaaccda18c", + "lib/meshchatx/public/assets/ToolsPage-CCZUezpR.js": "f43dbe17e466c75d05e1f7d9fad87473c55627ffb0e2091d9f1f7df0b1bb7201", + "lib/meshchatx/public/assets/ToolsPage-CIL1rxRX.js": "3929db20ca506dd8a0f5d472a05020b6d17ff19b05d1f5fbfc4de29c06a3c6a5", + "lib/meshchatx/public/assets/ToolsPage-CPSXRsrJ.js": "6be53f8324013a9bf5ad594ef306a855153dfc61fbaa4ab7ca78b788ea2ff356", + "lib/meshchatx/public/assets/ToolsPage-Cew0Sqhi.css": "e1b9d743705fa603a58891abe0593e8926429aabed9c8cd5d691bdc63a879e27", + "lib/meshchatx/public/assets/ToolsPage-Cm6ojBq3.js": "ef96587aa53a4d8c372a6568d023766a15f855cb1285bcc5ec60736b5fc4b7df", + "lib/meshchatx/public/assets/ToolsPage-D-IbKVrq.js": "a86c77d33d8d74e3ec54ff4a44134f0d0fcd7d9476a3b7f0f5337416fca56d08", + "lib/meshchatx/public/assets/ToolsPage-DCqZsXeh.js": "0915f4ea91b2fd2245268693e263c2bab301e9102cbe3c9cc4ccbc5f6504639b", + "lib/meshchatx/public/assets/ToolsPage-DHKGnt7Z.js": "514cb6228d057782556f7339071527cfc18e8bfddfb21ae90692feb252b7d71f", + "lib/meshchatx/public/assets/ToolsPage-DTD8UxZd.js": "d91c74ee0ac8a88e73c60630edd6cc2081edfa503023dd00d266d65cf65f630c", + "lib/meshchatx/public/assets/ToolsPage-DWpU2afb.js": "98d2bb2d51a8ce7db8d76bbb11ecf314eee807bd69b55b3c47cf60eb0c37dd90", + "lib/meshchatx/public/assets/ToolsPage-DfjQvRAF.js": "f03a9b547353041bd26219408e1bad31e9986771c96e3a8c692fc62ca49b20c5", + "lib/meshchatx/public/assets/ToolsPage-Dnc_orjh.js": "b1d79f9bfbe3f62b905b060100c9e4790834210fb02473ffd0318866966457c5", + "lib/meshchatx/public/assets/ToolsPage-DvDwVZ8q.css": "8b40bbc801fb539e2346d30fe073f355e22a7c6f4f1fde6de2e4ea9ddd46d0c9", + "lib/meshchatx/public/assets/ToolsPage-L38MWtvZ.js": "0dad49737c44ba1114cb0bdb7b8799f9ec0d49f0200c2a6d8af0355c4f95ae40", + "lib/meshchatx/public/assets/ToolsPage-jGJtt1FO.js": "8fe7a078df4e0f36d6cf8ac4fe5dfd1db3cdd511cc5cf730ed1fd51662e1634c", + "lib/meshchatx/public/assets/TranslatorPage-2Yezyf6n.js": "bcdc4098efae54479ee44c4a19f76f8a4c54dffdf580f979d005318ec6805979", + "lib/meshchatx/public/assets/TranslatorPage-B9lOpJC8.js": "952cb88dcef6a892dbc871ae5b69def1f4fdc3b0d1b010e5d32dabcb1d8548f3", + "lib/meshchatx/public/assets/TranslatorPage-BBnOy-9j.js": "3b350824bea7bb7abede2d7d4be55626706470ad69719547527e817b6a9a3e43", + "lib/meshchatx/public/assets/TranslatorPage-BhB_cOYa.js": "dbfa31d1769aafa320be2de0b3e5c7d520296f8a57dae24777c56f59fe679271", + "lib/meshchatx/public/assets/TranslatorPage-Bx-iamx_.js": "3b4268fa07113dcdf7fb7572f2ed8bba09bca596bb9cc7be1ac0988260d490d9", + "lib/meshchatx/public/assets/TranslatorPage-BxiE4CTi.js": "88db0f1398eec72b401b07b94434d09bf56767ff3823d15f8e99a550d6f07658", + "lib/meshchatx/public/assets/TranslatorPage-C1MrKE6r.js": "beb6a5f7ed42c0662044de209efd6e6d1a026e6c7d7e4cc46854ce1d1376bbfd", + "lib/meshchatx/public/assets/TranslatorPage-C2D0qvec.js": "3f321eaf12c7981a6944df496dd8ce427e0680e758441093ca24a8c8f8633fc6", + "lib/meshchatx/public/assets/TranslatorPage-CQs4_NoK.js": "a8d8838e74d631444196a11291a7299e4a75d378476510c46a294330d7620ac7", + "lib/meshchatx/public/assets/TranslatorPage-CZ__7xGT.js": "7f765bf40e4a2c0382a8806142e67a1255a164fea3a3c124a498eaa584320964", + "lib/meshchatx/public/assets/TranslatorPage-D0lqy7LK.js": "e24560834361754885f6e9b6b07233adc076bf109e769fb4a397ee857dd77078", + "lib/meshchatx/public/assets/TranslatorPage-DU0_fIZo.js": "a0127d8ace8a56e1f5de1a844b40f100f6342258ea5c729147e6ce18db7ad9cd", + "lib/meshchatx/public/assets/TranslatorPage-DYyPNK-E.js": "d38688427bdfabf261aaec97d5ae5323434887147869018e818abca639529d37", + "lib/meshchatx/public/assets/TranslatorPage-DdhsGqd-.js": "2d3628cc34aabe5c667396046c96c61e3a53736745dc8f39f6cba38d09c55a6d", + "lib/meshchatx/public/assets/TranslatorPage-Die2Kti8.js": "9b0d0a594e2b147a2fe1430cda8770d26e463ef2211644be2f93ee22e4609e2d", + "lib/meshchatx/public/assets/TranslatorPage-DiyAD1yE.js": "d780a4aff40db62a2c57859c87f6b48b01b78c23e4b23c46488740cb1dbc06f1", + "lib/meshchatx/public/assets/TranslatorPage-Dnyns-3_.js": "ceedc57a5251f582c21abb8848cbe032daeac2de2b94e589ca63117ae6834537", + "lib/meshchatx/public/assets/TranslatorPage-Dvv62_Nt.js": "fda3d637c566626f81a0e0a7b35d82b3cdfb3d1d7536ee8725a1112411b35358", + "lib/meshchatx/public/assets/TranslatorPage-Dz54TokK.js": "e825e1ab1b1bd1ed7cac4412a89841765aad1a70079b63c614a1c8b816ce306c", + "lib/meshchatx/public/assets/TranslatorPage-r2ceAdNq.js": "832a2bb19c517aa4915101213d375b0891ebbfd7cb1163ee896702938183d2a5", + "lib/meshchatx/public/assets/app-2fy0ix7T.css": "601334eab816b5d14c18632e689131acf4b5a36b223e63c5bf123acbae866d2f", + "lib/meshchatx/public/assets/app-B6j1Aqua.js": "6c5e9758d44fc3096cdf20bb16d82a4e9ac04f83faa3dcd1793cc55824040ce6", + "lib/meshchatx/public/assets/app-B8CKyts2.js": "c3ed5f12accc876c7f3597eff1ed212eb501fe8e73832b9715e4cd0a388e9a23", + "lib/meshchatx/public/assets/app-BHB7Vsxd.js": "5831bb7c937c5bfc9597032a522f4952f9730f64e11c956e5be4bbb793d55a9a", + "lib/meshchatx/public/assets/app-BOBXDFxj.js": "20b7aef1b45421bc64a7c8a8c1e32ae6e32c831a28dedc051c5ff5861aa84b52", + "lib/meshchatx/public/assets/app-BXuILOrd.css": "9fbdfe449e583ed793c389fbaea80ad69b0a3f38025cbb4c1109eefc8819950a", + "lib/meshchatx/public/assets/app-BaDr5OMd.js": "ca195a3822dbaaee8442308144826a57d2ee81d8d73d93aa5f9923c421bb79de", + "lib/meshchatx/public/assets/app-BbDj6Q8X.js": "ce7025732322005c795d7202dfcf52a9cd4ce143149969cc1073d41fe6381a3a", + "lib/meshchatx/public/assets/app-BbY1SChk.js": "dfc0594a5d3142b9220853d26bbf19803ab5d0721001b4f42f47131dd40f7190", + "lib/meshchatx/public/assets/app-BmpTRjdT.js": "c2af7991c823b38c43d1e91bc824e1b984f76aa38b1c636326b19e1d96378726", + "lib/meshchatx/public/assets/app-Bohj3HPH.js": "439c99979819fe2f65c621b8b8bae00fef9f6dacb520fbcf2acf5685f290a87a", + "lib/meshchatx/public/assets/app-C4nDn0Na.js": "77d4d6975479c3fb608238b69b0abc50f1a46eec980a0c1be53d9622bd2d4a8d", + "lib/meshchatx/public/assets/app-CE3Hv6a6.js": "81aca058b7bd320fca3b65d92e5a7c5e6e851318fcaa854cbe712cdf1b670696", + "lib/meshchatx/public/assets/app-CTRkibwF.css": "b8f7a7d52f31af48e35ca0c2a8670edd64c4f28361b4eb412a00f28597221e90", + "lib/meshchatx/public/assets/app-CTqOzAzO.js": "6aa9e4f4366a4769220f697be7dac38146d645658190e33c7145bee4bfb98e02", + "lib/meshchatx/public/assets/app-Cj_1FtQw.css": "cf2e01aaf6fad80d752baf7a3f07d4d7dc08ea4d38316f341d5634e1c952c926", + "lib/meshchatx/public/assets/app-CnWI1kjY.js": "890f181a79455eabdbf26cc9ca4eab34ea3091da92ad3b905de8297c9a8f0e7d", + "lib/meshchatx/public/assets/app-CwKr_yxB.css": "caeb23a9c6bf10c22b8d156e1d96dbc3e72d18ee76ac37be9885831cd62868ab", + "lib/meshchatx/public/assets/app-DTD_JJvV.css": "8f549a4267d38e01ba9af00e4287bc93b9516e68aae18819f6bc5ea1d509bab9", + "lib/meshchatx/public/assets/app-DTNPJDnD.css": "795b62ed84ce576bf737e9e43276b4a09fd7087233abfdb6b50bf33a8c46b011", + "lib/meshchatx/public/assets/app-DjEvJFWn.js": "9b78392a3df0b616fa569cab8f441a338573e9a028471405892ba0368014d56e", + "lib/meshchatx/public/assets/app-DsETXe-k.js": "b935ea6a5c9ed4cf93c1128812803ba272a2d4d77eb857631a949f35e6fb0ead", + "lib/meshchatx/public/assets/app-OYNH2PgU.js": "0888811e513a882dc4259a6b94fa29279d95c68bb258a975583cadeb312f55a4", + "lib/meshchatx/public/assets/app-QAFEbTCA.js": "9c9e9e3313b36c9e03aadb705c21fae67d232290218796a00419bbde748e27e3", + "lib/meshchatx/public/assets/app-RFBX_G6w.js": "63bd0ea6fab70f05d4801aa7b95c3461246c3ecf20d5fe4a7da34ad664a33b96", + "lib/meshchatx/public/assets/app-_GNIkRr2.js": "1351b5f5973f2b41a814d2e938eeca2581313a247463a3fd76c5686d635a46e7", + "lib/meshchatx/public/assets/app-zuyAIlIs.js": "a7c41ab6e15ea121781a8b7da09c33a67431219a2253ba78dabb588739aec470", + "lib/meshchatx/public/assets/images/logo-chat-bubble.png": "2d73e0e18141cbcebf0a38c31c2f5152370291f6eb8eeb65a7fd02a29d9b82da", + "lib/meshchatx/public/assets/images/logo.png": "2d73e0e18141cbcebf0a38c31c2f5152370291f6eb8eeb65a7fd02a29d9b82da", + "lib/meshchatx/public/assets/images/network-visualiser/interface_connected.png": "a6f2e0a1efb5949789bc47a15922e3d2f443d51cee30b984b50d7576a5e95e7f", + "lib/meshchatx/public/assets/images/network-visualiser/interface_disconnected.png": "948f78f1957ffa821114bd18d4cf13986c65269055eedd106be252b44274fd9a", + "lib/meshchatx/public/assets/images/network-visualiser/server.png": "9f995a1dbb06232d71be176267199439b923d5898e076c890dea01b6a9b16535", + "lib/meshchatx/public/assets/images/network-visualiser/server_1hop.png": "7a3ad9dbe673dd2ef8a5b7d90ac9c276d436d8b1d16bb69f8ce84e40f5bcfb92", + "lib/meshchatx/public/assets/images/network-visualiser/user.png": "bcad4e7a6bcde488199f23e9fd6c60a6fd928c05f079175499785c5636f13796", + "lib/meshchatx/public/assets/images/network-visualiser/user_1hop.png": "91aa213e0d7d8ae55c5d89c79e77cc37ff3bc5d405876af91cb70ea1ac16cd2a", + "lib/meshchatx/public/assets/images/reticulum_logo_512.png": "035f499a1619cfb6d2da2ca99539e9e9d122bb18addf2ab83d3413592e7662f9", + "lib/meshchatx/public/assets/js/codec2-emscripten/c2dec.js": "5771ab23ccd1fc7c99b1b9a257461951454918dad23ecd8b549c651540cc078d", + "lib/meshchatx/public/assets/js/codec2-emscripten/c2dec.wasm": "24f8611ba983641ee3582f1ad12163697b582134308bba2449eec1ae30935547", + "lib/meshchatx/public/assets/js/codec2-emscripten/c2enc.js": "e7b155ab6333b71ec2fabe32a55fc443db167be7491c27bb68948388c162d402", + "lib/meshchatx/public/assets/js/codec2-emscripten/c2enc.wasm": "4cf5e44036256236b5f440bc6dfd338d9d049a242a3bb90756dac68a43b31efd", + "lib/meshchatx/public/assets/js/codec2-emscripten/codec2-lib.js": "9d0a78ea1db26314d34dbd09921d625df866ae47cd8db511b0bbb2e78f0e950e", + "lib/meshchatx/public/assets/js/codec2-emscripten/codec2-microphone-recorder.js": "b7bd6721b30881f1c3ec8d6461e15d6bba94a8c6a4eac6be0dc8214a3b0863b3", + "lib/meshchatx/public/assets/js/codec2-emscripten/index.html": "67b3a8c8777f87a5bd9383ad188e6fb5025c6131628b354d8c0c0ebfae6175b7", + "lib/meshchatx/public/assets/js/codec2-emscripten/processor.js": "efe9a88a4b1ba8ad72373480e976b496632097d0344997bcf4b93d5e7c7b6bd9", + "lib/meshchatx/public/assets/js/codec2-emscripten/sox.js": "e1c13c18a90e7b1518f0830cf1d2b263856f2276381278eb78afe25b28814a70", + "lib/meshchatx/public/assets/js/codec2-emscripten/sox.wasm": "eab8957398b7df78550e5d74bdbe38dd232ad5e6d68fc874daa78a9ed669753e", + "lib/meshchatx/public/assets/js/codec2-emscripten/wav-encoder.js": "dfeec66f1ffeda1b783d240afa85141c77df3e5e6bfb0f12caa89c586c3e6b18", + "lib/meshchatx/public/assets/js/tailwindcss/tailwind-v3.4.3-forms-v0.5.7.js": "1829e78dfbc21c0929c4fc257e849d054dd7162f4bf2a5f5676617fedd990e54", + "lib/meshchatx/public/assets/logo-DZE3PCxd.png": "2d73e0e18141cbcebf0a38c31c2f5152370291f6eb8eeb65a7fd02a29d9b82da", + "lib/meshchatx/public/assets/materialdesignicons-webfont-B7mPwVP_.ttf": "61e8aba5a4e981fe22cf7c8e8bcdbea00476e75c62c37f01bf7ee33361d68428", + "lib/meshchatx/public/assets/materialdesignicons-webfont-CSr8KVlo.eot": "0b183104d2fc5f26196e773c77bdaf2e05509fd4259d2d15ecedca79b87e84f9", + "lib/meshchatx/public/assets/materialdesignicons-webfont-Dp5v-WZN.woff2": "662fefa8f2f8a95c18588d21774789c107c64e771cbe65a69af46291c4311afc", + "lib/meshchatx/public/assets/materialdesignicons-webfont-PXm3-2wK.woff": "a5928a0d5c2f624e46f98d9b15c2f60045377f7c594dd78a1759132ea3b463eb", + "lib/meshchatx/public/assets/proto/audio_call.proto": "db67d003f56bf1f8317913deeac6ecb55760c573c82f350cacfd6450da4260fa", + "lib/meshchatx/public/assets/vendor-axios-C1it03rL.js": "03842a2abe5c255e5e77227c5a50978b76230f5639302ad531bafe5552ee16e7", + "lib/meshchatx/public/assets/vendor-compressor-DH721-V_.js": "0d60c566c6074e3a14899a7eef34de5fbf100c060cdb7f91c85c17393ae2df12", + "lib/meshchatx/public/assets/vendor-dayjs-Bm9JdU5I.js": "0e7b1d2a8b6a9f404245fc05c44363797e8ff0a9263796c593aba3924ff15591", + "lib/meshchatx/public/assets/vendor-mdi-BDiqFXHQ.js": "bf220609d423893e0a456f755b3146cc5c8477891b2d5bb999fcfc8f5c61e737", + "lib/meshchatx/public/assets/vendor-mdi-Cx2MC6_s.js": "2e568519042465df31a18333c29eb8d32d4a935f2ed033f76c8eb147bea222f3", + "lib/meshchatx/public/assets/vendor-micron-BSEEgE84.js": "a66dee6052d9e0008f7295d581178addecb939553f72f536bf5b67bed87285fd", + "lib/meshchatx/public/assets/vendor-micron-DU_TH2sZ.js": "1b0bf55b194ec42669c46d877185f82ec71d88dbb878ba93381c42db0a8adf7d", + "lib/meshchatx/public/assets/vendor-mitt-BHPWSuhB.js": "ed25e2504b52c9fe7e4ddd6942bbcf1963d347dd112bec223f25666dfd8b6845", + "lib/meshchatx/public/assets/vendor-other-BjIYm04z.css": "cfce4b37252781143ea9b1c6bdbdb1348e0b77194ec89ccc19a5e00d2d365e2f", + "lib/meshchatx/public/assets/vendor-other-BtPCEgEn.css": "7f80cd941e5d83568410726dadb7f2a05e47fd819961b76c744b88cbb64d0519", + "lib/meshchatx/public/assets/vendor-other-C0noCZhC.js": "cca9b42fdf038917f8866c1f9d4750081d5f402bd2042b61346190da94b3bf35", + "lib/meshchatx/public/assets/vendor-other-DktJSGWy.js": "cca9b42fdf038917f8866c1f9d4750081d5f402bd2042b61346190da94b3bf35", + "lib/meshchatx/public/assets/vendor-vis-CfGaKk2g.css": "29ca7c5984322088d17495b1e842dc3b612893a0d07b3d004a00dc3a37c23be9", + "lib/meshchatx/public/assets/vendor-vis-DW7fmx29.js": "9e93cc024f5ff1bcc50a5cd2a71ba6184258109d7160aee1e9fb66ae5941ca3e", + "lib/meshchatx/public/assets/vendor-vue-DpQ2LQiZ.js": "887b6b1c046857e64597df74c7845578798ade35dacdfa88ecb569b20debeb93", + "lib/meshchatx/public/assets/vendor-vue-XbqVpb8f.js": "ac54e340d86d33d265fd8a3f3e3c64334ec3dd50106506c100defbaa80a9dc81", + "lib/meshchatx/public/assets/vendor-vue-router-B-dvAhom.js": "38550e69ae685e1d9f5c405ce019b70a808d84bfb2a6ae46ac93a18a2aa44a9d", + "lib/meshchatx/public/assets/vendor-vue-router-DNECaeJa.js": "8f40faea305bdf48a74b198e2a4cf57aad2584d27c649926908092dfe3346614", + "lib/meshchatx/public/assets/vendor-vuetify-BLqNJyZz.js": "ab7479f05c00ded360c0dabb266e57a260385782ee1db27973907892400b8793", + "lib/meshchatx/public/assets/vendor-vuetify-CZPGfs0P.js": "65924b51d3aa97e6b2b6c2537a6de5e03d5c502cfd6a32a763efe3f4090539a5", + "lib/meshchatx/public/assets/vendor-vuetify-Pi5piU4G.css": "3bfdb31e32b3a58f3d73a72709fa746a49b5080afdb80e6312d142bbc2d1b3e6", + "lib/meshchatx/public/favicons/favicon-512x512.png": "2d73e0e18141cbcebf0a38c31c2f5152370291f6eb8eeb65a7fd02a29d9b82da", + "lib/meshchatx/public/index.html": "12b6b63d5bb8164a855a6166e742792db319a3e26ec32ff91f2c277ebc4b3874", + "lib/meshchatx/public/manifest.json": "3087f201e01ba1e4783999433b9cbd34071a634f737b932c288bd2b0bbba405a", + "lib/meshchatx/public/meshchatx-docs/meshchat_on_android_with_termux.md": "66b5ddd5611a5bde02072e6e3ec4a6af01c7baaba90531b2d3e385ea5ad58a70", + "lib/meshchatx/public/meshchatx-docs/meshchat_on_docker.md": "6c0f0874d08188435d694f0d73114485cbebcfa16459e4c52ecd3f86b794fc4d", + "lib/meshchatx/public/meshchatx-docs/meshchat_on_raspberry_pi.md": "6a9db4284c00ea2e0443bdab124e256d3daf89489482141ed124c8115a62e360", + "lib/meshchatx/public/rnode-flasher/LICENSE": "4e590a1cbb467d60c6c55ca547dc71517955098d13d5483e3d9191fc03af44df", + "lib/meshchatx/public/rnode-flasher/README.md": "d453c7d31a69ff39fea6d096cba10fb8025a3eeef9c17e310ff38ce60adf311f", + "lib/meshchatx/public/rnode-flasher/index.html": "496fbd47d8879846812ba1e8895d3ea2451dc7686b374f3a47e4420b2f915865", + "lib/meshchatx/public/rnode-flasher/js/crypto-js@3.9.1-1/core.js": "4c350747271d3901045e9f6939ec2f0edd40dc6140bec6b8e540b66d80310b86", + "lib/meshchatx/public/rnode-flasher/js/crypto-js@3.9.1-1/md5.js": "1d7f30238bedb8d3016abb0f4096480d960e1d1668720668d47dd39f80f24a48", + "lib/meshchatx/public/rnode-flasher/js/esptool-js@0.4.5/bundle.js": "6320195516fa7974926025e3f33d0fd4a18cab3e1cf26526b9e2c079007176b0", + "lib/meshchatx/public/rnode-flasher/js/nrf52_dfu_flasher.js": "f7f48c88357dae487d724cbb735af12a93b0843aa75183d1dfd51b4be82c6f54", + "lib/meshchatx/public/rnode-flasher/js/rnode.js": "31583723b56724d3485873d49a8eb4abe07587462f700dd25a2f9eae02ab4f22", + "lib/meshchatx/public/rnode-flasher/js/tailwindcss/tailwind-v3.4.3-forms-v0.5.7.js": "1829e78dfbc21c0929c4fc257e849d054dd7162f4bf2a5f5676617fedd990e54", + "lib/meshchatx/public/rnode-flasher/js/vue@3.4.26/dist/vue.global.js": "c71ec2d9f47acae53c0202acbf771c1e06e13943708c8e7a4ef76f733b91e2b5", + "lib/meshchatx/public/rnode-flasher/js/web-serial-polyfill@1.0.15/dist/serial.js": "739e8a556a1453c87a619b2520dcbda39f0cea55c5d0bf865bc5967e7e4fcad0", + "lib/meshchatx/public/rnode-flasher/js/zip.min.js": "4435d44e680530b0965c7219227f14601f56fd703a27dc7844c1b78fa4501b76", + "lib/meshchatx/public/rnode-flasher/reticulum_logo_512.png": "035f499a1619cfb6d2da2ca99539e9e9d122bb18addf2ab83d3413592e7662f9", + "lib/meshchatx/public/service-worker.js": "33d3c60e6a84f1e43ffdb03a32a96d8d87e716f9dbf3828896810c91cc694d5c", + "lib/meshchatx/src/__init__.pyc": "548cf869efb387ec82427694cde124406c0d31bd0989ccf0fc56a88f1a968c1c", + "lib/meshchatx/src/backend/__init__.pyc": "507bf7619277ba811a3dd78982ecc9f00467e5764bd6b5e769edca293611fe16", + "lib/meshchatx/src/backend/announce_handler.pyc": "6393ea2caa12d638572b04401bd7ad9517980c5605b6b318206fac65abd06c08", + "lib/meshchatx/src/backend/announce_manager.pyc": "027c538008ef992013fd0fa61b0bcf70b48c0a62bed981a5aa1768a86fda6e68", + "lib/meshchatx/src/backend/archiver_manager.pyc": "a76c9d8d7cc82f57cc8ee84b8fc1602a014e8fc3c0283a766c7eb757ceeafbc5", + "lib/meshchatx/src/backend/async_utils.pyc": "0a6fa463e03f024d27072061975a1bcf9b793634f6fb2005da7b101f9c118caf", + "lib/meshchatx/src/backend/colour_utils.pyc": "6c93816c445b4d17b94563a6525e8f8272f2d9ae57d8daa8a33aa3c711a267ef", + "lib/meshchatx/src/backend/community_interfaces.pyc": "a3dcbd3c1f6a6b8502ab8754dcbc096dab2b1655c18b86247bae4dbde43bbd12", + "lib/meshchatx/src/backend/config_manager.pyc": "10a620bab746168831b7fc19cdf636cedc9b6557d0f4c13a83f508a5b238663e", + "lib/meshchatx/src/backend/database/__init__.pyc": "2865f72f20cb5ba0a766e9377dbf9527fa9386775044a810bf3b51be86f6cffc", + "lib/meshchatx/src/backend/database/announces.pyc": "4c9249b37537bb9aae510534cd8c85b58dd1b4ee962126a2ec9dd91d0d164c78", + "lib/meshchatx/src/backend/database/config.pyc": "dbfe1babe8fd4b3455a872b2cdcab7304a026d964ece9f25209a688ec0c86a42", + "lib/meshchatx/src/backend/database/contacts.pyc": "50f5f0df140b33b72d6011a48107847a9057fd7839c48fc3c8df8c82c96e013e", + "lib/meshchatx/src/backend/database/debug_logs.pyc": "85b2a05da6059a74d568aa6f82b6434cfdd4cba898d2573d3d65ca133fd6b34a", + "lib/meshchatx/src/backend/database/legacy_migrator.pyc": "3c954566fe8581aebf929cc39a556332ec66a20ae4edbf206a84ddc75514ab1d", + "lib/meshchatx/src/backend/database/map_drawings.pyc": "df2b602fb83be5352bd9baee4500a1b39251b1ecd6fdf8ca39b758feb476c052", + "lib/meshchatx/src/backend/database/messages.pyc": "3f15d622494b7ed3342a8e7ec22916a018a02662e76cd63cdf58c429be5af574", + "lib/meshchatx/src/backend/database/misc.pyc": "7523f99a18083fb586099c7e5e36dfc1965e0bd595fbc6597ff759b6c270946c", + "lib/meshchatx/src/backend/database/provider.pyc": "3e74be8357e9dc1bf9c2e8f5d76f53abef939e320f41d99117ec5f2e97159a36", + "lib/meshchatx/src/backend/database/ringtones.pyc": "3b6e7582a285ea9d7e1ec249c2db5e85d6d0e31dc7a30ff141768205df7c3fee", + "lib/meshchatx/src/backend/database/schema.pyc": "78c237c92bf4bed5b52aedc2ebeeda27767ce44741bc1e3fc6a7e51ea3578d85", + "lib/meshchatx/src/backend/database/telemetry.pyc": "0bc61db825a8fe7623ac127d265427a8baf46ee87cd289c1f624dba53ea71990", + "lib/meshchatx/src/backend/database/telephone.pyc": "5437b99b383829c12dddfce695a5f8131e7c5b1158c498da70de6bf3000bd8a9", + "lib/meshchatx/src/backend/database/voicemails.pyc": "097725b79122d6eda1780edaab304f262cc42d00bc21662e86d9ed399639bd64", + "lib/meshchatx/src/backend/docs_manager.pyc": "c9578e2d30a815461463c1e81db9644ec50d711bfb806cde71deefd43c725eb0", + "lib/meshchatx/src/backend/forwarding_manager.pyc": "193677db7f9041cfa2c397771886dd62660f0c5db8cf755e554ceeac06af0d75", + "lib/meshchatx/src/backend/identity_context.pyc": "3b16675289df3612498a23dd73d9cdbd02035ceb8b3aca05f0a785e92011265f", + "lib/meshchatx/src/backend/identity_manager.pyc": "2dd602c97ffb381ebf450bd3f40ccb1175e682afe53aabaa0c53a3ffdfdc9d17", + "lib/meshchatx/src/backend/integrity_manager.pyc": "dbec84e46380dbeb3f79bf6a0a529e8446856b2b229197c22f869d86da443e49", + "lib/meshchatx/src/backend/interface_config_parser.pyc": "e2bfe1ee32c0ece0e91fc96a22c913118fca57ca1582e918bd4a4b7b717547e9", + "lib/meshchatx/src/backend/interface_editor.pyc": "6c7815bd22b739b88a69c2d14471746aa0ef27b7a44cab6ed143fca4e0640097", + "lib/meshchatx/src/backend/lxmf_message_fields.pyc": "cb0718617356cf00f506e197abd4ba9463f0fbc4d94e165cc9bbe17e9f9a2a30", + "lib/meshchatx/src/backend/lxmf_utils.pyc": "dbf148a99751e7528f3f5a95898097988730bfbd85271d4e4cd64d5e248a5503", + "lib/meshchatx/src/backend/map_manager.pyc": "640685d59cf2fa4ecd34d9a33674f04dbf03be1373bd362e99ed0eb476378c19", + "lib/meshchatx/src/backend/markdown_renderer.pyc": "ee12384ca0b896cae85c6c3b59620ffe4d79aaf1826d72210a4e6b5d488c6a8a", + "lib/meshchatx/src/backend/meshchat_utils.pyc": "cf0561ce6a93169f1bb6be4219f12ed8ee9ced2c0d6b81e89196ba9c8129dac5", + "lib/meshchatx/src/backend/message_handler.pyc": "fb7f583f30d5d192ac9794ec09ba94aa919ab759f007998d0120a2ae6c52a373", + "lib/meshchatx/src/backend/nomadnet_downloader.pyc": "8f5765e7c0aafe0a09370bf8c03a49770aae1062ff57f3618291f256f9aebc39", + "lib/meshchatx/src/backend/nomadnet_utils.pyc": "6841de9233a3595cc8c36e59a10e5a9ebc8bfae8a301d3e48b7ffc723dc4fe76", + "lib/meshchatx/src/backend/persistent_log_handler.pyc": "6f7d6e99b969bbfffa8c857847c4da7433daaa564da1e422b61a79b4eb6ff0b4", + "lib/meshchatx/src/backend/recovery/__init__.pyc": "403990bfb6fe62d5665b7b671bdce8911f91d3e85c359d8435e3797be9fd4308", + "lib/meshchatx/src/backend/recovery/crash_recovery.pyc": "d1032bbd517442066ef2e3c056a0b42cc4a7aa103501178638d307cb10044a6f", + "lib/meshchatx/src/backend/ringtone_manager.pyc": "722963182fc03b82e2db13b4b6563cd5625aca84fd653466884c3777f1338033", + "lib/meshchatx/src/backend/rncp_handler.pyc": "9aa633a9f0ae68afd8b2b7e5e80bc3ce02c2521f1692f59a53506141d17ca7b6", + "lib/meshchatx/src/backend/rnprobe_handler.pyc": "484fc5dbce4081f965c28763487cb837bc1136c307bf7d8db1ef8a931dcb6edd", + "lib/meshchatx/src/backend/rnstatus_handler.pyc": "9075aad102ac2a891f818ffa7bb4a4ac5bc4bc7414bff411960bac92076e28f8", + "lib/meshchatx/src/backend/sideband_commands.pyc": "cda2579da628302e4fea04b775a9dcf30097913f4d6768cc200162c548a83ea3", + "lib/meshchatx/src/backend/telemetry_utils.pyc": "716e8a0021c804a477d2f18d01461881d92c8b9c095a605be32988748df52c16", + "lib/meshchatx/src/backend/telephone_manager.pyc": "76d36ebbf58b1829497eb0ba6b4a9fccca6a35500715837a897837c4caad0709", + "lib/meshchatx/src/backend/translator_handler.pyc": "6ea736f420e08e70e02e809d2556ca728d8976c41177cb5e0b7f3a41cc2802c2", + "lib/meshchatx/src/backend/voicemail_manager.pyc": "6c1bfeeecb8fd5e25020268e7aa3384dcd4cdf592a67a8025390cd4a4382a43a", + "lib/meshchatx/src/frontend/assets/images/logo.png": "2d73e0e18141cbcebf0a38c31c2f5152370291f6eb8eeb65a7fd02a29d9b82da", + "lib/meshchatx/src/frontend/components/App.vue": "4a12991a470a01db7921e95fbbe11e0ac1673000e02a072e059f423929f40ff4", + "lib/meshchatx/src/frontend/components/CardStack.vue": "4720185d7eede95fcf979c8be6a4e2d9c6aeabdc860e7ed58b8d6eaaf105a74f", + "lib/meshchatx/src/frontend/components/ChangelogModal.vue": "8f748c8d918b8f454f438d6dc5d1b6970af7b1d7dfb3325706495af0d0019df6", + "lib/meshchatx/src/frontend/components/ColourPickerDropdown.vue": "8d9d0184ec2189c9f7fc75e38b55cd04116fb263929e1d7e9b381557f8417eb2", + "lib/meshchatx/src/frontend/components/CommandPalette.vue": "3f0b4422e49b1164275af29a2a29dd67a0791c7e82d0f400b82cc882cbcde71f", + "lib/meshchatx/src/frontend/components/ConfirmDialog.vue": "cc6d9737f8f37a9d7c138f25f7060895f38299905e9af541a2c283e1eaf8a4bc", + "lib/meshchatx/src/frontend/components/DropDownMenu.vue": "27ece7df482e4818b20689536841df25cb86a311785cec9eb9193dc884f98bd8", + "lib/meshchatx/src/frontend/components/DropDownMenuItem.vue": "0bb9626bdf3526da75cd5b69c46e924df14cdeaf9ea7890141e1447a9d2c1af3", + "lib/meshchatx/src/frontend/components/IconButton.vue": "ac62e58b859e87eb7eb95e07356d52c4bd4531950bce15aaefa5765ff571cbd5", + "lib/meshchatx/src/frontend/components/IntegrityWarningModal.vue": "a74a010f3e550c78027cdc15ff946c0ad1e23174a56ec110927b50667829f1f3", + "lib/meshchatx/src/frontend/components/LanguageSelector.vue": "830ba9144d9f97717b221b1fadec82624faf864755d3a1981a1cc54c600ba649", + "lib/meshchatx/src/frontend/components/LxmfUserIcon.vue": "6d5f4fcf638394b1fe8fd9f24f9691f0a6da2915e776b235321542b7d9a4c3e5", + "lib/meshchatx/src/frontend/components/MaterialDesignIcon.vue": "cbed9a408df8b63f19b69422c715696e93d22a9fa6570c48dc34f95a081cd91d", + "lib/meshchatx/src/frontend/components/NotificationBell.vue": "e2b5a0c30cf6cdec8724257ff99be9794fdb312f9f3c358ae7f09a49811b8126", + "lib/meshchatx/src/frontend/components/SidebarLink.vue": "a8b34d24e9c8c562b8e49c60d27c5137d3774c313abcc0633796c7c9a07873bb", + "lib/meshchatx/src/frontend/components/Toast.vue": "5b181e9b7f11b695f157af1bafbc3f05e4b97841d2e28a67799e286b2bcb964d", + "lib/meshchatx/src/frontend/components/TutorialModal.vue": "5f6c28c67ab4a0bb68c529a00ec46111d7bcfec831644372ca6e8c00cbc33941", + "lib/meshchatx/src/frontend/components/about/AboutPage.vue": "07d5cc7287c0c612633520c7aeb57240b024c288979cd55b7d1ef4243ebb40e7", + "lib/meshchatx/src/frontend/components/archives/ArchiveSidebar.vue": "08699f2ff9b3892c08c091c43a8ea520be0e6a7f4ce56c3b814d85df16bf1e8f", + "lib/meshchatx/src/frontend/components/archives/ArchivesPage.vue": "88cbf111ad0b96c743b1cd12ade91cb31e07ad55d6d2af6619d1b201745ff330", + "lib/meshchatx/src/frontend/components/auth/AuthPage.vue": "630b273a65b2d785feeb226a239c8fbfc2b4cf1d853485fc874eec55a86afc38", + "lib/meshchatx/src/frontend/components/blocked/BlockedPage.vue": "d03e92421b4136650435d322b91015046686dc9823afe5db4659136860fb8f53", + "lib/meshchatx/src/frontend/components/call/CallOverlay.vue": "b75ba5867920641d6db75eb539d7117355222f8dd883ea84c264779e8a623277", + "lib/meshchatx/src/frontend/components/call/CallPage.vue": "3b0d61eb1633437304b9fecf6999f7f3fae2d2b398180a29b77565882b8a43c5", + "lib/meshchatx/src/frontend/components/call/RingtoneEditor.vue": "0ab7cbc582dd4895b31e90ee2191867bda71c8b22809a7fd7a07c52c0a608c1f", + "lib/meshchatx/src/frontend/components/call/RingtoneEditorModal.vue": "77130ef44a3e0b3425549849159395210da5fb30b9ea77176d61d5436131e7bd", + "lib/meshchatx/src/frontend/components/debug/DebugLogsPage.vue": "3b78d0569a22a2828dbd64c716f7bccbc7f1690ff4f489061e5ea6cc2a3bfaa4", + "lib/meshchatx/src/frontend/components/docs/DocsPage.vue": "594a0592dbb37003247e92dae4eee8b024732dad6a7e3496a1461f2bc1e7a671", + "lib/meshchatx/src/frontend/components/forms/FormLabel.vue": "bbf96a72e6c24ce3117231127a0f5c1cc7602c4b07253d33b30c2d06d8d82d90", + "lib/meshchatx/src/frontend/components/forms/FormSubLabel.vue": "f51888a11726cdc4442f142b80920f2848c77a3d45e810e6b107fa7fee22195f", + "lib/meshchatx/src/frontend/components/forms/Toggle.vue": "4b392284db8dd4648a7511367a314dc0b4fdc121009ebf639a2c2d9b36a28cf6", + "lib/meshchatx/src/frontend/components/forwarder/ForwarderPage.vue": "2a27545221c407e6b9a131230437a141a7eaa66bc0337e52de89c316b9510637", + "lib/meshchatx/src/frontend/components/interfaces/AddInterfacePage.vue": "35d9defcc49f9024d399b1391e059947600018a1145ddad5e60bd217f330afb9", + "lib/meshchatx/src/frontend/components/interfaces/ExpandingSection.vue": "7700e5b0e524ab58666121ac24fc64826aae2fb8a8dd5c4961f82e21455755ac", + "lib/meshchatx/src/frontend/components/interfaces/ImportInterfacesModal.vue": "7cfe8d5c1d8c5dd615a3302c0d4f04d05dac24f55e4a83e9b804b842dfcaf7ac", + "lib/meshchatx/src/frontend/components/interfaces/Interface.vue": "bb79a0caae492867c4a6266b83901804949dc620ff9401fb6c0bbc0e5bb1928c", + "lib/meshchatx/src/frontend/components/interfaces/InterfacesPage.vue": "3066b6877b90fcc54c33c07b2576cbfc200618999cb71c0ff2333569d91e90e7", + "lib/meshchatx/src/frontend/components/map/MapPage.vue": "9cd1e7b9b2a9276ff19cc96626e0bf28dc3efca021cdf828bcc0d8d5c9df832f", + "lib/meshchatx/src/frontend/components/messages/AddAudioButton.vue": "b44bbbf529ffd7e4e4482254af6a03bde7f255f8bee18aa4ad4a9835f79e10e8", + "lib/meshchatx/src/frontend/components/messages/AddImageButton.vue": "47aae1ab30b74ddaf802e8a2e69797e4c1fa38bfec724eed04cf96abff86e007", + "lib/meshchatx/src/frontend/components/messages/AudioWaveformPlayer.vue": "a0e8c55e874f310957a54b4e059b7ae731f3e094b1c5bf2457a067880f1bc399", + "lib/meshchatx/src/frontend/components/messages/ConversationDropDownMenu.vue": "5d163651f79c802ecb3b29ef5972748ca26c0ef1c73bda6d4b7c70a00e488c4a", + "lib/meshchatx/src/frontend/components/messages/ConversationViewer.vue": "60c115098f6d81250215178cf496e7e988a4488869b99af15a2c444263a32011", + "lib/meshchatx/src/frontend/components/messages/MessagesPage.vue": "99f8b6a7c9f221e4fe139c5dd21cc273d896541aa9f7a551db218f5ce6b9fd04", + "lib/meshchatx/src/frontend/components/messages/MessagesSidebar.vue": "8634548f882dd9fd08f8688aae47589f90b669607436111b7dc0d1d304682d18", + "lib/meshchatx/src/frontend/components/messages/PaperMessageModal.vue": "4c4542048f2a93c4b14f567b6d1ccde2cabca03d8db1481368dcfcb1a895d17f", + "lib/meshchatx/src/frontend/components/messages/SendMessageButton.vue": "f6bb6c1ea4de624daf1db288b469f1f1a6fa13cf6a51a08eabae63ca0e8e8f71", + "lib/meshchatx/src/frontend/components/micron-editor/MicronEditorPage.vue": "e71ba834937de67f53c884e7b3d46d44f8be165c50b6747f628a442c40f9b810", + "lib/meshchatx/src/frontend/components/network-visualiser/NetworkVisualiser.vue": "854ce8a507709de13fa16a3d41c9b5a002d3c1b024070d4d2a710a2c5bd82e43", + "lib/meshchatx/src/frontend/components/network-visualiser/NetworkVisualiserPage.vue": "6405ee48cbbc99d557b4d635fcfb4c398d676499f7d1ecd92e785a49f0f61a6e", + "lib/meshchatx/src/frontend/components/nomadnetwork/NomadNetworkPage.vue": "950e1cff585e8b09d9dde76a59fbe6c658f82c27f4beb1c0c5f63b50d698c218", + "lib/meshchatx/src/frontend/components/nomadnetwork/NomadNetworkSidebar.vue": "706742db682b4266481fbce12bfbef540b0f910157978e4572612b55b0fa2a59", + "lib/meshchatx/src/frontend/components/ping/PingPage.vue": "7ce3f8251f4b67c1e34556b8b6a98ff3a1a5aa89d99f03e157a0ec14395d13b4", + "lib/meshchatx/src/frontend/components/profile/ProfileIconPage.vue": "15dd6855b8ad8180d484ebd8cc0b642dd06363f7304ca47d614ba72987438420", + "lib/meshchatx/src/frontend/components/propagation-nodes/PropagationNodesPage.vue": "1f7fde09cd2df361a7ea2f8c8a2cb8224cb7719d07142f682810069c48f54606", + "lib/meshchatx/src/frontend/components/rncp/RNCPPage.vue": "5e6ac6959f228c1a8bb3181a866f84bab7636f7f0c245e2e5c7a834304c441f9", + "lib/meshchatx/src/frontend/components/rnprobe/RNProbePage.vue": "9bcc82d30b06dc8b78962f1927bcdc4fbb71e26a75d9df5f852b9c8838ad4099", + "lib/meshchatx/src/frontend/components/rnstatus/RNStatusPage.vue": "d4422707ecd8cd3bf1b524ccf712099c9a2676416911cbf197e38a5cb56f67ee", + "lib/meshchatx/src/frontend/components/settings/IdentitiesPage.vue": "c79d5a44121b94e726fcc699a7871ed69f2ffbd2e91d7609de885515450add20", + "lib/meshchatx/src/frontend/components/settings/SettingsPage.vue": "79ebf9678a761ce6a0e3a2645fbae5b00409be0d0cbfea760ff54cadf1befe2d", + "lib/meshchatx/src/frontend/components/settings/ShortcutRecorder.vue": "67c60b7c03c37a52219351a019a9328dfab7e9cc9d21e4b5f98f3e4c3b1721e3", + "lib/meshchatx/src/frontend/components/tools/PaperMessagePage.vue": "74cf5a8103614ad1f630f0dd7fe334e33b295491448ede6377f7d9c67811429c", + "lib/meshchatx/src/frontend/components/tools/RNodeFlasherPage.vue": "882768e87373c4ff725a8eb3e398de7cf6dc3b20f83c75e081bf14e9bfe11702", + "lib/meshchatx/src/frontend/components/tools/ToolsPage.vue": "6cb98e604b4e2756d6e9ce49c10c24d3de1b001670e4ef8680030cc4cb934373", + "lib/meshchatx/src/frontend/components/translator/TranslatorPage.vue": "cab3ed65f3d87427b93c0ef7848da4b15132af094e358e897b56875d483d0eeb", + "lib/meshchatx/src/frontend/fonts/RobotoMonoNerdFont/RobotoMonoNerdFont-Regular.ttf": "3357fec1cce2d30c9a547ab35f5bd1742c005ce6343096427750bdf160be0a8d", + "lib/meshchatx/src/frontend/fonts/RobotoMonoNerdFont/font.css": "20653f81d3484a395f14b7e3363171ae46cb7ab8893bff28887c66b38290438b", + "lib/meshchatx/src/frontend/index.html": "f77e799ff3ca5a01196d22d19bf03632e2a0a4ad39f54be6feaedc5b6867adc8", + "lib/meshchatx/src/frontend/js/Codec2Loader.js": "a30385a7eedfe600a5abbf428b32b4384f2a6c390d6679b34d3a2685b1d52aab", + "lib/meshchatx/src/frontend/js/DialogUtils.js": "33a97d4be2a17acb3e1bce4c5063112503dab414a03a566916ca5cf507850e42", + "lib/meshchatx/src/frontend/js/DownloadUtils.js": "b94edded3838a57ead6242a03a4f95b33f8af031b376988678c68e967f4668ba", + "lib/meshchatx/src/frontend/js/ElectronUtils.js": "2c29fe23b46992c396cd0e4d6cd646103747d44fbeccf8e30ca16f1adf3c347c", + "lib/meshchatx/src/frontend/js/GlobalEmitter.js": "603e355b62444d11694b13b0650c08ddf810d77cd5c0c904d83ce09d5bdb1ba0", + "lib/meshchatx/src/frontend/js/GlobalState.js": "ba87ecc82ff4878df187a9532f7148d8a23052b86154e047af462a7767558214", + "lib/meshchatx/src/frontend/js/KeyboardShortcuts.js": "099999f253c8ae161a6968b8ac9d20fedf2df05af40130d7ddb15a885b6ce753", + "lib/meshchatx/src/frontend/js/MicronParser.js": "bdc176d7a420fac0af00f5f008ce82450fc742584fe084ff8417377d794eab1b", + "lib/meshchatx/src/frontend/js/MicronStorage.js": "9eb743fb52c61e6d56c7058df80ad6f8f932bc67815974c806b65f6e1d8c7ae9", + "lib/meshchatx/src/frontend/js/MicrophoneRecorder.js": "c6484db2cb4651d1153cc5b1fbabb376d76b9284cdaa543a89055d8b2db556d3", + "lib/meshchatx/src/frontend/js/NotificationUtils.js": "4f2964c4aab14f3e23b8b5eac7239dff38df8eaaca096fec8a22551becfb5745", + "lib/meshchatx/src/frontend/js/TileCache.js": "60b3e89a07b7d05d520408b355b7bb99cd7351911725b95135cbbdbd59400dac", + "lib/meshchatx/src/frontend/js/ToastUtils.js": "6b96944dd1b0ad06466195576d71d33b3ab57e513c2e929d0ad5cd28cac7f20e", + "lib/meshchatx/src/frontend/js/Utils.js": "737cb98d6ac1651983c82d0a736b3cc3157f5fb5e40e9dc7c4632d52cc800b27", + "lib/meshchatx/src/frontend/js/WebSocketConnection.js": "019e9a8701ba5acdc03d42c1ffc7f4f5e7dc19d5167f611cd1fcd8f152dd5192", + "lib/meshchatx/src/frontend/locales/de.json": "deb3336e65166cce379306ff39bdb5b78d0fc22762cb82f11138b7a1ee5d85a5", + "lib/meshchatx/src/frontend/locales/en.json": "318eacb7337f76fc8c1b7fb1b479fd8c3ef8e128a96f75794d0d7bb82154acb9", + "lib/meshchatx/src/frontend/locales/ru.json": "e9aa331ec556013ccb5ae6e9bad4ee021cc5d31301d952d2c63c2bb0e6f875ee", + "lib/meshchatx/src/frontend/main.js": "cdffea1680a4765ae6515516e8bdc3b2ee31f837303da4064cc348f12f0bec28", + "lib/meshchatx/src/frontend/public/assets/images/logo-chat-bubble.png": "2d73e0e18141cbcebf0a38c31c2f5152370291f6eb8eeb65a7fd02a29d9b82da", + "lib/meshchatx/src/frontend/public/assets/images/logo.png": "2d73e0e18141cbcebf0a38c31c2f5152370291f6eb8eeb65a7fd02a29d9b82da", + "lib/meshchatx/src/frontend/public/assets/images/network-visualiser/interface_connected.png": "a6f2e0a1efb5949789bc47a15922e3d2f443d51cee30b984b50d7576a5e95e7f", + "lib/meshchatx/src/frontend/public/assets/images/network-visualiser/interface_disconnected.png": "948f78f1957ffa821114bd18d4cf13986c65269055eedd106be252b44274fd9a", + "lib/meshchatx/src/frontend/public/assets/images/network-visualiser/server.png": "9f995a1dbb06232d71be176267199439b923d5898e076c890dea01b6a9b16535", + "lib/meshchatx/src/frontend/public/assets/images/network-visualiser/server_1hop.png": "7a3ad9dbe673dd2ef8a5b7d90ac9c276d436d8b1d16bb69f8ce84e40f5bcfb92", + "lib/meshchatx/src/frontend/public/assets/images/network-visualiser/user.png": "bcad4e7a6bcde488199f23e9fd6c60a6fd928c05f079175499785c5636f13796", + "lib/meshchatx/src/frontend/public/assets/images/network-visualiser/user_1hop.png": "91aa213e0d7d8ae55c5d89c79e77cc37ff3bc5d405876af91cb70ea1ac16cd2a", + "lib/meshchatx/src/frontend/public/assets/images/reticulum_logo_512.png": "035f499a1619cfb6d2da2ca99539e9e9d122bb18addf2ab83d3413592e7662f9", + "lib/meshchatx/src/frontend/public/assets/js/codec2-emscripten/c2dec.js": "5771ab23ccd1fc7c99b1b9a257461951454918dad23ecd8b549c651540cc078d", + "lib/meshchatx/src/frontend/public/assets/js/codec2-emscripten/c2dec.wasm": "24f8611ba983641ee3582f1ad12163697b582134308bba2449eec1ae30935547", + "lib/meshchatx/src/frontend/public/assets/js/codec2-emscripten/c2enc.js": "e7b155ab6333b71ec2fabe32a55fc443db167be7491c27bb68948388c162d402", + "lib/meshchatx/src/frontend/public/assets/js/codec2-emscripten/c2enc.wasm": "4cf5e44036256236b5f440bc6dfd338d9d049a242a3bb90756dac68a43b31efd", + "lib/meshchatx/src/frontend/public/assets/js/codec2-emscripten/codec2-lib.js": "9d0a78ea1db26314d34dbd09921d625df866ae47cd8db511b0bbb2e78f0e950e", + "lib/meshchatx/src/frontend/public/assets/js/codec2-emscripten/codec2-microphone-recorder.js": "b7bd6721b30881f1c3ec8d6461e15d6bba94a8c6a4eac6be0dc8214a3b0863b3", + "lib/meshchatx/src/frontend/public/assets/js/codec2-emscripten/index.html": "67b3a8c8777f87a5bd9383ad188e6fb5025c6131628b354d8c0c0ebfae6175b7", + "lib/meshchatx/src/frontend/public/assets/js/codec2-emscripten/processor.js": "efe9a88a4b1ba8ad72373480e976b496632097d0344997bcf4b93d5e7c7b6bd9", + "lib/meshchatx/src/frontend/public/assets/js/codec2-emscripten/sox.js": "e1c13c18a90e7b1518f0830cf1d2b263856f2276381278eb78afe25b28814a70", + "lib/meshchatx/src/frontend/public/assets/js/codec2-emscripten/sox.wasm": "eab8957398b7df78550e5d74bdbe38dd232ad5e6d68fc874daa78a9ed669753e", + "lib/meshchatx/src/frontend/public/assets/js/codec2-emscripten/wav-encoder.js": "dfeec66f1ffeda1b783d240afa85141c77df3e5e6bfb0f12caa89c586c3e6b18", + "lib/meshchatx/src/frontend/public/assets/js/tailwindcss/tailwind-v3.4.3-forms-v0.5.7.js": "1829e78dfbc21c0929c4fc257e849d054dd7162f4bf2a5f5676617fedd990e54", + "lib/meshchatx/src/frontend/public/assets/proto/audio_call.proto": "db67d003f56bf1f8317913deeac6ecb55760c573c82f350cacfd6450da4260fa", + "lib/meshchatx/src/frontend/public/favicons/favicon-512x512.png": "2d73e0e18141cbcebf0a38c31c2f5152370291f6eb8eeb65a7fd02a29d9b82da", + "lib/meshchatx/src/frontend/public/manifest.json": "3087f201e01ba1e4783999433b9cbd34071a634f737b932c288bd2b0bbba405a", + "lib/meshchatx/src/frontend/public/meshchatx-docs/meshchat_on_android_with_termux.md": "66b5ddd5611a5bde02072e6e3ec4a6af01c7baaba90531b2d3e385ea5ad58a70", + "lib/meshchatx/src/frontend/public/meshchatx-docs/meshchat_on_docker.md": "6c0f0874d08188435d694f0d73114485cbebcfa16459e4c52ecd3f86b794fc4d", + "lib/meshchatx/src/frontend/public/meshchatx-docs/meshchat_on_raspberry_pi.md": "6a9db4284c00ea2e0443bdab124e256d3daf89489482141ed124c8115a62e360", + "lib/meshchatx/src/frontend/public/rnode-flasher/LICENSE": "4e590a1cbb467d60c6c55ca547dc71517955098d13d5483e3d9191fc03af44df", + "lib/meshchatx/src/frontend/public/rnode-flasher/README.md": "d453c7d31a69ff39fea6d096cba10fb8025a3eeef9c17e310ff38ce60adf311f", + "lib/meshchatx/src/frontend/public/rnode-flasher/index.html": "496fbd47d8879846812ba1e8895d3ea2451dc7686b374f3a47e4420b2f915865", + "lib/meshchatx/src/frontend/public/rnode-flasher/js/crypto-js@3.9.1-1/core.js": "4c350747271d3901045e9f6939ec2f0edd40dc6140bec6b8e540b66d80310b86", + "lib/meshchatx/src/frontend/public/rnode-flasher/js/crypto-js@3.9.1-1/md5.js": "1d7f30238bedb8d3016abb0f4096480d960e1d1668720668d47dd39f80f24a48", + "lib/meshchatx/src/frontend/public/rnode-flasher/js/esptool-js@0.4.5/bundle.js": "6320195516fa7974926025e3f33d0fd4a18cab3e1cf26526b9e2c079007176b0", + "lib/meshchatx/src/frontend/public/rnode-flasher/js/nrf52_dfu_flasher.js": "f7f48c88357dae487d724cbb735af12a93b0843aa75183d1dfd51b4be82c6f54", + "lib/meshchatx/src/frontend/public/rnode-flasher/js/rnode.js": "31583723b56724d3485873d49a8eb4abe07587462f700dd25a2f9eae02ab4f22", + "lib/meshchatx/src/frontend/public/rnode-flasher/js/tailwindcss/tailwind-v3.4.3-forms-v0.5.7.js": "1829e78dfbc21c0929c4fc257e849d054dd7162f4bf2a5f5676617fedd990e54", + "lib/meshchatx/src/frontend/public/rnode-flasher/js/vue@3.4.26/dist/vue.global.js": "c71ec2d9f47acae53c0202acbf771c1e06e13943708c8e7a4ef76f733b91e2b5", + "lib/meshchatx/src/frontend/public/rnode-flasher/js/web-serial-polyfill@1.0.15/dist/serial.js": "739e8a556a1453c87a619b2520dcbda39f0cea55c5d0bf865bc5967e7e4fcad0", + "lib/meshchatx/src/frontend/public/rnode-flasher/js/zip.min.js": "4435d44e680530b0965c7219227f14601f56fd703a27dc7844c1b78fa4501b76", + "lib/meshchatx/src/frontend/public/rnode-flasher/reticulum_logo_512.png": "035f499a1619cfb6d2da2ca99539e9e9d122bb18addf2ab83d3413592e7662f9", + "lib/meshchatx/src/frontend/public/service-worker.js": "33d3c60e6a84f1e43ffdb03a32a96d8d87e716f9dbf3828896810c91cc694d5c", + "lib/meshchatx/src/frontend/style.css": "5ed589d77e34fe3aab454a4e8436a7052d1210e21c90b18aad0ec65de7a2ab9f", + "lib/meshchatx/src/version.pyc": "8c5d97068b03a391d1368a492577b349016763c81870e3cdfaa1754aaac2015e", + "lib/mmap.cpython-313-x86_64-linux-gnu.so": "f4f9fcf21f78389d3f1a51b6524c85a262f0b242e407e449c5ff0cca3eeb6419", + "lib/more_itertools/__init__.pyc": "44b1bf3d413bfa8d17976fd5b5c73f12351afe833ba5a29307e3e752ba494ba2", + "lib/more_itertools/more.pyc": "47991b88f0b5aff289659e7b4cc308d65a1e103c1fdb69d8e280e61865d44165", + "lib/more_itertools/recipes.pyc": "541b029f71dec5649fd3852ffb93a81c0bc879c82fb04f5b6016e0843444a3f7", + "lib/multidict/__init__.pyc": "46de020b58945d56162b2cfd50b8b6d90b20d662acc0e66b2fae8fd372c4f39f", + "lib/multidict/_abc.pyc": "b8343394fc90f121ce4d8d0b4bef2665baa6e6235ceb0fafa25d3260640e6ce1", + "lib/multidict/_compat.pyc": "a4a526264fd1e1360dc9443a18b3db840666405a6b6d429cde19b751d47e6217", + "lib/multidict/_multidict.cpython-313-x86_64-linux-gnu.so": "54f761d8f971f708345f94fc179e1eddb0c98844e4dc5c4b863c1f54247fe9c7", + "lib/multidict/_multidict_py.pyc": "c897d89351d983c614f3ebed6acc471e7989621eed3db6975c5597406271c25d", + "lib/multiprocessing/__init__.pyc": "4f60a82faa80d6a7ea9dd04371c7a8083c5148c32fd6ea39747d54c23743a57e", + "lib/multiprocessing/connection.pyc": "c40c1d0f817378821a825beb215422abea260ffffb5bed47b1819ef4a9297767", + "lib/multiprocessing/context.pyc": "57e83c3bebdba57c56588e7fea96e91a7147faf6dfd3b683e1eb2d4da2cbe77e", + "lib/multiprocessing/dummy/__init__.pyc": "0afa59eb479caaf1076534a64a679a1a78d96396dea7967ea6e82e681ee82e08", + "lib/multiprocessing/dummy/connection.pyc": "6e47ce2dfb51e3c5c3d4e0df8eeb66aa6b63bea7952c4ec352494cb5d8c1fa3c", + "lib/multiprocessing/forkserver.pyc": "1a200da1adc4758ad3003223e82126645be4c177808a02f5da90eac69466f797", + "lib/multiprocessing/heap.pyc": "092043bd43d530880b391073beb5ac613e59bbb8cd29702aa03b2619004e8574", + "lib/multiprocessing/managers.pyc": "600b6d3a8ae765552b3a06575127bf58db2ee79b5f695a53d3b0d63ed6b29052", + "lib/multiprocessing/pool.pyc": "c24e6601ebfcff21f8eaca47fd2929b8451dd6f70b4d96bece71298c440d3e17", + "lib/multiprocessing/popen_fork.pyc": "d91f31bf11761104574003334cce7242d2d70e85ec0a72a5aab73205e3ba08f4", + "lib/multiprocessing/popen_forkserver.pyc": "13ef85204a0be265e47e4aa3b3c2d34dcc1f6ea53cbdba174dd40e9d5ed17d6d", + "lib/multiprocessing/popen_spawn_posix.pyc": "23e47110f03e9cc77db71da065155d445c7fcd92860ff016c06cae9f68377d2d", + "lib/multiprocessing/popen_spawn_win32.pyc": "f55eb0394ee0d6e7f2ea643f5671ae7be08bf9dc188d1dcc40264d6ee6309a5c", + "lib/multiprocessing/process.pyc": "ebcbbb105e966ade79077f6d578b507ab9e63b4f3fe56c1788ed5d940166febe", + "lib/multiprocessing/queues.pyc": "363cea571ffa1c1cb1cc501102fbb46e9b7d17780cb4fe002fd75eaae73a2b7a", + "lib/multiprocessing/reduction.pyc": "5d957d1e08e817614e9030c8884b23175cddbf5f413a565d4f90c4bfacf0a3c2", + "lib/multiprocessing/resource_sharer.pyc": "81d488bdcd96fc0013f59aa11c7cd78ee27e71d1571e46d934499523cbcb7057", + "lib/multiprocessing/resource_tracker.pyc": "1170673fe743b00bef8e7c3afe5719f2b1f9ca76706ed6ab4277605df693eb85", + "lib/multiprocessing/shared_memory.pyc": "36eaa710406369599bf414db7d0ea21c2196b3d557c894c35df6e4a09e42b3d5", + "lib/multiprocessing/sharedctypes.pyc": "a2515364f5d27ac91e6fe024b081e759a3bacf4d629dfeda0883a9ce8dc20683", + "lib/multiprocessing/spawn.pyc": "402661a08098d3958ec92457d5a8665c63a0bdf60c04471841e8be4ad05f3657", + "lib/multiprocessing/synchronize.pyc": "a8dfc22cac40066a7982a241b02cc94a71fc21f701b625eba6cac8997d66bdcd", + "lib/multiprocessing/util.pyc": "38fb86c14bf815e034eafbaedb8508d04d29309732dfcff39efdc21e2834e980", + "lib/numpy/__config__.pyc": "82143f9e5e4e48ae605c84f3e51cbbe46b1b2b3cf2da367996f90889765d4f8f", + "lib/numpy/__init__.pyc": "1c89ca20d70b4224b1f08d9c7efca4646da1cda1ec364b3c559211410e57eef4", + "lib/numpy/_array_api_info.pyc": "55c35af6cd53f1c37b5689a8d9b21e6d97d97a4e6f5ff7b434b7164df5fe9805", + "lib/numpy/_core/__init__.pyc": "2761d43f96261c9a41b66fd072865546f5604cbf0945c0c05d7c301590a39879", + "lib/numpy/_core/_add_newdocs.pyc": "95d2fc2346f66e1d0db5c161bbdff7a5f0ef511e03d0ea31ae8259d575492d49", + "lib/numpy/_core/_add_newdocs_scalars.pyc": "bd9d131bb4f69263d3ec9ebbeaccff8b5de5131e6a7f2e5179a72526e3e57566", + "lib/numpy/_core/_asarray.pyc": "ca981d4fb1e3cf75d0a3d4e5bc5b415c96d84c1774104d1eba2fd73d1d720870", + "lib/numpy/_core/_dtype.pyc": "fc1332fd4e846bffda17f78d9f415d4869e646d9937cb1dd799f4e7943a079ce", + "lib/numpy/_core/_dtype_ctypes.pyc": "951734304c07bc4ed6ed83336cd7b63727fd1f7caf8008e17115dc492915e364", + "lib/numpy/_core/_exceptions.pyc": "f344e794128e92a6ba30bc81f195d8570374f1a7dab63be486678e48b6addf25", + "lib/numpy/_core/_internal.pyc": "8dcc375e4f4b25424af9d39747726f30202b7e2793c293f2a8008381f50c5573", + "lib/numpy/_core/_methods.pyc": "7ff6f29d866a78ba4f5a2dd756ec9ab37f3b563b0a8e9542203932b14191931d", + "lib/numpy/_core/_multiarray_tests.cpython-313-x86_64-linux-gnu.so": "11be2d8caaaded5d9d4cb92300c57b679c2a2cf911c5463d53d4a6f342692b09", + "lib/numpy/_core/_multiarray_umath.cpython-313-x86_64-linux-gnu.so": "20940059012771d5b788237d4781e9f65ded45f187a39014bc7a7365276683cf", + "lib/numpy/_core/_operand_flag_tests.cpython-313-x86_64-linux-gnu.so": "d4ab4fa1a47704f5e009b454fb226d79087dec489778d24956f753e6d9fe3009", + "lib/numpy/_core/_rational_tests.cpython-313-x86_64-linux-gnu.so": "12af246c8760f96e9e13a755d0a92c90ad931352d934486f20bb044acd400f1d", + "lib/numpy/_core/_simd.cpython-313-x86_64-linux-gnu.so": "e45758c525bfc1dac5bc020c31be2645d6ba426bc52df27b73a91ddeaf393ce3", + "lib/numpy/_core/_string_helpers.pyc": "2aea3128d3e81ab464a07c3ac8a176cc9bd9636ca5fe920f39ed430eb7e1d76a", + "lib/numpy/_core/_struct_ufunc_tests.cpython-313-x86_64-linux-gnu.so": "2ae3135138340a5cf571be637908f5057ce1fb03345a551bd8f4d77955bccb26", + "lib/numpy/_core/_type_aliases.pyc": "b8d9e0a76a5fcd5180b20fc84619cc2a9d16962a9158af845dcc6dcd1484b4c8", + "lib/numpy/_core/_ufunc_config.pyc": "32c32ee0cb28e088ef9ec821758a089004a3d28e5041f8499b4d7859f737390f", + "lib/numpy/_core/_umath_tests.cpython-313-x86_64-linux-gnu.so": "a4af4f6d4c1738bf387c7157120963d54530363154a2b8edbadbe5d0fee648ac", + "lib/numpy/_core/arrayprint.pyc": "4ea0422c31ab3a227f848d848fafcaff2aa2c776c89b2dc51460d65ee984f05b", + "lib/numpy/_core/defchararray.pyc": "8950d13b397ab697c297e57bb6728449158eb382d01b33ffd9823e074e03f3ca", + "lib/numpy/_core/einsumfunc.pyc": "84f59f9df97f8695504b58f04dc585c2bb8818ebcc4d80d42af2fed8fe712928", + "lib/numpy/_core/fromnumeric.pyc": "e8c8c75c2f28523ea9ca9bcdf64c5cff7293949dd092d14e19dc562d2952c1f6", + "lib/numpy/_core/function_base.pyc": "8c2542674a6b8965b6feea176f7e9ab9713b008abaf0b6d10512d7581fccf948", + "lib/numpy/_core/getlimits.pyc": "151f93fda5e1168c2c4e547dcf4bb0b32233c4318dbb5f11eb85577e631601e4", + "lib/numpy/_core/libgcc_s.so.1": "137f5385f2fc44139b4c28b230e7e3298da51b04da7fccb0ec2e0a108054da1d", + "lib/numpy/_core/libstdc++.so.6.0.34": "f3eb617c6c2b6f14db1e113aee0406afd0c3e47d753eb0e854adc8bf9a4d86d6", + "lib/numpy/_core/libz.so.1.3.1.zlib-ng": "b5d8498c0788ccbed7c7cec20e4c13b952e4a2c902432d72a8e3e594ec4ed3d6", + "lib/numpy/_core/memmap.pyc": "e6c4f20613db6e30acfdf9d29d1ecce0441f7d88804e99e20fa60963a364caff", + "lib/numpy/_core/multiarray.pyc": "1da94c0d86a08cde811dc629b288cbe0f479bac67d1a5cb2477257307d19f72a", + "lib/numpy/_core/numeric.pyc": "a208fa40f3ec695c17ff77eb48554c7729baf71d3438b7f31508451481bc302e", + "lib/numpy/_core/numerictypes.pyc": "4720743b67881b3da9ea2205a277caaa7a8cb2b215c9931be7f7d92606a20a9f", + "lib/numpy/_core/overrides.pyc": "4774195868cb7c2e99032a378e48db4246ab8ad425ba66bbcfc19678f561de73", + "lib/numpy/_core/printoptions.pyc": "33bf65ff929f3539afb55094d849b60af23fef69071834d439730e21efa9194d", + "lib/numpy/_core/records.pyc": "1f7de77758eaa5ca7a72a947982cd7c57c2643415374d9b422f3bf18408a46fc", + "lib/numpy/_core/shape_base.pyc": "abf1b8657de8e9c691a532a558731b6a511c39f1e3e98d7bd9609e2788d806d3", + "lib/numpy/_core/strings.pyc": "ac91b6d6f81b73020dbe6d139212dd8eb09e55c45c5d8b3d6bfede7ac139cc59", + "lib/numpy/_core/tests/data/astype_copy.pkl": "9564b309cbf3441ff0a6e4468fddaca46230fab34f15c77d87025a455bdf59d9", + "lib/numpy/_core/tests/data/recarray_from_file.fits": "340d24962cf7d4594b9d8c6fde9a737abb8e36a35892e12fb6ce70cd711e21ce", + "lib/numpy/_core/tests/data/umath-validation-set-README.txt": "a715b039a1866a169177e0250227437e870bcab0220e9d3085fe610bb858c2a3", + "lib/numpy/_core/tests/data/umath-validation-set-arccos.csv": "c81973f2be919e701885d9686f3186a3614a63e0e849341a3f6eb2f35dfc6b72", + "lib/numpy/_core/tests/data/umath-validation-set-arccosh.csv": "d065deed71b56778d701c2be3a5128b7f0dfdcc7ad0d04a56e6dcc27ffe23109", + "lib/numpy/_core/tests/data/umath-validation-set-arcsin.csv": "c3f4afd8d0e7fa62d9480a9be7a253da0e1ba81cf16008a179d5b11ee7fcdae5", + "lib/numpy/_core/tests/data/umath-validation-set-arcsinh.csv": "0d9acc6286596723350c3c97354c52973c7a6ce81a8e74522d6033c5c3dc93c9", + "lib/numpy/_core/tests/data/umath-validation-set-arctan.csv": "d1aa2c5d9fbd0d84e8a74963e1b7dc04dc1856f8d9756d7785b3114d1453995d", + "lib/numpy/_core/tests/data/umath-validation-set-arctanh.csv": "1c42bd78fc753a42ab5c82a4314574231ae6b03a8896029d76223e2ef176276d", + "lib/numpy/_core/tests/data/umath-validation-set-cbrt.csv": "bfce7931366287e7d9a7f1ae103b2ddaa688b315386bbbe501b788272db12a97", + "lib/numpy/_core/tests/data/umath-validation-set-cos.csv": "d0f3670ea2a4a2467b11154381b7acf0a35973e21226b65495565ce4b916d7c1", + "lib/numpy/_core/tests/data/umath-validation-set-cosh.csv": "24a0b89caaf7c13cc0fd7352890bd552af73918cb8763bedbb6fa3e1967fece7", + "lib/numpy/_core/tests/data/umath-validation-set-exp.csv": "ad401621bbf278a87dacf7e9da7d19abb00aabf9ef1e981b8332e3025961b1e9", + "lib/numpy/_core/tests/data/umath-validation-set-exp2.csv": "763a2c4feddf4e988dfdfff658eba680cbae2a00bf5e1a553be42c505c08eae5", + "lib/numpy/_core/tests/data/umath-validation-set-expm1.csv": "2bb8cbe8de0a4065fbd5f8f986f624cdc31793b32641eb3c170acd7f2acfa605", + "lib/numpy/_core/tests/data/umath-validation-set-log.csv": "ca7cdb55b2b1173c56170c479f15fb1699bebdad3da08de82b5fe54ded7d838c", + "lib/numpy/_core/tests/data/umath-validation-set-log10.csv": "34e043fab39623f14f1b85666f3bb726d5fd500f37f1fd80683140fb06a2a860", + "lib/numpy/_core/tests/data/umath-validation-set-log1p.csv": "b5d6d858fa96233f0111b232925ca787fb69409ce8f7bd0475de1e93a0ec3dbf", + "lib/numpy/_core/tests/data/umath-validation-set-log2.csv": "dfd1140f4bc531bc32a17a0e8600a689de8d78401053b15fed01633ec54e6c81", + "lib/numpy/_core/tests/data/umath-validation-set-sin.csv": "f0f5239d0fd87e6c456f8d9726bbe9be691e4a910e9445d298dbc82b85607c03", + "lib/numpy/_core/tests/data/umath-validation-set-sinh.csv": "5ceb0152e3dc32388efe97af31a96999dd2246fda09a787dbbb6d5f592cb83c2", + "lib/numpy/_core/tests/data/umath-validation-set-tan.csv": "1efd9650c22c71fbd0279639062a6e1e4e28138558e9029b429fe4351742a984", + "lib/numpy/_core/tests/data/umath-validation-set-tanh.csv": "8a895917f30ec964606126be4ac0f875fe669f214ad7cceb20223be34496a137", + "lib/numpy/_core/tests/examples/cython/meson.build": "bae5d53ca7a6355310e4c8840ea4b80578701876bde891e34b9d16c59b894bff", + "lib/numpy/_core/tests/examples/limited_api/meson.build": "60ce51c16ff0685ca69564871610823873ba282927a283748c28aa49c2f48b93", + "lib/numpy/_core/umath.pyc": "8f4fb343068eaa60c4e3b90166b25cf4d08a1094706789bfba0760d0628738ff", + "lib/numpy/_distributor_init.pyc": "18e616343aabceb89974450bb5c18e90d37e178f44b888012dd029f74f967d1b", + "lib/numpy/_expired_attrs_2_0.pyc": "70bbce72f70af2a47628db38a78e0867dbceb75328e319d6d1148a823a8c7e9c", + "lib/numpy/_globals.pyc": "aac7e4f2544c71006e40c20541f55e9b28c74f546b606f625bfbd3cae313af80", + "lib/numpy/_pytesttester.pyc": "b5e2722eed9df62f6e27aabf48689dcc65a1736daf0cec762ac3f1808c6ee0ff", + "lib/numpy/_typing/__init__.pyc": "51976eb1fe1d937c8f1f118f44f983d4a5c5484d5f58c66a8af05c2546897c5c", + "lib/numpy/_typing/_add_docstring.pyc": "914a917327b33ed85cfa739e33e8db0a012dc792873f915a76731655cb39a46a", + "lib/numpy/_typing/_array_like.pyc": "f52328dfacd78b927fe771e618602983665f0a0b1c45c630f9541db67489b730", + "lib/numpy/_typing/_char_codes.pyc": "e900e7d8c5145431572e11410484d0b2f7f76e0ff7989ed2681cf6d1202dbc54", + "lib/numpy/_typing/_dtype_like.pyc": "57cb2dd6afeb3fdf05d99a7edc6dc516612e5c9078369f82565d15315d51edd1", + "lib/numpy/_typing/_nbit.pyc": "0feace3ecab8cbae16750137cc06365751b286f46861565b979df59be7bd5b29", + "lib/numpy/_typing/_nbit_base.pyc": "a01a1f9ad2e50089bb81eb108c302135103277da2d0ee26678f0e39613476f7a", + "lib/numpy/_typing/_nested_sequence.pyc": "1e4a8909fe4c258b07e417535ec3fa04dc18f20dbabe0cd09ebace840c6fa64a", + "lib/numpy/_typing/_scalars.pyc": "2ca858733e40fe5626cf455f29570c6bced7f1c5b163b04e2511affed46a754f", + "lib/numpy/_typing/_shape.pyc": "1756991398d34bd28f96537a75b315960495927e9b9aa75237b1b30974032406", + "lib/numpy/_typing/_ufunc.pyc": "b038502b1ce65b6a82ff8d9afdeac635557d62040f22b00783bea71fad8cf71b", + "lib/numpy/_utils/__init__.pyc": "e8081478f782a0c491c7defd4094a31bdc3f0ff84026353c975def64a5e79ec1", + "lib/numpy/_utils/_convertions.pyc": "6755864e0307ae56ee79385cfe3925557fd77581626148361a24c668616fe624", + "lib/numpy/_utils/_inspect.pyc": "8e9de982535a06076c1a1550d1ab886ad14e94c60edb5eca74862da8ced0a7e5", + "lib/numpy/char/__init__.pyc": "f7f4aa19c7e10fd000217a5165f149381e3c216e1b6c98a923d32e2031117ae8", + "lib/numpy/core/__init__.pyc": "06309cac2efb42ca34bb439e1129fca20d81e0d8d0fc97bb6320abf22395f081", + "lib/numpy/core/_utils.pyc": "a95be52bfff0a6dbd791b661692ea2791824642f01429f62337119bb3821f440", + "lib/numpy/ctypeslib/__init__.pyc": "aac5e5036edb8abc7933605dd43244d1aa52971dda08bd58b967e87b212d5200", + "lib/numpy/ctypeslib/_ctypeslib.pyc": "c2d3657f42aefc02590d42e356fccca59edf82e9455aeec8f9505424f7ab8100", + "lib/numpy/dtypes.pyc": "6e1a96f7044e3ec605c40fd1ea2bbe33765719632242ba3f95767a684fdcf9f2", + "lib/numpy/exceptions.pyc": "3c6dffa11f46e3cbac539a18849b0f58d1d7d3a7c186b8710b6af79a31c4fb8b", + "lib/numpy/fft/__init__.pyc": "513d14493c2a4d77a09c397cc23b241af77332b2a94872357cd081c89c77b134", + "lib/numpy/fft/_helper.pyc": "320d87ff22f066492008c35efabcfabaee94793cef82be6e93420043b7dd360e", + "lib/numpy/fft/_pocketfft.pyc": "01e96e62adecf0246ce047f417582963938b4c1a3e6fbb71a307184bc3f37432", + "lib/numpy/fft/_pocketfft_umath.cpython-313-x86_64-linux-gnu.so": "dd31cb2498792214ab9ec3e2ce24cebe3f5418d91735493e5a81ad3f5701b224", + "lib/numpy/fft/libgcc_s.so.1": "137f5385f2fc44139b4c28b230e7e3298da51b04da7fccb0ec2e0a108054da1d", + "lib/numpy/fft/libstdc++.so.6.0.34": "f3eb617c6c2b6f14db1e113aee0406afd0c3e47d753eb0e854adc8bf9a4d86d6", + "lib/numpy/lib/__init__.pyc": "10e4c208dac670fe9cfd623b6770d44ea8e2ee59c969bad34fb3647a0a88cd60", + "lib/numpy/lib/_array_utils_impl.pyc": "b25af46750053f8efefd1a87d024b78db03a1c297ed576a56a68ea848f0bd0ee", + "lib/numpy/lib/_arraypad_impl.pyc": "5ede93f349374092b5482124622b1c4c03b2593cc3eed68af10ae7b19cfacfbf", + "lib/numpy/lib/_arraysetops_impl.pyc": "963ae864a6d22340515c33526b08dc3cab9f5703174828ca6f701999437b1c09", + "lib/numpy/lib/_arrayterator_impl.pyc": "7bbdb6c498377d31c82e360e4e024bb3b33373abad4c761f595bdec4488afe33", + "lib/numpy/lib/_datasource.pyc": "3420526ae244c17b1e984983eef40a26a8c3649fc13ee2af99d2c6e723fdfc56", + "lib/numpy/lib/_format_impl.pyc": "4dc720dc7eeb525fbfcda9746a0ad84f74fb8c02c0321c93ba9d385f894c6e6e", + "lib/numpy/lib/_function_base_impl.pyc": "382237ab7643912d5e760a0d64e17577c29d9dde12125f18d70563e4e04e7e4f", + "lib/numpy/lib/_histograms_impl.pyc": "6096f6d07835e244da811a380f513c998170041bbcf0d7d2adc449c55c661aab", + "lib/numpy/lib/_index_tricks_impl.pyc": "74bb133604ef10492af15ec36feb3dec5565f813cb633dcc0a96517499d30128", + "lib/numpy/lib/_iotools.pyc": "ad023ff00ff578c30ed4b369926369eac5e527baa0a08a3e3ff126f9255e21fe", + "lib/numpy/lib/_nanfunctions_impl.pyc": "26044dc554cb540cd14c7114ecc0218f6f8f87897ff4f1e28a5c89549cb0572f", + "lib/numpy/lib/_npyio_impl.pyc": "99401d6f64c65f0cd656ebb6c3f3e7f80814c0393044b631bdb5fe0b78d0cd07", + "lib/numpy/lib/_polynomial_impl.pyc": "5ccd1cad5d415753e321eca2afcfb19e57cd4e7f354808d62df305745dd74d8c", + "lib/numpy/lib/_scimath_impl.pyc": "b60903f725675414550cbfe8cd0b92a7230dbb30951d2c69c4aa09766e2a6084", + "lib/numpy/lib/_shape_base_impl.pyc": "bbfce42c11c1aff85eb299c4c84a2dbb1c55a051fc8e9874eb7a45c69de1e272", + "lib/numpy/lib/_stride_tricks_impl.pyc": "f89f9a3de8bf8ede353e368800243d27cb4102c3c72145bf918f6cf133ade9f5", + "lib/numpy/lib/_twodim_base_impl.pyc": "f6d18caeebf477fa9e890b0db7851325d55f99dc6fe6dfc22d878674c1527f32", + "lib/numpy/lib/_type_check_impl.pyc": "c2ff265e299cb0bcf07335e7645bd91130a310dfa46645874f05790f37c0072b", + "lib/numpy/lib/_ufunclike_impl.pyc": "aa397a7ac276ad46b496bec6865c235137d2fb5be38b3ea949924912cf08d519", + "lib/numpy/lib/_utils_impl.pyc": "4fbb5f57b19c5ec369e9a6ef26277f6fb62ff6e879f1c793a52891ae2e8ac88f", + "lib/numpy/lib/_version.pyc": "c59720feee99e14f483d9611905e4254fa21243b8e063fea856c5bf827937d53", + "lib/numpy/lib/array_utils.pyc": "8e13982ee30aa209cdf964f2f5be85c630b305eab2179d84362e53977c6a48a0", + "lib/numpy/lib/format.pyc": "cccba2a12e20f67dfde57eea448e1fd2a7e79be8ecec7439e409d484d811304b", + "lib/numpy/lib/introspect.pyc": "8e20a55860abd8345be7b02a8c19931948ac0898a149176b8a756a9de15fa340", + "lib/numpy/lib/mixins.pyc": "b96bac1068f6031c1e74ecedb0dd9ec7122880b90ea8bdaa3219de27acd0a72f", + "lib/numpy/lib/npyio.pyc": "4c2b643f9a2ef5163c29afb9686fd718ef92198f15b538cd3e10d045b38c0330", + "lib/numpy/lib/scimath.pyc": "73aee0a3e8b670a2ed60fc534a984cef5a4649dfb96925dd7de6fd4115c7a7cd", + "lib/numpy/lib/stride_tricks.pyc": "82d805a08b6d6107ecdfed97ca57c4142984a1620d63436cd7a83abcc9ffe4da", + "lib/numpy/linalg/__init__.pyc": "4cd4f7e6730567b5147500042087a6692c89b8f1a0c91df63b57acb6baa18df8", + "lib/numpy/linalg/_linalg.pyc": "c973f65bd929ccd935550f86753d3a47ef0d9f748a9587dbf7167f4364334e24", + "lib/numpy/linalg/_umath_linalg.cpython-313-x86_64-linux-gnu.so": "5639a0ca5c9b92ed7d3c0e77bca0ec1d79155d013f4d937ded46134e0d02e091", + "lib/numpy/linalg/lapack_lite.cpython-313-x86_64-linux-gnu.so": "9fee4f796fa048898652dc90ae37d34084746b0b54f6f665a20f6b39f63f6e84", + "lib/numpy/linalg/libgcc_s.so.1": "137f5385f2fc44139b4c28b230e7e3298da51b04da7fccb0ec2e0a108054da1d", + "lib/numpy/linalg/libz.so.1.3.1.zlib-ng": "b5d8498c0788ccbed7c7cec20e4c13b952e4a2c902432d72a8e3e594ec4ed3d6", + "lib/numpy/ma/API_CHANGES.txt": "17fe235bc5f971805bce9730b5eca69289d39afce028a636906ac717502d9eb2", + "lib/numpy/ma/LICENSE": "05f3b88351988ecfad10abe92c0c50e5875c6452d5009a0084cc291551ffcca6", + "lib/numpy/ma/README.rst": "92b7f672f54aff33507f5777c95630834b831f34e2478bc76ebf75cf0680ca82", + "lib/numpy/ma/__init__.pyc": "b7b154b2286d7611b7bf301bf8fd8251ea45369cfd5b8a86eaaf6c2e00768e9b", + "lib/numpy/ma/core.pyc": "9d85c1ae24ef3f0d2153ec28fcac246003a0a35888b0828c435f9621a73d7d1f", + "lib/numpy/ma/extras.pyc": "3b460685f1911c672ceecf39352b3970bd3ba20025553e22719f8994557c790d", + "lib/numpy/ma/mrecords.pyc": "65c3877b7602ff83c3d0abd81a35108b71deeac3b4f39614de1cc74287afef0e", + "lib/numpy/matlib.pyc": "756daa3e71486c65560aa5bc13209f1eb7c4d20b5eb4d1f74028d16e16c530e5", + "lib/numpy/matrixlib/__init__.pyc": "8b201550ba35a259e63242a676abbeea82408a0342e72a3a9fea1043f2bf3c56", + "lib/numpy/matrixlib/defmatrix.pyc": "7acf739b62bb58195e210c99592aaefd58485f0fa97de29f17fcffde25571492", + "lib/numpy/polynomial/__init__.pyc": "ce14eddabeada136776461aeef702419c77021cbfd368983050ef57809cad16f", + "lib/numpy/polynomial/_polybase.pyc": "67477fd9dbb43c08cdb59c75c34e4c3f3025f62134d6e461236ef28f39dc21f1", + "lib/numpy/polynomial/chebyshev.pyc": "263d6a8c2fa641f4b7594c80d697c84888b741134865ecd194687f69cd538fb6", + "lib/numpy/polynomial/hermite.pyc": "ac8a5f7913b950b2dd61a313610d49e6b5e186b66c69c7d684c7fe57d9e8b4b3", + "lib/numpy/polynomial/hermite_e.pyc": "f52afeb484e2aafcf7626d8ddd9082d54f86dcf20c316639e1af61c079f5c28b", + "lib/numpy/polynomial/laguerre.pyc": "f5538930fe9070a2263cbe7c8c0e838534444d44330aad38ea4075eebbe27465", + "lib/numpy/polynomial/legendre.pyc": "b894e5ef9c39c6b9e011ded9b026bb0bfcfe2a4b690b0c4d68e4cea7c1461c10", + "lib/numpy/polynomial/polynomial.pyc": "2e8fa5aad5d10fc490ac3e2de6dfa6cf35f0a28eeadd7e5e9a54ed2f2b05ebda", + "lib/numpy/polynomial/polyutils.pyc": "0cffadebc90f1590ff44f963c2de28410c8328305b5dbea0fa6779fa0ff40527", + "lib/numpy/random/LICENSE.md": "103166b62b80443afb9eb3488e052ea06be0cff566b908f199e561fde49af19f", + "lib/numpy/random/__init__.pyc": "85caf953acb6cdc6e3a5f6fd4c87cca2b28acf471918a12aa657612cca780802", + "lib/numpy/random/_bounded_integers.cpython-313-x86_64-linux-gnu.so": "4207eecdda788292bd4cea616f81d7b50d2f677658432ac9fbb8e5f58819dccb", + "lib/numpy/random/_common.cpython-313-x86_64-linux-gnu.so": "e3932d8b44ed4847257e87397dd3ad12e3fab19ce9aafa69ee184c59f0388177", + "lib/numpy/random/_generator.cpython-313-x86_64-linux-gnu.so": "1062c4b545a4d3a04fb15d4ee0d4c877b45b9583600aab7745abcf438a40b94c", + "lib/numpy/random/_mt19937.cpython-313-x86_64-linux-gnu.so": "76da76d6cfb50e1559417861273d9c6d9b4214f86f9322ae5199bd21ae507669", + "lib/numpy/random/_pcg64.cpython-313-x86_64-linux-gnu.so": "424dac00b22272be82581f7db30cb6390d0ab8f9315a2877201e19243f553b94", + "lib/numpy/random/_philox.cpython-313-x86_64-linux-gnu.so": "8a65b68bdc552f2701ce7c51eb8ed57b560153d78d41867e5a3aa923edb6594b", + "lib/numpy/random/_pickle.pyc": "85a6d9879b6bbf46a450b71128a1611d1d47e14442350a583b46f055d628dafa", + "lib/numpy/random/_sfc64.cpython-313-x86_64-linux-gnu.so": "ff4b7acde2f14da301f34ca00777acb61a8642188f97a74dd8448981a7014f95", + "lib/numpy/random/bit_generator.cpython-313-x86_64-linux-gnu.so": "88c847a4e3ab889c0b4111f8dee8c32367792672b38ae1741233601a3d09539a", + "lib/numpy/random/lib/libnpyrandom.a": "b9d7d11751ddf00f1d7d5384821dfd89cfefa78a2aadf5e07e6185d6070bfb6d", + "lib/numpy/random/mtrand.cpython-313-x86_64-linux-gnu.so": "fd0aa848f08d1f54f47aed1aaa019a363522e48d0cb7efe883f887c5dc7a3be9", + "lib/numpy/rec/__init__.pyc": "0bdd544df71bbaac930045c1549ee81f761b0f44cd52a5d293fa50b3a2b1a724", + "lib/numpy/strings/__init__.pyc": "ae93edacfec719d6191df76787d9efe0e1d07dd6b3bbdb2bb23182c49dba7d6a", + "lib/numpy/typing/__init__.pyc": "58160116bbee6d8da78c2f27f082e77fab32a6b774504a3713ed3d128f309afc", + "lib/numpy/version.pyc": "7e5b89eb8ef8ea1e7a29d3af65df42a8313900a36fccc22d44c3d92446e9b61f", + "lib/numpy.libs/libgcc_s.so.1": "137f5385f2fc44139b4c28b230e7e3298da51b04da7fccb0ec2e0a108054da1d", + "lib/numpy.libs/libgfortran-040039e1-0352e75f.so.5.0.0": "e725607dd70cf725c018b38b944bda70bc6d7cd7b5cc74918888cb1ddaf3bfd3", + "lib/numpy.libs/libquadmath-96973f99-934c22de.so.0.0.0": "6ed5137f412781ad7863439fb543613f620b43c32b63292a0029246162f5bbc6", + "lib/numpy.libs/libscipy_openblas64_-fdde5778.so": "628706f08ff8c397ab630f392eba478a4ffb2d10290382b120c98486937663c4", + "lib/numpy.libs/libz.so.1.3.1.zlib-ng": "b5d8498c0788ccbed7c7cec20e4c13b952e4a2c902432d72a8e3e594ec4ed3d6", + "lib/packaging/__init__.pyc": "e9219105831b35436d85370035acff10778ff4cb8ff57244edad208f68448925", + "lib/packaging/_elffile.pyc": "187b07230620ca43781b71e30d41448b472048830a5c623516600d130c00bdcd", + "lib/packaging/_manylinux.pyc": "44f193526edb18b2b97cff690c7fb2e2da2be39b8b9ff54f639f419110952746", + "lib/packaging/_musllinux.pyc": "32a7ebd23bfb17b16d141fd8760cb30b323422942b449e962749355d53944784", + "lib/packaging/_parser.pyc": "bad2526defaeb32fc5aa072d1914536cf5822c17c0a878d5ac3f8ebbea45e77a", + "lib/packaging/_structures.pyc": "10c89c665d31c4281c9899665ffe68ca520f5053dcd5a3c6d5ce568623fceb73", + "lib/packaging/_tokenizer.pyc": "0d49810ff124a04403d239dc290e2b35a99e884a0a9ac32db6ebfa57ffd75950", + "lib/packaging/licenses/__init__.pyc": "511e85848e4a2ca4dc54bd68cecb40157bc3664745e1fe71df7d9683f2cfbd8d", + "lib/packaging/licenses/_spdx.pyc": "e768c09a8844ae8c8f6289a3a58fd4f61900696333f27ab46e435154863f99b2", + "lib/packaging/markers.pyc": "373813498faededa2d1e8b6edac54d08a5616905cca3011f488379671631eefd", + "lib/packaging/requirements.pyc": "5fe8e69904827462840d0cf7717223ae05da076e736e2bb01a183691548631ec", + "lib/packaging/specifiers.pyc": "644b0d8117554964965923bf9bbf8c5b3db9ef05fb1d031944f010d4f59b3b0f", + "lib/packaging/tags.pyc": "d47374edd751e5eae81829cbd6fb2bc2a35d91871f0322c5199a15f26b1953fb", + "lib/packaging/utils.pyc": "b5bf9583706d653cd093bb1955c40b3fa53bc99a558ba7e19d97ebc425306458", + "lib/packaging/version.pyc": "e903aad86214efbc99e97fa67f09801b0e1dbeafeffe8759b9ad20d3c78f4cd5", + "lib/pathlib/__init__.pyc": "00e86247c331ce78b1aa77c2adb4c45c296cc17452a614baf55568c9b7937b32", + "lib/pathlib/_abc.pyc": "286b7fea455fb24bc2e5159dca1e0972d79d5f4d3a1926b4886ee5b485f2f8ca", + "lib/pathlib/_local.pyc": "2455b17e044e7f683ac2e7e6ed8f6c157b58bad33ff7e7b5167220c73560ddee", + "lib/pkg_resources/__init__.pyc": "a6c037a2b0f0b55191aa0290536c8c070b2b750c3695e3d0ae7b7f4f953c32ad", + "lib/pkg_resources/api_tests.txt": "5c476fcb88a01c7aeadaa34734c1e795f3ba5d240a36a3b22c76e5e907297c02", + "lib/platformdirs/__init__.pyc": "0ca08fc90613ee2f870cc4adf34dbc075159eb99300243b484d849fa3a8ca3d3", + "lib/platformdirs/android.pyc": "8e979426ede720da5f14dbccc900f5c88ebaf6de2c7d50d6bda8d73c4c03c975", + "lib/platformdirs/api.pyc": "4b73f691b8ef897040720c8bb34588108adbe8e4ea906b75690947893c49bc43", + "lib/platformdirs/macos.pyc": "afbab25058ccb6ecf4af6cead531794b86f4706c695a718511cdc419e26f8acc", + "lib/platformdirs/unix.pyc": "63fc1f5f293d88ff30597aa03f6bb776b5f38114788910a574fd0eccf1a0c2b1", + "lib/platformdirs/version.pyc": "8ed3c8401808898027372450f279f82ba8fa6ccf4b33f1ea1b7c53f7d0ce2cc9", + "lib/platformdirs/windows.pyc": "4478630fe6b7fee6dfbc637ba05c9ce197fe68fed3ec7f8968484ab22169df6b", + "lib/pluggy/__init__.pyc": "0e0fa1fcccc1a82b3347d93c25653ead33ad84c8776b27bd89e118bdafaaebc1", + "lib/pluggy/_callers.pyc": "b43cb06d03c7bbcb995dd164512f9de4954f3c49c8a74ccfaa3ff3bee4037d55", + "lib/pluggy/_hooks.pyc": "fbda918abf93e38441aebe8a188e91ab0ae21b106d58550481b6a5a054bcf167", + "lib/pluggy/_manager.pyc": "8dbbd4292b0e214462c598aa5427484efd75702255ea53f39c70cdb23e7faa8c", + "lib/pluggy/_result.pyc": "79dc65665553e2b8b1561aa5bcfa916838891142095692402892d19a6fb1a706", + "lib/pluggy/_tracing.pyc": "fde5eb7e859f442c5e72fac4b424f3b505f4df4cc03f53fc92d3735b7cad086f", + "lib/pluggy/_version.pyc": "1826b2c4ff36752e19faf5134a27b5c0c3008d059a0f6d591ab9e81815806b73", + "lib/pluggy/_warnings.pyc": "17997cd232ae8ce72c7fd44b37230e0611a7dd09730c7537901bee5a8598b57c", + "lib/ply/__init__.pyc": "0e0b92b375b8b9e30c44d8519bf1f2d10efdf10a3b12a907f0b4cb9da55a8ce3", + "lib/ply/cpp.pyc": "05d7b48b3a984c897c6a7ed510ac5e26dc88fbe74978fda65c9cad43c2638c38", + "lib/ply/ctokens.pyc": "1c4755602ccfc100bb9e30db7b62e972d9501087b4cbcf655c394b2cc22f167a", + "lib/ply/lex.pyc": "575b186b80559cedbcb06df3c4cfacdcabd6760267e30f00f3354b72e084f9bc", + "lib/ply/yacc.pyc": "14f3a654d3eadc14dde8e9f38dfb0417f2c8204a6c514c397ee3d3022a60e1e6", + "lib/ply/ygen.pyc": "f596e9dfd59a10d71227234977d5caf73fcf53fc16d6057b767d2f601baddd1f", + "lib/propcache/__init__.pyc": "5b1c19100879205e26e5be6303235c3576d32bcb762f820a1111c0aaba1556a6", + "lib/propcache/_helpers.pyc": "f2ad2dd490d1227a18538441f6f6dc8ac688e91d6e50424d8bbd792921fdc536", + "lib/propcache/_helpers_c.cpython-313-x86_64-linux-gnu.so": "7044309284f4d9f5cce8c819460e6911e840d07ab30d1fca087795b2f70f53a9", + "lib/propcache/_helpers_py.pyc": "01b89769a0c76c8798f3f1650bfd2b059023967b9251a9987949ca004e30e136", + "lib/propcache/api.pyc": "5a128c4990729c78b89c89ed18beb00a6e1ef35136d257cebf34136c61b79e1f", + "lib/psutil/__init__.pyc": "99130221ad3c42549a34e01367c47391f8a5fcf9faef5dc0f22299daa5483555", + "lib/psutil/_common.pyc": "a92e7ab32fe9f7a4969366d797bfe3cbafdcbfb08e3d951816e876d046cf1242", + "lib/psutil/_ntuples.pyc": "d949a5f6061b05a8e8510f609ea08c3300e93c1c3fd20a3213e3cb58beed1ef5", + "lib/psutil/_psaix.pyc": "051a02a3026525bad84ef29fa81053e58d35542180493a8d4b456d3570a96bf4", + "lib/psutil/_psbsd.pyc": "2b3d326c17969ec5939ce5500c6b5a83be31a93cf20a43f966ed9b685adf9e54", + "lib/psutil/_pslinux.pyc": "a9d916bb91125563bb2bdf036c7ceba0bf8b7c1cf373b5b8f717515132a2952c", + "lib/psutil/_psosx.pyc": "ef30bc1b62fb154e60597116766d98a0fba2157cf044d99bc1cd58286a0c048b", + "lib/psutil/_psposix.pyc": "8afc71bb2c2d8e0884a46538f7c967b275ef6c5a130d4256674df722c45b5819", + "lib/psutil/_pssunos.pyc": "8971ee9d52cdab2524046d92ea3eaa4448ca77d0e93e7f144cd35e759da31478", + "lib/psutil/_psutil_linux.abi3.so": "5882b762a1ba1f86d78f0546484d2d99c21aa1baa94c571bb89109d3b1c1c906", + "lib/psutil/_pswindows.pyc": "163ffc3ab41798a951d0e4da73d707c2145c74f6873a0d7a9f8313dd4c593b1d", + "lib/pycodec2/__init__.pyc": "3ad1f8807a294e84eebe9272b400f2064e2831e9820f77c97763c9ca2df51318", + "lib/pycodec2/pycodec2.cpython-313-x86_64-linux-gnu.so": "c691c2e291ab7a561c52731bf17c6b8479e69f6cedd176b1a5836094ecca2267", + "lib/pycodec2.libs/libcodec2-30fce438.so.1.2": "3453c1cac697701e680e521d03a9d51b4868416e5a827646fdc8ac02d196249d", + "lib/pycparser/__init__.pyc": "3386d4386f88fae0e7a454b69f98349cc4c8e6be099a65318b3e85cf963ccb0f", + "lib/pycparser/_ast_gen.pyc": "62fe3e4cddec1a9bed5bbc364657fdc9291fb0945e7d481f6b3731b52fc162bf", + "lib/pycparser/_build_tables.pyc": "525cfd8caf318c22133d557cb63e7c1e1160a7786525c6ddd68e78ebccb0c3c7", + "lib/pycparser/_c_ast.cfg": "95de5ecc4f72cc82452150147f0edecc94a5322e275ca342cdf9aa8cec904cda", + "lib/pycparser/ast_transforms.pyc": "da70858d4e9eebbb9bbc01c21975814e2f54c455e054a47e37f949b02275ca19", + "lib/pycparser/c_ast.pyc": "ce057e1895f7aa89785b3b5d5dc5a25c4b4892fe63d52e442df1a50595a307fe", + "lib/pycparser/c_generator.pyc": "54bb3debe6cd184dbc66907b9d6a74eaf4086281c516e9e651d69a1a703cf61d", + "lib/pycparser/c_lexer.pyc": "13cb26326f2a137f15184dd9dfff116b107803a374c040dfa14d3762db124e1b", + "lib/pycparser/c_parser.pyc": "c666b84488bdf41ef6384c942e878d6296b0471815d50fe84594c33bfc52b64b", + "lib/pycparser/lextab.pyc": "48f2d43e8e8b5d2f8485f88e0fcb5c818aebc41eadd3d29678f42c93aa38ea40", + "lib/pycparser/ply/__init__.pyc": "bea2cd1dcbd9ccb9ec0c032f6c621663baa0742a8a55e45a612de9db67c1acd6", + "lib/pycparser/ply/cpp.pyc": "c896555a4b8d53e9ca3d0c50eb2eae60916248042a6899e0562563aa5e28f813", + "lib/pycparser/ply/ctokens.pyc": "3850e9692a2f4b50f3838db77a77045e8821472d3b5196688b27c0b32052db9d", + "lib/pycparser/ply/lex.pyc": "699252cc2e0e916534457305d8229e22d8fa732fd0692f34e930d7549b72c3ad", + "lib/pycparser/ply/yacc.pyc": "e93faeacbd9995e1057ae11c5f0d29fa2835d21fc2f01bf0bd359d363ce0c266", + "lib/pycparser/ply/ygen.pyc": "9fdbf5e69d0e8d0c0a20757dc2f12a88ff68bf5bc7f66aa296d249978fa97e97", + "lib/pycparser/plyparser.pyc": "e9f2be80505aecfc0d1e3966444add367577fb6c8e47d7f50eb9d8d732761d3b", + "lib/pycparser/yacctab.pyc": "02ed2d97f180ae0e27ab6711a96bbf7a6984393c616180df2f87ae5eeb5168aa", + "lib/pydoc_data/__init__.pyc": "55e03b3265e793993411e1785afef3b787781e0e29fbe4cbd72eb0ac0c505b37", + "lib/pydoc_data/_pydoc.css": "038d4bf51b4d373284640f3658d70eaa856def24d8d02b8e29b289beaabf1cc9", + "lib/pydoc_data/topics.pyc": "80fcd8c2baea3fa596720ccb74918aaf41112a0739fa71543584b736b1e195b5", + "lib/pyexpat.cpython-313-x86_64-linux-gnu.so": "e023be7ffb4bbbdfe8441948c4ebf28c90c4aa0c54eb028d12e593ccfda276e6", + "lib/pygments/__init__.pyc": "9925d7e490df9aa5d4d4f7be82a708df4f250cf29bf557cf8b0427b0c19b1f22", + "lib/pygments/console.pyc": "b3873328a5dcb6ef6465871076694d5ccd160ecc5b53a2fbdc664c12e26aeaca", + "lib/pygments/filter.pyc": "489faaa0de666685906c67efd5285d90d6ad215d495f80ca2ec079a43de625e6", + "lib/pygments/filters/__init__.pyc": "b9b16ece9cb668bf4720bc8537d477419520df8bf795f0f8b356bb15453b9e9d", + "lib/pygments/formatter.pyc": "7d63da1ad458c938776df49149459fe8d28a4ff9a73ef9b259342ac9c0b4033f", + "lib/pygments/formatters/__init__.pyc": "b1e24b0e40f7201228cb6297fb7198d43f59cc848d4792f8f75b3447995f4dee", + "lib/pygments/formatters/_mapping.pyc": "e38923f5c887fe2154f70a6a157c74c4709e0c6136df0b321e0be7592a442768", + "lib/pygments/formatters/bbcode.pyc": "4b16606370fc89080174fe9f096f5d6424e68087c8f54f34a6ff538f30b409e3", + "lib/pygments/formatters/groff.pyc": "3632564647a0536759b43ddcfff28a300b21e6aaba640f8edf1be37f8f302453", + "lib/pygments/formatters/html.pyc": "f9e9463e61576860ba4389dcff7300c2b3196d2c2ece9ea55f3eabbc0aa4644a", + "lib/pygments/formatters/img.pyc": "ef55ce521747fe88a2f96af6d04a663884a7866a00a7b97a05e8b4de87fd46ea", + "lib/pygments/formatters/irc.pyc": "1be805bcd618018ec22c3d12dc407b52e3fabf1b8888da3038abc20784067721", + "lib/pygments/formatters/latex.pyc": "9f9a66f40702c6790bd103bd2402b63b64d2657880f2b7abf0635d26eb69d3e7", + "lib/pygments/formatters/other.pyc": "626abf7fa9252f9738cc48e44cb4fbb658206523e249edc2b851893e3087cdfe", + "lib/pygments/formatters/pangomarkup.pyc": "c6cbdcbe725f663027cc97fc8e2f4a0774efd9f995d36126dc7b85827d04043e", + "lib/pygments/formatters/rtf.pyc": "3e1139c2b351e19d2c0a47722e5820e32b69f0cee72539f55e3b9e62a491cd8a", + "lib/pygments/formatters/svg.pyc": "9b682049bb513391a87570ba5a1a596c49962f1720404b80063f82e69c268cd0", + "lib/pygments/formatters/terminal.pyc": "3583c850136447edcd0b9f30a02a3883b17b8b2b11dfa183977d17960555665a", + "lib/pygments/formatters/terminal256.pyc": "37c26b832eaeadf81ae1f00d339c9c50988dec9011dda8a23fa8156b79e0d5a5", + "lib/pygments/lexer.pyc": "47df7e0139b8eca950ae61f4cdca449ac8abb85fc8f023f2e3d2952f72a8d235", + "lib/pygments/lexers/__init__.pyc": "0ab92e72379eb4b33e42e9414e872a0ee264c6f68602736b4917a6b9656728c4", + "lib/pygments/lexers/_ada_builtins.pyc": "68d5b2cf9d3c3d1cc91e48b70a8b61e05f808326a0097984d676109a9feb8b3d", + "lib/pygments/lexers/_asy_builtins.pyc": "3da4406454f5c35ba9361248e23df3953e5ae1085b8fa1728a7ae72897ed3b1b", + "lib/pygments/lexers/_cl_builtins.pyc": "000b53d8fefd283d17db4ec084ff2d56009b9534fd9f8e2a15dd273ed1101666", + "lib/pygments/lexers/_cocoa_builtins.pyc": "a62e025198a41ea19c6731bf72e2c852b25ad656656a31baca7d582136de6354", + "lib/pygments/lexers/_csound_builtins.pyc": "1060d85d1f14a0eddd1aa965942a650551ee9860d83e8633186cff4455f48e8a", + "lib/pygments/lexers/_css_builtins.pyc": "f8a5950da21eee72aab62513fa146bb03d7fd179710b8366684b864dbec3f81b", + "lib/pygments/lexers/_googlesql_builtins.pyc": "d04d1f9595935622b150b702cbecfce63ea50fbcccbc907480c0ef9a57c9f69f", + "lib/pygments/lexers/_julia_builtins.pyc": "5ae3ecbb3a6f4e620f1e13b0b86052b08eee1ee538262adc8bc667170ef56007", + "lib/pygments/lexers/_lasso_builtins.pyc": "e12156f9ef8c0206e7386ec15b4e9871d7f87e511677e3fa7606792e1ad12bd3", + "lib/pygments/lexers/_lilypond_builtins.pyc": "3e3101fe21809275298b55c223553387ce1c9b190a6050b36da6d7455a9905b8", + "lib/pygments/lexers/_lua_builtins.pyc": "6c395e89bb8be3c9749968b896cd9bb674c411cf5f4d622202c752ec96247647", + "lib/pygments/lexers/_luau_builtins.pyc": "68672f33dbf3e34624559b69f528c838f6699e091378b227fbf4397d6edb14a6", + "lib/pygments/lexers/_mapping.pyc": "545f8989d4358c196c821d63c424f07c1ce0317d89f1d88838c239f86c4d33e0", + "lib/pygments/lexers/_mql_builtins.pyc": "fff90bb675847d2abfa103d2478f3103a0b244d414628a4b0ef3399aa8f13764", + "lib/pygments/lexers/_mysql_builtins.pyc": "5d44cb1d66dd4e071cd30ce613eea72152705696f084e6119275e6dba6f22c66", + "lib/pygments/lexers/_openedge_builtins.pyc": "4ccc1390e39b1b9edb83b69568c02731e284db6f76423dd4c6586f6ca07063d1", + "lib/pygments/lexers/_php_builtins.pyc": "36c3c787a20c191ea3a116189f797cdef8ef4fa1dae981b97d2e358feadd13e0", + "lib/pygments/lexers/_postgres_builtins.pyc": "864db4185b2a0a1b331115169133f72e247c655464b04549d994e4e3a7c78c9b", + "lib/pygments/lexers/_qlik_builtins.pyc": "d1994e4c235b0f0deebaacd40930a272ba54059dff83ce969e8191588d67cc42", + "lib/pygments/lexers/_scheme_builtins.pyc": "13f766a55037b7a2bb840e49f091c6dea007a0dca6bfd99a28ab3e43e75a2eda", + "lib/pygments/lexers/_scilab_builtins.pyc": "4d81330296f4cea7df6b32d3f3d1620eabc58e9ba8d2cd03ebf230c14a319f54", + "lib/pygments/lexers/_sourcemod_builtins.pyc": "a12b8cd2814b3a3c2276e7693878ad5bb466461dace908283e6917a2a993f873", + "lib/pygments/lexers/_sql_builtins.pyc": "41ec9315ec9de15870a0349428f77f45083bb87cde3a8089adfa28558ba57182", + "lib/pygments/lexers/_stan_builtins.pyc": "007ce68ebf26eb88e44e468a1e66a630fa053efccb61035834eebd4f59ca83a6", + "lib/pygments/lexers/_stata_builtins.pyc": "fd15c883d5c267faf0752d95083f17383e1667f724615b4c57a53a101bd69d0c", + "lib/pygments/lexers/_tsql_builtins.pyc": "0ddba5a4777faf43c96521366cecb266a354e036827b960e4440843d8411ec6b", + "lib/pygments/lexers/_usd_builtins.pyc": "02cc569794dd7321f9b245779b298ed300066f6edba54285ab5194c0d1f1b45a", + "lib/pygments/lexers/_vbscript_builtins.pyc": "a16791e68655ee8d297380b1ff40558b89a9924aadee1aa6f93322a282920f7d", + "lib/pygments/lexers/_vim_builtins.pyc": "1a972f57a3d29269e492a2c7e5d03ce78cc69accc672c1915e521cc8473c6820", + "lib/pygments/lexers/actionscript.pyc": "9431534c5ea7d1609b05cf3d413d3d29014bc1ed0f3766310d4380ebd4dcf02a", + "lib/pygments/lexers/ada.pyc": "d5323f1823bb94d62e519b039a5fa779d9575064a78c1552173f74d74ee98d3a", + "lib/pygments/lexers/agile.pyc": "3fabdbbd80111385b6f1709c3e44a2e4ff0c7bfa26ce612341a509ad7dcbdad3", + "lib/pygments/lexers/algebra.pyc": "fc8d14619e24898ea076bc4215d3a1b87d799c6b61a3edbad6fc2d695abdb22f", + "lib/pygments/lexers/ambient.pyc": "29873781ed9d856d4b985cbdd446d55e843ebe293af6f2e1f9bbc6ab1bf7fd79", + "lib/pygments/lexers/amdgpu.pyc": "8ed490190e732bc55506a9d63575ff5d742146e84ca07f968bb3e420ddaf98f6", + "lib/pygments/lexers/ampl.pyc": "ca311687397201e22072e2261e9b44ccdc9d49cd130dc126dbd82cb7cc039edb", + "lib/pygments/lexers/apdlexer.pyc": "76291eb079cd9a49efa78631336b07c86771d9e293fbdf279b49aaa32fd3ecd8", + "lib/pygments/lexers/apl.pyc": "a9a6094d6443e4b459a40cca86fb1ef095e32308b079b0a129fc0ec261966405", + "lib/pygments/lexers/archetype.pyc": "72069a60ab5681385fb359a44eca5753c58183ea8bfe929ef6750eb1040297ba", + "lib/pygments/lexers/arrow.pyc": "032684a41ec61d783b321b57621ad0844adcfb929470ba05156930a06b9be356", + "lib/pygments/lexers/arturo.pyc": "32a87500ba1920a3dcb08139df6f12e7f7cb9f425fbba106a75ceef81002e012", + "lib/pygments/lexers/asc.pyc": "926c55e259f1fe6144eadd08c85865868579f851dc56c345699dc3e130810a3a", + "lib/pygments/lexers/asm.pyc": "b74b936719eddb4581a75af531b0753c5352cc0c4c297c7e7c53a3eca23339cf", + "lib/pygments/lexers/asn1.pyc": "746bab249ad4258c8e10950620d9efc1302928af46a5ba851bcdf8f0bef23ebf", + "lib/pygments/lexers/automation.pyc": "60d71677c7f3f6ed829bfa723b9dba22fd943c52dc3e5cccd032f141ba59c99d", + "lib/pygments/lexers/bare.pyc": "e3a3bb3bf5318cf1017602eafbd370e05a868b008caeb1ffc48bb762632ea8e3", + "lib/pygments/lexers/basic.pyc": "17776268bd5f0a80a2cdcd10f4479cd8e9b67495811a741e5479f3516c94f22d", + "lib/pygments/lexers/bdd.pyc": "33b45af6364879d4b1d90d9dbb66e651a09cc7d1344ea6ad2a1fe312ee6cc51a", + "lib/pygments/lexers/berry.pyc": "f3b88737d0b5bb53e882c201d067bf8eb04b1b205e81d516da2355052e1ab073", + "lib/pygments/lexers/bibtex.pyc": "451b26238b26731fdfd279bcdf06d9934f03e0d76f940ab2c20641cf919a3b59", + "lib/pygments/lexers/blueprint.pyc": "d6c117a34b8c6dc783ded1be8fabb7a1ac31f0307d2b1df35147ad31b0ad9b4a", + "lib/pygments/lexers/boa.pyc": "35bcefb062f752adb28a331d9f620bcc67db805543e70f4d33a271aabdf876ce", + "lib/pygments/lexers/bqn.pyc": "9035ad28ae6c18b98ba684c1a239bdd3a5e4c4943cce4d915113a94e1ff16598", + "lib/pygments/lexers/business.pyc": "d1845179b8247c5d1436b9afa2c0a833e5fac4bfce3489015f4b8cc42af50ea2", + "lib/pygments/lexers/c_cpp.pyc": "9c86a387350aa7e8c02bca19f281fac0554c9d159df3ee95a3f44f739ca4a729", + "lib/pygments/lexers/c_like.pyc": "12cc64c07f9f0678f9eef8fad49e9b171af985f275971355afdd1408dbb57e0f", + "lib/pygments/lexers/capnproto.pyc": "62a3a5c9e6a1a003bba8c5c1ee07d403f6af668291e3e36fedc3ffbed875a276", + "lib/pygments/lexers/carbon.pyc": "67496085c380b131f1861e1108f117fb2464b734c168eed3482987d7948235f7", + "lib/pygments/lexers/cddl.pyc": "7e3d2d00d2540294eba18249e078be56ff3b5fd99653787def337b94065cb69b", + "lib/pygments/lexers/chapel.pyc": "9ccf29433881a4c86f740402b4c789411df6a75a21951e86bebe389824907cc8", + "lib/pygments/lexers/clean.pyc": "dbf57b455059b193dc4d4223ef92e8e75aeafaba64f1c0dbecab2246a4f26d57", + "lib/pygments/lexers/codeql.pyc": "b96d8b078ba46c79beff601473d2e9f2af25da9a97d4db70fc5a0ed3be146781", + "lib/pygments/lexers/comal.pyc": "a714cc489461285f872ebce8b57a1b13fe90b233ccda793f472dff3d7865a877", + "lib/pygments/lexers/compiled.pyc": "94907caa86f6b8b992e913bd2dede36fcd3be9c36663755714aef145d708bd0b", + "lib/pygments/lexers/configs.pyc": "fa89debbe3d1b2a970dbcf80fdbcb56d4d4ca42d668eefc074b3a2b36afc6fe9", + "lib/pygments/lexers/console.pyc": "f1e480e30eb45bc71903a203ab498b70315c81648cde93ec764c766636f414df", + "lib/pygments/lexers/cplint.pyc": "1fbe8123e017c1470f918c3a6f9d471583eb4410812a4b1245b4bea2658afc96", + "lib/pygments/lexers/crystal.pyc": "b60210b4ee29b6b5c96197e7eebb24d468d9ccedc818b294ad3f0315f291acdf", + "lib/pygments/lexers/csound.pyc": "f5a16e555ec43a3e1c83ab74486a7cc4b4c212b97f9841ec334361c155d8fa67", + "lib/pygments/lexers/css.pyc": "4fa718c2e58c0abc915775044c78628ac23f0e114e4861c5d679d114f7b014c5", + "lib/pygments/lexers/d.pyc": "bd6b540b11ea6785f601a0ecd0a0fc72e7848dd62f2d86d8124d627bc805fcc5", + "lib/pygments/lexers/dalvik.pyc": "af1a7a61a2237d365ace5aecb72d171b3ce97fa1194378efdb8400d2420ca35f", + "lib/pygments/lexers/data.pyc": "a0a8af53a01861ddd1ac3f99145d7a925950ef3d8980426ad40f872623a36da8", + "lib/pygments/lexers/dax.pyc": "b374eb6562f8c929f892d1a0316b6a11383efc8531e7e9da1a33ab0fbb838364", + "lib/pygments/lexers/devicetree.pyc": "ad42651a351d7d660a886817b8ece765779b504d1f0cfa194ebfe9bc5585bc61", + "lib/pygments/lexers/diff.pyc": "de4a8b93428125db609fbc821835c95331da0411a4923a7c9dbabd7bda6c2abc", + "lib/pygments/lexers/dns.pyc": "8cd75d5c6aed5af3913ddcaec0b38e04c7fd9c601b490ea7cbffdad2a649de5f", + "lib/pygments/lexers/dotnet.pyc": "7e89638461961792a10082a75b830f5bd5f8983a3ccce886fb7453045cc0d0e2", + "lib/pygments/lexers/dsls.pyc": "aa086b315bce8d415dc9dd3bc17f3d7e2f7e2067eb3857897afcfca524aef0d8", + "lib/pygments/lexers/dylan.pyc": "a83ff9022e6ae7df4224b2bf0ea4caa36c63e1ce7e6472565b90e8d26f12332e", + "lib/pygments/lexers/ecl.pyc": "6a505b7739cd00882e25c002adfe925e06039c51600a1d681d68fe0e1a315fc0", + "lib/pygments/lexers/eiffel.pyc": "ac927ea80a408a67cdd3bda76a226b6c0a31e66378947ff1a651a8ecf43efed9", + "lib/pygments/lexers/elm.pyc": "13f30904debe5d1bc5eeb7b2d951020d2f43fe8a96be0e8d1b67193f5e65aad9", + "lib/pygments/lexers/elpi.pyc": "cf289e5754bcc7eb751de1e5819220aca050a7cc6d485a2513b6a2f1d0b7fe99", + "lib/pygments/lexers/email.pyc": "b3cf41403a5d43084a6635ccda0b015d4b87ea3f74b73d30d4ed8e618464ebb7", + "lib/pygments/lexers/erlang.pyc": "3638764f4ba72a8c5c20922da948a621cab8fda44d6cecd081460852a296d889", + "lib/pygments/lexers/esoteric.pyc": "39e5ae37f36d1c49322885831e1a8530eb8f95f223ac1692271f741dcb6857cc", + "lib/pygments/lexers/ezhil.pyc": "d176007596a437ba1407832806e9b47f0cc714fe89a8b290f912fc5fc27245fe", + "lib/pygments/lexers/factor.pyc": "23a03b64b12abc55c97db5bdecbeb71bcc49493711edbfd77e40bf3f7318b064", + "lib/pygments/lexers/fantom.pyc": "be566686da86aa742830a643bce2eeb4aa756e762b2d4a1c5df5fa1d0ecc0f37", + "lib/pygments/lexers/felix.pyc": "3ac48964f52c11f52edca2db62a8c77bbc4ddef29b1f13771a8fb085cd1d9a3c", + "lib/pygments/lexers/fift.pyc": "3021b780914af4020e376ee0b5de28124fe680dec7aebc947ad5cbe02067c1d7", + "lib/pygments/lexers/floscript.pyc": "70dbe361612ddd398b61c56a81946a45e49969d996f4854447918e7cdfe07e4b", + "lib/pygments/lexers/forth.pyc": "e79df4df74df55fc3496d150699614a10d69a862b11f5b2af55538e3f908725d", + "lib/pygments/lexers/fortran.pyc": "a24994fc5bf975fa49bdf16672cb97e13900cc4e57280b13a42f14f857647042", + "lib/pygments/lexers/foxpro.pyc": "81aeb60ba07ab6dab2d0ed7040847236607b3ca2050861c6adfc81aeba2bbee8", + "lib/pygments/lexers/freefem.pyc": "ac3936ede9ac2e6132a9b83c4e750b7fc0fe0806cc406189a4602b931f3ac1c9", + "lib/pygments/lexers/func.pyc": "5820e2cd01565bfe46f75f56d0ccddad766c2562e54d39a5e7060936e647e844", + "lib/pygments/lexers/functional.pyc": "5ba26042f6b5d9610131de9f9d395c406a7d43bdcacab008790bee992e9a565b", + "lib/pygments/lexers/futhark.pyc": "db3c893a5bdb90508bdaaa7be9d2cf41d323d4ecd09a845b3e5d808fdee9666b", + "lib/pygments/lexers/gcodelexer.pyc": "dd103ef3a227e73a6146249a32bef7ed0c42bbe91d3c289d280c71ad98f1ef64", + "lib/pygments/lexers/gdscript.pyc": "4fe48d3abde81badc35508874b1e931a53824dac61794b5b17e5f07deb9ef2c6", + "lib/pygments/lexers/gleam.pyc": "ba9d984982a8f371f4917968bd61a2f51e7550069f69dd291634fa27f5d87902", + "lib/pygments/lexers/go.pyc": "eae1ea4824a43123ce2aa5432152a244791d8dd81420b9a257d4d66b4e427c44", + "lib/pygments/lexers/grammar_notation.pyc": "2601c1e02242e54ce9a85380ab4b88cfadbbb4975ae776f27dcd7069280ec7f4", + "lib/pygments/lexers/graph.pyc": "dd3d6a9bee30f8ef859c256499e84dc1badbb9ea8981c57e879dea6dd28872f0", + "lib/pygments/lexers/graphics.pyc": "bb90df44d5dc961aaefa6bd57936891500fdf925c460a49fac79d66912340d90", + "lib/pygments/lexers/graphql.pyc": "c313002977dfa1ffac2f8b532db49151d672b792e2227afbeaff886bec3a75f3", + "lib/pygments/lexers/graphviz.pyc": "2cfd34a06c241859ff7eac281cf80994956023a0378ff8ec877a0ae9b668cac6", + "lib/pygments/lexers/gsql.pyc": "33dec19b0c1a5682eba49f32bf30c50419a359abdc84d181bde9f2bf5d24b284", + "lib/pygments/lexers/hare.pyc": "0eb6eb5e63904cb9ab496912070996778f0c07b8c8c563352ab15f9f83482fb2", + "lib/pygments/lexers/haskell.pyc": "edfda5771e538017ce0acd3452f6c1d8a9b86419111f96358d06d0d5ba7e1a46", + "lib/pygments/lexers/haxe.pyc": "e0999d2f208f9353d4865c04de2263d6552c881526c6ad1b0a0005a4aa90f8cc", + "lib/pygments/lexers/hdl.pyc": "71366a7e10c9ba627a8f7b69c7234358a7d847dee4337076ad80318bca32572d", + "lib/pygments/lexers/hexdump.pyc": "e214cbbe5dbb22ba97000c043cf5e9e4567629ab27a18050db609389e00fa935", + "lib/pygments/lexers/html.pyc": "d890aefd103facf2463c891b98f757bc51267265734195dfa68495a653b52ef0", + "lib/pygments/lexers/idl.pyc": "adc4ca59bd7c3e071e91b58257861e8f62a3a2d4905e31ec39e307b14d403661", + "lib/pygments/lexers/igor.pyc": "0e0b46b63e05fde21fd1f0213fc098ecae9e36b0d3743497ac75fe869e2d840b", + "lib/pygments/lexers/inferno.pyc": "3d494ec221110dd5884d869b486d26dadcc5a991aeee1396a06ae9c02ddac50d", + "lib/pygments/lexers/installers.pyc": "d743b46fa76f7525293ef1307e6d50930cffb03d35a972f909a3bcb102e5e23d", + "lib/pygments/lexers/int_fiction.pyc": "1dce33a1755b4913c7703388b07ee6965c0cca0bdf91cde8d26073d17c933aee", + "lib/pygments/lexers/iolang.pyc": "f650ef6a4e514748341a8e58cbbd61b48e2ff09e7d8d7237faee89d17b73cd44", + "lib/pygments/lexers/j.pyc": "174181bb34a5ba590e68997d8f81b1e07d2a8d5114d7c3e31f9e0cc3faf3ee6c", + "lib/pygments/lexers/javascript.pyc": "917680877c06f0c44ecc43e6ac320de7fc89bbb28c619300195b12aacbb2d734", + "lib/pygments/lexers/jmespath.pyc": "101bf280b6fbe08653171b911f790965b15c479e01f76727830100f61be0d729", + "lib/pygments/lexers/jslt.pyc": "6eb95e0949a7556334a1ef90462ce0fb49da5f7bf012a67a59ccfb806a768c8c", + "lib/pygments/lexers/json5.pyc": "592fc7b60fce48a5da865b227747305bb4fcbac19cb09b46e80be415702610ea", + "lib/pygments/lexers/jsonnet.pyc": "956109b808887c2fc5c96e96fd1edcb4be0b8fdbf6b84e728119293152acd2af", + "lib/pygments/lexers/jsx.pyc": "d80562937cc8a9363e3f5f4f159dbc320fd23636d51589bed673245042551b6b", + "lib/pygments/lexers/julia.pyc": "877a09cc1065d20133a1f52dcd88079156cbd24d1d0183341b1cf240492f29c0", + "lib/pygments/lexers/jvm.pyc": "0e57951f7b910bcbda9c8c07baca3676c5ffdbf66ac0e50912780fed8360bfe2", + "lib/pygments/lexers/kuin.pyc": "0031eb09637335c15a285af64d38390131204329c2643100975f7ff0773cdaa4", + "lib/pygments/lexers/kusto.pyc": "b6710324c5d5970f725426ed0681d24bae8ef886526d6742c4721b5040bcd3d4", + "lib/pygments/lexers/ldap.pyc": "a476f4772359401f990462281984e7a139917e81f492fbb01602ba48a4db78be", + "lib/pygments/lexers/lean.pyc": "9a07d876ab7329e3e94fa8d2cebcc69164d9424789c00397dca726313ad8487c", + "lib/pygments/lexers/lilypond.pyc": "3ce0a024a42b2ed483a35234d5d2cf0d9b3fe18c3ced601c799dfa3ff4aea1c8", + "lib/pygments/lexers/lisp.pyc": "33073f93f925677036d38807b7fa63d8d8c6afdc76bdd7b8b8e12f4a72f97aed", + "lib/pygments/lexers/macaulay2.pyc": "3182da4f6c777b3b83bae3e4bf2fb6893e0855ed109bc9cf6308b3726f1458a0", + "lib/pygments/lexers/make.pyc": "ec41fd5d142f1129c2c766aa7c756e6584d44fdcd3fb943b29a637900aaa4367", + "lib/pygments/lexers/maple.pyc": "fa612a8e3ef4357a6d954f8434632ea6f34034ddc4f381734907b571e0172492", + "lib/pygments/lexers/markup.pyc": "d20bee7947f224b36ab32aca17c5d65a112b76e21374bfae85750d98a6b3f571", + "lib/pygments/lexers/math.pyc": "ff261a684cd5463a23c03ecaffb066d46e958037e41a2280eddd5c894ddb53b3", + "lib/pygments/lexers/matlab.pyc": "1e3cc5ce24a29571894676a50828c9806ed7f0b4c306671c1e65cca16676a3d2", + "lib/pygments/lexers/maxima.pyc": "554495de03719660134cae778a1163e6c2dbc731b26b3c6ac99840dac1e47947", + "lib/pygments/lexers/meson.pyc": "8b54be2693142cec21f381d748e7f1ca0900a73d8e77cd2573027ea6420eee08", + "lib/pygments/lexers/mime.pyc": "4f95c0fa19004935ae6dee437c3025a43b86b0a9abd74ac752bfe30ca3b6bf80", + "lib/pygments/lexers/minecraft.pyc": "03d5aed4f491eec64d4e6b49442155565f63d0769f96cef068ce5cd62dca1be6", + "lib/pygments/lexers/mips.pyc": "39b9ef3bbf34c72e8929ad591a4a983add8282bd4d6581c19430b30dc426597d", + "lib/pygments/lexers/ml.pyc": "7308bfb04721e02cd2d16fcbf6fe38835dc70cf3b71bc60894fee5ff1b40f3c7", + "lib/pygments/lexers/modeling.pyc": "2cd720088d590c95c57e42a495731c3fb6f4938207e4ddba66c55585ffd99cfa", + "lib/pygments/lexers/modula2.pyc": "38d0bec25fe3fb0ec786fe73786166e867949a66dd29cccafe411d93064779e4", + "lib/pygments/lexers/mojo.pyc": "1693fb51d899b3b63228356d1eeb84d110819af9da7697b55775b1cea6934c56", + "lib/pygments/lexers/monte.pyc": "7f8484910c63b831a0306fd01c92a22b20816eb31ae4d6525c47a0a72eb69ec3", + "lib/pygments/lexers/mosel.pyc": "c2bba5971f91a9e78ac19a2409a1907645c82ab3ba28a3fb7cd7856a527ccc91", + "lib/pygments/lexers/ncl.pyc": "57828b5b2afaffbafbadc033bef0de78b6802d0e2463640322b42cbe8e3ccb10", + "lib/pygments/lexers/nimrod.pyc": "2cfc3f9fe270152ea1bc160371f0c276c4fca752f5a96fd04bfea12a134e1a07", + "lib/pygments/lexers/nit.pyc": "d0dd01068f0b7713916d62182976905cc233c358b6ce97e4da0d3242eb58e9c7", + "lib/pygments/lexers/nix.pyc": "de2dfa83bca937cb2f4dec3f60a6e45f402970c1c7e6f0492730b61ee788f25f", + "lib/pygments/lexers/numbair.pyc": "10ee71fb0c1645cbfdd661f6715e39fd720d7dbcab37cdea0f22f9c592c6473b", + "lib/pygments/lexers/oberon.pyc": "8f0a6787c0c2fa2366d5c9b74e665038d297b95dd8aa53d21c7d9da7ecc0267e", + "lib/pygments/lexers/objective.pyc": "de9b40c7be618345894fc03ca821b959a16a4dc9454e008e6efb8f66d26bd5f2", + "lib/pygments/lexers/ooc.pyc": "beea8e1a78d68d8d8b73ae105d96a2a321c56b7933592cc1fc50bc3cab2a492a", + "lib/pygments/lexers/openscad.pyc": "beac7cc089b94672aa073099c7afaf9f1531868769cc32d8895acadb4084a68e", + "lib/pygments/lexers/other.pyc": "43ee40f7a32ed6315bcfbc5d4a6e8f91d1bd22f074c7116e9f054295f276e6f2", + "lib/pygments/lexers/parasail.pyc": "cd960ed945c6cadb1a43cee0fe2be3be3c38631432fc81fbf93c2e78d4f4f8e5", + "lib/pygments/lexers/parsers.pyc": "8a25e19263ba993ab1d445a53da0c66f4b71e052567766c484c59740a539b81e", + "lib/pygments/lexers/pascal.pyc": "deedb191d998983ecefae227c5439677eabd33e2ea0742627562ee5a448d9221", + "lib/pygments/lexers/pawn.pyc": "cae92cd0a55c71eb85aa8283c65b82abd19a83b55a8d3d16742017f7e460c3e0", + "lib/pygments/lexers/pddl.pyc": "339566c1750c8142d480ee83af6155d2b627b2b98a7c667aa36d91316d5e9992", + "lib/pygments/lexers/perl.pyc": "99c92959ac6b60a7765ae7d7890757b66d00f6051657cf97aa1773263d86a30c", + "lib/pygments/lexers/phix.pyc": "7d39157ce03f8a59cb0adf391776e534df4157294cf8a5097241fccc80631f9f", + "lib/pygments/lexers/php.pyc": "aa76ce919a7b95078a6b42610ef93a2fc5204642e16ec0e7e13276ad4f1499c2", + "lib/pygments/lexers/pointless.pyc": "3e3fc200f0fc30683265a27efb3ab8bf81946507971e5d73ba6b533fed657355", + "lib/pygments/lexers/pony.pyc": "7360b15a8f248bdd3197e753f5d3c234e4f5d0436353336ec97ef276ce7be4fb", + "lib/pygments/lexers/praat.pyc": "efc8725184983376e79f73f56dd22c0c290dbc23b22cdfd042ee9fc9ffae5d69", + "lib/pygments/lexers/procfile.pyc": "b8bf107bc9127043f0337244da28f96565c7cfaf2993f8eee7523745eb54e331", + "lib/pygments/lexers/prolog.pyc": "b57caea117a2925641d68aeee7fae4131b884db31ce494536841153fe27e0e17", + "lib/pygments/lexers/promql.pyc": "89c0875b366a9ccae0c424dd8f3403d88cc629c0e708bd0d47b81ae335586816", + "lib/pygments/lexers/prql.pyc": "3a7c9772f329f53830fb89703d05ac7d50b172dfc5fa5f53ea977c7836570772", + "lib/pygments/lexers/ptx.pyc": "16d071a14633a1dce959e03c642277dc6976b0cdf17510998f96e445e8c0d690", + "lib/pygments/lexers/python.pyc": "3c5faa399ef7fd32a3e5b3ceb19723116dee92bc7921ee47e737a9b9160b6df2", + "lib/pygments/lexers/q.pyc": "12d4534c76d425a6a261497d1d5d3b7546a70c3659d183574ef77a616c5f18ab", + "lib/pygments/lexers/qlik.pyc": "d54e6e24fc0be9c89d4e05fd2ab60b9dab7b869ade7e54ff653577a4dd241182", + "lib/pygments/lexers/qvt.pyc": "5f4b3f80cd9d924cddf1b63769173ed7590c167514726c9d463818ea903d2be9", + "lib/pygments/lexers/r.pyc": "fbb49bc8acf21f3d95b2b56883eb818548e8b60fb5a6e004b43cff642170e277", + "lib/pygments/lexers/rdf.pyc": "44604565e5f697b0548338b0ec55f717705a0aa347a80ce5fbed9fe8631bcf91", + "lib/pygments/lexers/rebol.pyc": "b4e4d7318a1cf81c557b9b0702bf2b8d0431875469127c01ccff1fee2e66b884", + "lib/pygments/lexers/rego.pyc": "7ba53c5233426498851140d5691cbbb32838edb3a3ade47f91fcfb0ce0686ccd", + "lib/pygments/lexers/resource.pyc": "d1c42b1ce0bfaf30d902842fec064704ee573b0979581526cfe35c5039f38a08", + "lib/pygments/lexers/ride.pyc": "515926ccb94358c55c413f103aa8297cd28ff5053a16772c068bdcdbb0652227", + "lib/pygments/lexers/rita.pyc": "bb1d0c2cb53e69e0b12d172f472c8eb367655599785e847d304a9a4ed43babaf", + "lib/pygments/lexers/rnc.pyc": "4a442fd7c5d165dad6ffaac1676e43d0f4d13f0f4ba05583be2135719b0e6920", + "lib/pygments/lexers/roboconf.pyc": "9045d9eb73ec249b8164607fa46be8fb5c4495d8a0a3295108947bb47c57d543", + "lib/pygments/lexers/robotframework.pyc": "42fc83d222c604e7e80c64fcd6e2a5cd9a3e06991e9f7737807b196d70de786e", + "lib/pygments/lexers/ruby.pyc": "128c4e56ea3dc9704e99abe82afe4a37954a1443664ac4ca11f72c67bf6b6eff", + "lib/pygments/lexers/rust.pyc": "20c33564b2a112265b606a50c9240ca11fbeebf4f40314fcf8b9a765e2e150d4", + "lib/pygments/lexers/sas.pyc": "7659b73dcd77d1a394ff136ccabdfbe87a11bc6bbed64d3668ec995c19b4f31f", + "lib/pygments/lexers/savi.pyc": "0640c77f925f790efdbdbbd54435f43c8cc6361c8f60152e8a8c69562c8d9f68", + "lib/pygments/lexers/scdoc.pyc": "5e2045af5cb3fad48a546d377924a5cb4058cec9ef361235c680d4a180f61cb6", + "lib/pygments/lexers/scripting.pyc": "f9c0df9a28c6c392035f19bcd30a3e6f3c80916df04f2388991c210b0eeb7c55", + "lib/pygments/lexers/sgf.pyc": "8f8ba4a3d554fa0217a0eaddb85c35f12b5a5aa5ec75e442b97f5c1355286b5c", + "lib/pygments/lexers/shell.pyc": "c449c93339081042ba059267a278dcdc264ecda4c49d1f80c5e60dcdf17f2343", + "lib/pygments/lexers/sieve.pyc": "52b8ef77a6704a8386c0926b7a9d9204e6ec17af43cb783d429f560087319266", + "lib/pygments/lexers/slash.pyc": "982bc4dc9cd3b742dfb3798bd258cfa161b8fa4ba662c6e7791d194bdd8e3266", + "lib/pygments/lexers/smalltalk.pyc": "e4f71c18b408e396f849ef4ea26424effbf0fcbe4a0cfd45c340d875de53fa48", + "lib/pygments/lexers/smithy.pyc": "cd3ec90648282b60b6b2be23c53052802d2ca87822e1ad145c61d72fd794a63e", + "lib/pygments/lexers/smv.pyc": "cd1866a3ef2098ed49018ae4747c18bc9664062acbf223c1efe2d71f97dfb693", + "lib/pygments/lexers/snobol.pyc": "d1aea64086c125ccabca0b044c8c53ecafb150698458bea7fc636f4377b8d883", + "lib/pygments/lexers/solidity.pyc": "cc26c2124867de42609f46c6652d0d6feef46856a375af4186de9c9b8063a30d", + "lib/pygments/lexers/soong.pyc": "1b33a57d56bbc5d324e419df0fc71a93bef3113c9eed50a9964ab7f0535edf36", + "lib/pygments/lexers/sophia.pyc": "d8eeb0267cd333acec6aa8371e8e8be9494e4d32b7dabf6b4b5d0bda8cf79a72", + "lib/pygments/lexers/special.pyc": "d4988c3de7ad48410e526f101f0311b190d65c3c35b575ca273f147e1636ab7c", + "lib/pygments/lexers/spice.pyc": "f919a9e3b53a8120c155c57024437db9d01b11e582fb2f96ba2f08c0e6aafd96", + "lib/pygments/lexers/sql.pyc": "607df824829fa7d6db480bd326cee8d7615fb4481a0eed58303e71040ba2bcb0", + "lib/pygments/lexers/srcinfo.pyc": "a66e28b31f48ad0f49ec89be9f7471dc1c2ec94b1b771219a09328c87eb71c84", + "lib/pygments/lexers/stata.pyc": "2d2deed9e373ec56b869a319da17364a5e74b8e8c1919cd9ba57ee6da0fee16e", + "lib/pygments/lexers/supercollider.pyc": "8470700d76c43d491f8721afb9738d9c21af31fe86a0fe3588db3a5bb6f30607", + "lib/pygments/lexers/tablegen.pyc": "d160eae5eea865ce4f4fda6726c6780397c018737dfe94bbf8913329584314d7", + "lib/pygments/lexers/tact.pyc": "b7282ac1127ea536098172d817ca41946d70b18ed8a3cf3d42f4e57dc43f4022", + "lib/pygments/lexers/tal.pyc": "573611d783e7b5c52acc722eaa1833bd4df113f8357d95563cd81b2da11606f6", + "lib/pygments/lexers/tcl.pyc": "66659678ee5e3f9fb36542644be49a81df7ffea1596b6aef86cfcd1c41a95bd1", + "lib/pygments/lexers/teal.pyc": "f2f2ece859954cf38b5c80014d6723bbfd76653209c2586eb7c03f78aa794b09", + "lib/pygments/lexers/templates.pyc": "e072866a9ad8c7bad71c832e02f5713600cffb9bbc50d31481ec365dab697be9", + "lib/pygments/lexers/teraterm.pyc": "077ae49146d08177f25b3517c289aa6aad424f744da1e5abc285438aa67d6b33", + "lib/pygments/lexers/testing.pyc": "bf62cd830e28737bb54f1fc298ac0b5f1f01ff6c85509351f6d62a1b4628df97", + "lib/pygments/lexers/text.pyc": "5993fe7e00da73c09a6d01887a85cb125da693ffaac277f6b00f04db62e83827", + "lib/pygments/lexers/textedit.pyc": "81789e5248302c63774c0bd57df0def597620f67467c8dcebcd6b5b09bedbc06", + "lib/pygments/lexers/textfmts.pyc": "e0c3b754961298acba793162f47c6a552be9defbe6a5accc3d7b73e621d093b9", + "lib/pygments/lexers/theorem.pyc": "e6f8649e9d66f61212d3af5055a707824f001de9eb9212288c2e7e36f616a756", + "lib/pygments/lexers/thingsdb.pyc": "41e56e4aa9be5758aa2665df6893df8581a5a039134329b6123e8740cee8ca33", + "lib/pygments/lexers/tlb.pyc": "eebdd5f0f3dc8b0bddada38f2f49a168a642ae477e008ecf3209c9e4e6aa9d2f", + "lib/pygments/lexers/tls.pyc": "76b0b7c072fc2168c1efa3d1451695d2dfb2070522b1881073afd6b3970063b4", + "lib/pygments/lexers/tnt.pyc": "1e9e0fdbfebff9a0e48c852cb02583e9aa593e31c2ffb5263964c0551b407b79", + "lib/pygments/lexers/trafficscript.pyc": "12a161d2679b0c6b96628d5c782d020f15c8063745cf78d47dd28f17f1516b78", + "lib/pygments/lexers/typoscript.pyc": "65e700cca453d35810e2f81043f4a9c20151fa9b5dfab10b580f06b51fccfacd", + "lib/pygments/lexers/typst.pyc": "118de752cdb054f17e17451e7349587292361ae6795431de200bfcf43acad4e3", + "lib/pygments/lexers/ul4.pyc": "27e69568b894cd9f2281ce604a1f917455b15238c5f07bdf724a2dc40201c4b4", + "lib/pygments/lexers/unicon.pyc": "896f2d8113aab9bb88a45a1aa894ed112685c99ef7b846aa850df5b1116a6616", + "lib/pygments/lexers/urbi.pyc": "730139cd21ef6ca12a303ef2281bbcae3f8c776f14877b926eb95d4d8f5aee9e", + "lib/pygments/lexers/usd.pyc": "adac22274582195ccd6c11cdef3b4040e00ce3801a642ccf95fb092843e1abe5", + "lib/pygments/lexers/varnish.pyc": "971ff01dc8e9be30754d73cf06af6af558c28560d68b7ec9e47c80f28e0f965a", + "lib/pygments/lexers/verification.pyc": "7763b819046a56583e23b85d6bc7710edb2e57497b7b20857112e6cff6b30027", + "lib/pygments/lexers/verifpal.pyc": "a0e508d5f867c7f1e47dae4a6c8c62ee392deef0f0f236fac1a5dd0883966ecc", + "lib/pygments/lexers/vip.pyc": "75072158c90a83e21b0cfda9a55b89c0c378366f0fc1debe37add9f323092307", + "lib/pygments/lexers/vyper.pyc": "119a51d8bbcd421ff95d1d4510a5f03f75f28a3f680e44ae62b89da442a387b3", + "lib/pygments/lexers/web.pyc": "40528dc8628863b79c9d694e2a54e8578f1f3a7466a0106b799748831efe811f", + "lib/pygments/lexers/webassembly.pyc": "7bd38cf832ef1d6612f27b3f2dcb964dca8cb047d2409ebff5666b66acbe9789", + "lib/pygments/lexers/webidl.pyc": "9bae1e3bc99814ceb921127834ece866d4d48f523ff8e4ff34d10c347ee9efcd", + "lib/pygments/lexers/webmisc.pyc": "c70f72b2488a16a94720f998303498a34e0a3e2f66c04df9f631757d4bdf0468", + "lib/pygments/lexers/wgsl.pyc": "0c5b34e22d8caed74e43a09daff62eb07e3a7318ca977b0d0cdf3e85bdc33b38", + "lib/pygments/lexers/whiley.pyc": "85e0fa3c6e20a858f60fdace249090a035b1a6e7ba2a9bc4a5466887f0aa22bf", + "lib/pygments/lexers/wowtoc.pyc": "b21cb21e9491d75157323d7e766ab2e0623bf10aa5e6682ccb6acc6434ec7dc3", + "lib/pygments/lexers/wren.pyc": "dda78b34f142587c6d7255423a97e12c51bb490d10c9d999f4d8624dab58a1cd", + "lib/pygments/lexers/x10.pyc": "90f7cd173cbb1d1060adb68941771baf42a711f67113a347fe8cd5ff2ba55c77", + "lib/pygments/lexers/xorg.pyc": "c74348acf2aac1e252ced0dff2242919ade9bd89394a7f474cd2f10469ad3d3b", + "lib/pygments/lexers/yang.pyc": "68ab87d2141138652185dc6020505e8e3e08eb253f8a18ea2e79a8e67727d540", + "lib/pygments/lexers/yara.pyc": "5e655a029b1a7c5a812a69decc1c24cde465cddde3b5a99af469ad821ceb31ff", + "lib/pygments/lexers/zig.pyc": "4fded76dd26680a4628d6bdbafc54f9af0405efbd276ce68dd1a5c70b3b4e2f6", + "lib/pygments/modeline.pyc": "ba459bd2aa7f96d4fe85690d8921829e12c82dbae06821a773ac6f65685b7fe9", + "lib/pygments/plugin.pyc": "53ddaab480758029d4d76ff8d7238a7089076a6ae827bde919d63fd64569c145", + "lib/pygments/regexopt.pyc": "f2b1abef7f0a9c02707217b228f593ce1db697ad6751591b76143dfb329d5572", + "lib/pygments/scanner.pyc": "89e298671ae67106958789af2e0deb19d0524121c525707b4dd2a5f57be0c3a8", + "lib/pygments/style.pyc": "5a8bf5e1e1aab39d2b7ec2b5e33b1a1bcabce24e1794228a832db745707287f6", + "lib/pygments/styles/__init__.pyc": "9a59c5b2e2c90ba0f89e60db835d4ae831a3fcdeb6c9fe05369576aac1f1feed", + "lib/pygments/styles/_mapping.pyc": "7df16480621475153a91eb6bae020db954caeb1be49fa75c7bcb3899afae43fc", + "lib/pygments/styles/abap.pyc": "4ccee759016a004b32e22bb67206197f07960f83f8821e4591c96b828c6ee09b", + "lib/pygments/styles/algol.pyc": "2f435ebd228d779faf8c7132928b517a7fb3e9bdff240c8dc23ef452586c7e3d", + "lib/pygments/styles/algol_nu.pyc": "ee1a450874b09a64a8ffb25f3fcc9c0633f3dd75d765481af561810b02dd83f2", + "lib/pygments/styles/arduino.pyc": "98534178895b7e903e0dfb53fa38d1c317707db40f6b70ce06d440bcdeeba0a7", + "lib/pygments/styles/autumn.pyc": "b9be352b04191bdc4ee66690cf48a4d871fbebf6bf06073c3d91e585a1b1675e", + "lib/pygments/styles/borland.pyc": "975e0fd524367b24ac1978cc6ca4e87ca35009d9c3a0e34b4560d2ee4642a07f", + "lib/pygments/styles/bw.pyc": "f1ebe82a20d05fae48a3d15385aa29e02523af79858950325493619b9dc2859a", + "lib/pygments/styles/coffee.pyc": "6d6e55f573c4e1b665d571f4a8ab1c189a37a4c1610901b123eb878f8ac0fb29", + "lib/pygments/styles/colorful.pyc": "59daee01b22c75bc588485d6a788dffed3343793433b5304bd15b546ae69178d", + "lib/pygments/styles/default.pyc": "be4e8977d98164ed38b82bcc29b3c0dc7ff8e17728ae32681561a36afe42f638", + "lib/pygments/styles/dracula.pyc": "2dde0795c55a701cde1f08b6884b1bbe0269efb599713ddc3ed513f6c2c16eed", + "lib/pygments/styles/emacs.pyc": "07cdee61cb10eee5ef5d3f3d7dd233bf7ba04d048aee072e54726f077a12e045", + "lib/pygments/styles/friendly.pyc": "7a39cd440c3cc56c2cf9e7ef9ede06f9bef428b6365464b12245ba26dda842b4", + "lib/pygments/styles/friendly_grayscale.pyc": "96052ec1b758ed983ef124c778365d7b3fbb3d9121704cf69b27711431e968ab", + "lib/pygments/styles/fruity.pyc": "aa46a70e52613eebf66bc935f8d9e11ce6cebc32590a295aed8c66900dfe0eae", + "lib/pygments/styles/gh_dark.pyc": "f2f2293c033489b0ffbc8535a00fbaefa17b63c275430617bd89629cb5aaa4ae", + "lib/pygments/styles/gruvbox.pyc": "c5f342da64c3cc449ac9861f305cf37ed39ad0828cd48e4944ca3d65d10d838c", + "lib/pygments/styles/igor.pyc": "ce16b81758f470b52488ba8bcccc56a0a23e0f9e25d6abdad27765ade93936f4", + "lib/pygments/styles/inkpot.pyc": "466fc6ff696eef6e8cc3a0322f6da0b871b8fe00908c5a241c039264c100172b", + "lib/pygments/styles/lightbulb.pyc": "50e0cf90d8b32fc2fc3112fb2786d4c383c342d6abfac04d1a386b0509487c54", + "lib/pygments/styles/lilypond.pyc": "7fdb4121a8daefe8f0e78110e3af0700039e24a90aa9670ce871c9b6016ad906", + "lib/pygments/styles/lovelace.pyc": "2c219893a3f6af15d08d45e1a69b16d779703b283b8ef31924a7fc99cb956171", + "lib/pygments/styles/manni.pyc": "82b7f07793c1ca63be72213a0f3965153c4a7aa9c4928665f4403eeaa0a016d1", + "lib/pygments/styles/material.pyc": "4fb375dd8a859df490974beeca089e1581ec6964d7d72fde444f8694bf7403c7", + "lib/pygments/styles/monokai.pyc": "781e00630b860bc44fa0451028cc671eaf8ad2f47fc9d9592598092811b09160", + "lib/pygments/styles/murphy.pyc": "effeb98b152072244bd089abc21dc06b425068892dc6863fa9a455de66028884", + "lib/pygments/styles/native.pyc": "e343433e83c6dcedf538cfe41cc15b8344a0b83f47f4223955af903e8a4d3edd", + "lib/pygments/styles/nord.pyc": "082135e2fa3709f5f54dda246c0e5fe7c380c134e7dd5bcad4a68e9c032dbc34", + "lib/pygments/styles/onedark.pyc": "6e8e784bfb4d0f4b04f59c9c079efd195529e2b3f836ea702872538b5c18ef08", + "lib/pygments/styles/paraiso_dark.pyc": "5dac4575c6467f4d10fc2be87cb7c0c275d5b120cf0080b73501794cc43f927f", + "lib/pygments/styles/paraiso_light.pyc": "89dfc2bdd82b0cf1043027815d5632dd89fe668c3e40960038b35ab3acb9ba82", + "lib/pygments/styles/pastie.pyc": "1818417180b16f3441628aae24bf1ad4ff8ed44941bfd8631759ae65bed67c49", + "lib/pygments/styles/perldoc.pyc": "cccc530ec77e14322efe4e841ec407077567d6cc6f201e6109d5640f5d781a56", + "lib/pygments/styles/rainbow_dash.pyc": "779b9f75a21d8ccec5ec996791af5c6dc11a4955892bae548e9f4ac2dc261164", + "lib/pygments/styles/rrt.pyc": "317ef8433bda7f79fb6088a7a54eea8a25a847a55fbe4ae77d19e959f5be7143", + "lib/pygments/styles/sas.pyc": "e676820ef7d9a53d3312efff9ace4aa2e8a5c5caef9c91024c4a60d54af3cbb4", + "lib/pygments/styles/solarized.pyc": "45433f924900b91333a1e0cbdbb8270ee841a449b3d19af333fadd64172c73c8", + "lib/pygments/styles/staroffice.pyc": "08181b9ff8ca1485009b6f026d9db02580fc25ed89773bc1d6f6af323cf5e238", + "lib/pygments/styles/stata_dark.pyc": "0a9f11f8ed91e78a7708613ab45d1bac3f3d75583c47ccea810cdfc8b189d1f1", + "lib/pygments/styles/stata_light.pyc": "b25e5a9c1fb78d1daf2e067c41a47340c7dfc3f3b489195c13e7238a83451640", + "lib/pygments/styles/tango.pyc": "ba374428faf52afd87a9d5a745f5de115402e87cd0e3fba1297c47d8467e4565", + "lib/pygments/styles/trac.pyc": "c4e76a05d990264a3c0f8bca55fe90cd013eeef32d3bd2d9ea2cac80d43318ff", + "lib/pygments/styles/vim.pyc": "56938d9764f99c55225b583bb08ed23cc0a3f7756972e39ce11ed16a9f661162", + "lib/pygments/styles/vs.pyc": "4cfbd2474613604e447f0a5aa2cd4613e9efc88f0dbe3c89ea3330b0a4313e55", + "lib/pygments/styles/xcode.pyc": "535e3d1cf8c2b4f2bf98f0ea4acba81dff994027a9284f0d06c6ce345f89b60d", + "lib/pygments/styles/zenburn.pyc": "d216e6e9ad4643f211872edc5c187b4097ce8bfe26000a6c65a7c9c4ae61ad48", + "lib/pygments/token.pyc": "27102b77d137a12305672c4d959577d871e5da2a9e569b2ed6179668f5cab715", + "lib/pygments/unistring.pyc": "fee0a457a1b6ee9b91a9e57b7081465c4a7c2ba78af2ab88e076c0e8050f7b16", + "lib/pygments/util.pyc": "376df479770020d4ad44fa61519960516d6634da75ea0ca72285230396cd2f3e", + "lib/pytest/__init__.pyc": "c2d5099aa30e291fba7363a99baf446376743fd53b5f8f83aee5f2181055bd0b", + "lib/re/__init__.pyc": "3a407d12f9616cb6911a29456faf011240bc5d6378d4b94404957873a7dcb000", + "lib/re/_casefix.pyc": "02e78c3d009e72dcbef654fae8bea54c59bbe9d4baddff042f2eb6c87d58e054", + "lib/re/_compiler.pyc": "0b8d43c738cd4256e87347a2ae8b47e327989747c3f7506b0319c565a875d435", + "lib/re/_constants.pyc": "73523153af3e0b937008cad887350a5ec6435e8f6efb9e3c583f7ebebbf3f50a", + "lib/re/_parser.pyc": "80279ef80d1b8a50217ea94d5ba7cc6247d7e07ca92fc005a7f624fa1b4941f7", + "lib/readline.cpython-313-x86_64-linux-gnu.so": "59f59527db9c68f4ff981f06853718ea2fc0b919a8842370aa7481c00a0b02f4", + "lib/requests/__init__.pyc": "b5165f152f973f2640cc56d752cc952215dbd708e3a67305850137bd66d1e59e", + "lib/requests/__version__.pyc": "1903b1d05c5e6118e03c5bcde75affe49aabc71271b8f55876f1bd4560f1cb71", + "lib/requests/_internal_utils.pyc": "6a8743125cd650cf05a8626e42a234433849c3c2a476cdcba658bed4981a9e82", + "lib/requests/adapters.pyc": "ad7863342c71c41b27ef21c6433b8671089c7ba0e4c7e524845b70a4bd078279", + "lib/requests/api.pyc": "8b599a3a7860d9135c91066da5a68899567b43154c5bb69230487f9d486e5d92", + "lib/requests/auth.pyc": "387c72696c764ddfa89a586f6d6982e273f1b1405f8d7d706fe87ac37acd325f", + "lib/requests/certs.pyc": "cfb1c3cd724d1f89fe8c0853dc9c562103736413130ef8efa082a2ddd91bfc19", + "lib/requests/compat.pyc": "181ae9a66175f9a0053059512ae759f88e07eb82acaa90d2c805d9dcb0aeeef7", + "lib/requests/cookies.pyc": "8f1a4aa71252af2ea581c86dd965e780bb1ab78bc1975e076c982e79f33a2c3f", + "lib/requests/exceptions.pyc": "7f0eb7d76a73be91173384eb7bb6cf0f4cba0171fe82de50e8fb6f4c70b29b93", + "lib/requests/hooks.pyc": "1ab73abad163b658d1c5837e36d1072f033fd9c8e10934c74703f7be078ca5cb", + "lib/requests/models.pyc": "f4d19f985b014fa2508a817aba4c4d2f558e034c3fb3faa3edd9ea80e87e829d", + "lib/requests/packages.pyc": "9d450c2b40137a26d205bc892808e312ac9f562e342f5f878ed5d2827747db7d", + "lib/requests/sessions.pyc": "66b407787616a7c51e05a06d3fa53b2769a92a4c89049f269ca92e637b57da06", + "lib/requests/status_codes.pyc": "76b9fe4a47ccbfdb2d8960da0fa505085828005922384203029d38883b10be9e", + "lib/requests/structures.pyc": "3a61bf0370b2a02e7a62f3f598ae0480fa8308a95437fd08cab10153d3d3b39c", + "lib/requests/utils.pyc": "858f4e2155206364cd2dc30140be8704f97e9097250127261cec3cfcc6b68d98", + "lib/resource.cpython-313-x86_64-linux-gnu.so": "8650429cdfe5f5f25b4f79cc417e884d2b21a5f1c14a1c551d54726d92a9f3b1", + "lib/select.cpython-313-x86_64-linux-gnu.so": "5bdedb878d89bf28ae31823fb4095cc980b6ded6c85219dcd4c9ee93a11ac74b", + "lib/serial/__init__.pyc": "52532d425d86881b9afcea2fde7b84d29427c1a20d618dfc22edae7d7fdf5b9b", + "lib/serial/serialcli.pyc": "29abae3bc7e0f2b6409238c5aeed4414fc3b5276631b5c1afa08e80cd4c20b4d", + "lib/serial/serialjava.pyc": "c25175a69320c9a98db4d0246864bd8c939c15aca07dce11cc4ff014e45ceab7", + "lib/serial/serialposix.pyc": "94879a9c029fa2e3d7a5767f621b6c06060e6014784d23058174127f44e88eb8", + "lib/serial/serialutil.pyc": "fe8cb01c8af4fe784bb9b8349e80b9df2c6e07571610b1a27e48f332d6345541", + "lib/serial/serialwin32.pyc": "2cc86319022e613faf5e8534b4b9d86c2c4febe393042bc5a0599adc4899ed52", + "lib/serial/tools/__init__.pyc": "0db24b899b8c19a8ffb4816a8279b9916b7c0ab52ac5e17270fd8990aca952d1", + "lib/serial/tools/list_ports.pyc": "e7fc848f99c390fc498d00cc1543185ff2a6b69f16ed995717194fd58594a52a", + "lib/serial/tools/list_ports_common.pyc": "c53bf941bca86d19dbda2e2d030d28346d128fa6b993d6b1ac818beaa7e6547f", + "lib/serial/tools/list_ports_linux.pyc": "15861e9fc15b48db2b101a9feb3765f41a799b30afdd5afb8b655b73f9069ee4", + "lib/serial/tools/list_ports_osx.pyc": "67a72ec870186e62cc7c09221b08326819676f49886a41249de95628573d9f73", + "lib/serial/tools/list_ports_posix.pyc": "84e2a24762064963b0d497a8aa8fd8b64cc694231dc3814389dff1458785a31c", + "lib/serial/tools/list_ports_windows.pyc": "e95dca00b3e408dab2a73d723b8513d5667728b1f9762ef64b4caccd08de8be9", + "lib/serial/win32.pyc": "f01bfabbf392d9f232a29b62e804c649c96b6f664455b7b0a299e7cde3b43b1b", + "lib/setuptools/__init__.pyc": "2a500b30ef0c1da620ff957819577f5335f0d04b3a042ba4a7fae21427b2db07", + "lib/setuptools/_core_metadata.pyc": "3bfe6ab2fe067bf402b0efb49d255326ac9a20495915d5d3154ac3a05a136c35", + "lib/setuptools/_discovery.pyc": "3a3026427dfd87c2a1efde4f87fcfab32cb9b8abf0c494446a975f62ed8c5821", + "lib/setuptools/_distutils/__init__.pyc": "5d6b1fc56dbd85a39e5faea0a99726a8e9644c2857177c429eb663d89fb592b5", + "lib/setuptools/_distutils/_log.pyc": "3ed66e4138f22c9554ab1cc0cfe468a9a780763682b8495383a22bbcaba60e1e", + "lib/setuptools/_distutils/_macos_compat.pyc": "a35ac44813f4e8f7b6232db77dc278a9fe4ccc23ef2bb775153d6a397e83deaa", + "lib/setuptools/_distutils/_modified.pyc": "f8ec04d5ffcec4b2e203ebb5e7602ef1fee3b931cfe880eeeb51f9910fead4c2", + "lib/setuptools/_distutils/_msvccompiler.pyc": "3491dec42373a3301da6e2da247a070863592916e24580e4ccf2292c9c43d3a3", + "lib/setuptools/_distutils/archive_util.pyc": "165dc6d93ff7a8da8f75b78755a5559cb387c840de5af41c6b590e951cb55b08", + "lib/setuptools/_distutils/ccompiler.pyc": "517aff4705c920669387a61e5b34d689c079e84d9280592d2ee50a16928a5433", + "lib/setuptools/_distutils/cmd.pyc": "08a3f84cf751293802e847fa2d9ed295354b3221d09daef18044a40d85381bb3", + "lib/setuptools/_distutils/command/__init__.pyc": "2d075e3f21da0c4d471ed47120bec50a0b35205eb3cfe0e4fb3f514a851d4ff0", + "lib/setuptools/_distutils/command/_framework_compat.pyc": "678b01fde295ac6590bfc5af7be15263f37506df5e17f930fc709101afa958cf", + "lib/setuptools/_distutils/command/bdist.pyc": "4a20601768f8edfa314fd206b14c8091b7725332ea0754fbb04ee6fb0e93e25d", + "lib/setuptools/_distutils/command/bdist_dumb.pyc": "f7403b134d695016dcd467fd91b5ce0a8456be99d55a59cdf08f5992e4db0b22", + "lib/setuptools/_distutils/command/bdist_rpm.pyc": "9f4564a5d973e75775341c57befaf3aa9b21d3f10cb4e87d482a574f2e7eac76", + "lib/setuptools/_distutils/command/build.pyc": "f8969465559a49fe4fa7baf6b81e206c6970f98fba09e57bb22c658e8af49614", + "lib/setuptools/_distutils/command/build_clib.pyc": "a573ce90df61c81cc7855ad7cd601f9157782acdd3840546dfca0491281f95ec", + "lib/setuptools/_distutils/command/build_ext.pyc": "f5d330923dca3c6aa34422a3de713e68f82aa0322b39e772b9a410c55d3ff52e", + "lib/setuptools/_distutils/command/build_py.pyc": "ac4931fe785d2636b01f9b81e851b04803e7b85c3caa679e13b2e3501a5a5c00", + "lib/setuptools/_distutils/command/build_scripts.pyc": "17986ae879004f001c6d66d418b350d2714a493b58be066436b3d0dcb8dfbf4a", + "lib/setuptools/_distutils/command/check.pyc": "4722e26b78bf1b838550346b785d6d74481420bd49f5b052567b93a2260b79c4", + "lib/setuptools/_distutils/command/clean.pyc": "d2554107c51c85aa857c6c86645c78419a6689ed8a768b85fa96b12de50af052", + "lib/setuptools/_distutils/command/config.pyc": "4868af24fac22ed791f9bd52e8560a582872348b6cc1bf4ab69f31e7fd812181", + "lib/setuptools/_distutils/command/install.pyc": "4bfb5e0e58f8c818d9716da62819884e2bf2a9e2fd05d301f4648b2ed4d96027", + "lib/setuptools/_distutils/command/install_data.pyc": "ff8599f6d06b00ba99f8aef9186f71d537ab5c68d24b5453126c69c28549702c", + "lib/setuptools/_distutils/command/install_egg_info.pyc": "7475123707219c4c753bf62f65c9d3da45f8bcc5940fac1fea8c58479201a4b9", + "lib/setuptools/_distutils/command/install_headers.pyc": "27b1eaa5eb7d751905506275b0d9499a8069a5544bf220a3d5a8601c6729a5ab", + "lib/setuptools/_distutils/command/install_lib.pyc": "78ae93358bfa272914a1c5a48c092c1262b00a2b78145efbc34ae4657b5193c9", + "lib/setuptools/_distutils/command/install_scripts.pyc": "d8e761f7264049bd4ec5aeb67fef51415de3b45552bc40c3d0f7715119a7886a", + "lib/setuptools/_distutils/command/sdist.pyc": "56c881265de61c0605f9a18c2c06f63c1ebe9d6eea69e9289a55fd1dd2b1854b", + "lib/setuptools/_distutils/compat/__init__.pyc": "918a4ff525ef6df594d098c1f583235c98653860152db517614ee5632648aebe", + "lib/setuptools/_distutils/compat/numpy.pyc": "dac5da5c94e257faa3b89ad9e642592b857dd060061e5227d307812e124bf483", + "lib/setuptools/_distutils/compat/py39.pyc": "e2ae21acd523b15546fcf13836e654492acdcb5b0fe4596e98e662e2ad8db5e0", + "lib/setuptools/_distutils/compilers/C/base.pyc": "0438999c505adff869a4256a369cd39bd313e7855976e240884e095f0661936a", + "lib/setuptools/_distutils/compilers/C/cygwin.pyc": "62ef211159001b12901b36b2d52cec7511f6d787f174645549d45c3875a1650e", + "lib/setuptools/_distutils/compilers/C/errors.pyc": "ce33835d48fae25e423baea22e3e2a001179a802d029a08bbc0d56e1c20c0a43", + "lib/setuptools/_distutils/compilers/C/msvc.pyc": "71c204c6aa9a48932cafc14e53923373d1d18f20be90e81817b6de37498e955e", + "lib/setuptools/_distutils/compilers/C/unix.pyc": "6d56f19f72161e6ea1983b29bc5894e85294dee808dc366d739496a0deb43695", + "lib/setuptools/_distutils/compilers/C/zos.pyc": "72ad03dba0a690637c324df7db6803f7b6ac98327f2e7e681c4a64c1fc683141", + "lib/setuptools/_distutils/core.pyc": "17b3e8e46af16b6687c5597c728a55f30af73cfa9e05902672e4df960b5d7a46", + "lib/setuptools/_distutils/cygwinccompiler.pyc": "318a17c0c9397256a589f50e8e60e376cae0394650612c21537103758977b1d6", + "lib/setuptools/_distutils/debug.pyc": "e55b43b5be9a165315eb59054729691127dfe624b19610d32529b59a4c368f15", + "lib/setuptools/_distutils/dep_util.pyc": "b418d730e346f2210d314bab075a7cbe6412047da98fd17aad222c1fd605bf36", + "lib/setuptools/_distutils/dir_util.pyc": "faa111ff17cd44a67267960db9ad09c0986d330d6d440bce033cc0d5545f1357", + "lib/setuptools/_distutils/dist.pyc": "415de9e2264201784b1493b13d441e62d35ff4aede0ecaf69b9611da40589c9f", + "lib/setuptools/_distutils/errors.pyc": "a5553b4b1f6d42f1382967400450a3c259c6b6f3e9b5cd12c15b0c3d76f8b025", + "lib/setuptools/_distutils/extension.pyc": "5a1835f5888a21e862bfd46088a57d85e26d700498db006699760d11211bbfe8", + "lib/setuptools/_distutils/fancy_getopt.pyc": "2255b09b011ddcab6d6539c26ecc081eac8c84d0de4704b06d4def70b78db2ea", + "lib/setuptools/_distutils/file_util.pyc": "1c0d53a8c4686b80e2bdcfa6e1cf6bdc8e8d8ad5a095dc50cac73f8970d768a0", + "lib/setuptools/_distutils/filelist.pyc": "db66985cbfce8868ee1183c56829dd17a368cbeea2d7dea68997c1c198203982", + "lib/setuptools/_distutils/log.pyc": "967d9984aa6a25aceb5e27a89dca2f50dd895ed9d96effb8c0612624ff0a318b", + "lib/setuptools/_distutils/spawn.pyc": "5cedcac358fe16926cbbf081f70036724d085d891e5b2d5a48d59bf6a0b486ae", + "lib/setuptools/_distutils/sysconfig.pyc": "c7cfcaec9be6f299df45f12a6fde7313cfba82398346c66da021e746a1dc3036", + "lib/setuptools/_distutils/text_file.pyc": "f4e42f724d5b66d193e7c07529fba4af4d4cbd2c2410b02c744a48cfacde5f87", + "lib/setuptools/_distutils/unixccompiler.pyc": "753bb3b9d9040535303d05be4080e563b1a55666f748edee4f73e73f42aa0303", + "lib/setuptools/_distutils/util.pyc": "74900571b2bd89b509825887ea7849722d5dca22d74528695dc67131794a97c4", + "lib/setuptools/_distutils/version.pyc": "ed920c7dcc767bee93769022c1f246afec19452336a520ed4a6151b0cf05c52a", + "lib/setuptools/_distutils/versionpredicate.pyc": "ff2380d11a2b2177468326b68978e8fc3f487b35dc32078b8cf4668b9995f6cd", + "lib/setuptools/_distutils/zosccompiler.pyc": "ddc9ef4261ca4fc9dda17e7985ffb38fdd450bc4491f72d339b42c189e81e93c", + "lib/setuptools/_imp.pyc": "e2ab24836941947ad05e65b2b119be4932da8e27a4d5cfdbac875dc0ddffe02e", + "lib/setuptools/_importlib.pyc": "f713396fd3bd77c7f1ddd64e0bb72991cb318dd0de39de09bea5ea31874049b0", + "lib/setuptools/_normalization.pyc": "5ee14886d6b8fb60a6383e3c744d1787bf013a1a97fae37d0d911ea48d8d2e84", + "lib/setuptools/_path.pyc": "69f9fe50b629fe4b1cc559d7184f220835e7837fbcefa49e67a83f6b455cb859", + "lib/setuptools/_reqs.pyc": "338523f37de53a59c530dd870e714023d62c5a61a89aeccf019e65ffabfd7fed", + "lib/setuptools/_static.pyc": "689c18d5a89ea7319f600627ca9b42f8e8d24818e70cf7ea9b302437bcb2c3c5", + "lib/setuptools/_vendor/autocommand/__init__.pyc": "1c6d6a938b23fa22287fa927975884bc829f868801d01912b3b32d4b9eb6bb42", + "lib/setuptools/_vendor/autocommand/autoasync.pyc": "d0e2d1c92cf108f583c714186ee1fd13bc28176bcdf86c1d1c31ee158abb37aa", + "lib/setuptools/_vendor/autocommand/autocommand.pyc": "8d78983394a79042c5e85e1951cc9fc275ae9dc023c48eefba4a86a3d1aa24f6", + "lib/setuptools/_vendor/autocommand/automain.pyc": "6ccca5427d8efb100923ed66ed888899e2224e964c3a049bec6539ba78d174f0", + "lib/setuptools/_vendor/autocommand/autoparse.pyc": "330a5257bb427bdb031c928dc3ce9ef5aeaf507f5c029f923b484807982f4cba", + "lib/setuptools/_vendor/autocommand/errors.pyc": "af6ea000c063683861bf5d72248c5e662cf3f0f9e16bb353bf64a5c89a0b0282", + "lib/setuptools/_vendor/autocommand-2.2.2.dist-info/INSTALLER": "ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508", + "lib/setuptools/_vendor/autocommand-2.2.2.dist-info/LICENSE": "ade78d04982d69972d444a8e14a94f87a2334dd3855cc80348ea8e240aa0df2d", + "lib/setuptools/_vendor/autocommand-2.2.2.dist-info/METADATA": "3800d9b91dceea2065a6ed6279383362e97ac38b8e56b9343f404ee531860099", + "lib/setuptools/_vendor/autocommand-2.2.2.dist-info/RECORD": "822bba66b41526fa547186b80221f85da50d652bee5493dbfe5d14085112f0c3", + "lib/setuptools/_vendor/autocommand-2.2.2.dist-info/WHEEL": "db07a93359e4e034b8785a58ad6d534ea3dca0635f1e184efe2e66e1c3a299ba", + "lib/setuptools/_vendor/autocommand-2.2.2.dist-info/top_level.txt": "0337e180a292f04740c16513485f2681e5506d7398f64a241c1ea44aac30aaed", + "lib/setuptools/_vendor/backports/__init__.pyc": "085128234369c2bb3f8239c4b02c02d6bece52391405172f0175ec1ddbc656fc", + "lib/setuptools/_vendor/backports/tarfile/__init__.pyc": "a6ce0e13ddda95e0f973d4cc78009d9fc46f37529d77c87da83f85c07fa6b0c2", + "lib/setuptools/_vendor/backports/tarfile/__main__.pyc": "c9e9413bc9ca5462e2c39db3937a0cd53aa0be29e3e123a0555d5a7c697af45f", + "lib/setuptools/_vendor/backports/tarfile/compat/__init__.pyc": "f338bc3f66e64a84928cbc54a5085b822318c49d191f03ffcd7132d4ff2cbc5d", + "lib/setuptools/_vendor/backports/tarfile/compat/py38.pyc": "44aef7221c4eadcfd49a2b10c3e8f9a063d83dba28cdf586ecf2c7fd9bae50d3", + "lib/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/INSTALLER": "ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508", + "lib/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/LICENSE": "86da0f01aeae46348a3c3d465195dc1ceccde79f79e87769a64b8da04b2a4741", + "lib/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/METADATA": "8215c54ead77d9dc5a108a25c6bdc72b5999aa6f62c9499a440359412afa5a51", + "lib/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/RECORD": "258a1f1c849e1175069a55a5d6ce357afdd04e34cd5de27093e4acec7a9d2ce1", + "lib/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/REQUESTED": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "lib/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/WHEEL": "189eedfe4581172c1b6a02b97a8f48a14c0b5baa3239e4ca990fbd8871553714", + "lib/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/top_level.txt": "7068da2cc3a8051d452b4029a23b73595995893b49ec91882bf1f05e212cbed5", + "lib/setuptools/_vendor/importlib_metadata/__init__.pyc": "834c963950e11d31f4f0cde0ee5a56269a5143c81e51689673a8cce79c7eb11c", + "lib/setuptools/_vendor/importlib_metadata/_adapters.pyc": "111a1f2ae156b00c6fbe0e3cf30c0cbf39ac4aa45285de26cb6730e6c4f8d9cc", + "lib/setuptools/_vendor/importlib_metadata/_collections.pyc": "9436c76bf6693b7f0b9037021b95a2b43f84b097f6a4f368514e7e920c068d02", + "lib/setuptools/_vendor/importlib_metadata/_compat.pyc": "edd20770f0c1ed3def1b6874e26aa1ed19300c3190ff7d9000168e81dcba3f67", + "lib/setuptools/_vendor/importlib_metadata/_functools.pyc": "089118cbb7a3b339f221a12ee1923173e4a2634c455abdab28184248c0d946e1", + "lib/setuptools/_vendor/importlib_metadata/_itertools.pyc": "f315772be3a93a50c979dc3d116618134484baf41c3d7f4c18773425fd9c5b2b", + "lib/setuptools/_vendor/importlib_metadata/_meta.pyc": "b158e3785a3a3ddaabb656ab5a4219ff0c4ed899c88950624456f17e6941ac4f", + "lib/setuptools/_vendor/importlib_metadata/_text.pyc": "ae8cbd0420ea34f8abee2dce00709776df5d27d418d60dff37efb2a522b57526", + "lib/setuptools/_vendor/importlib_metadata/compat/__init__.pyc": "14ed77dddd24974603d0dcc3cf336adb000d7e80bcbbdf6f63cabbecc2cd89be", + "lib/setuptools/_vendor/importlib_metadata/compat/py311.pyc": "0066b947bccf1de3fe6070e4288b4439b4b671e3f80a80096a444994ddc2ef06", + "lib/setuptools/_vendor/importlib_metadata/compat/py39.pyc": "110903562a93ab26290ac40decdd6f6ad07f1ad7c939805b1c6a9383f8cb111d", + "lib/setuptools/_vendor/importlib_metadata/diagnose.pyc": "a4b69f716008d54e8c1b94b1627a4cfa8473716835822cdd038401f8a1af8850", + "lib/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/INSTALLER": "ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508", + "lib/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/LICENSE": "cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30", + "lib/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/METADATA": "6a7b90effee1e09d5b484cdf7232016a43e2d9cc9543bcbb8e494b1ec05e1f59", + "lib/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/RECORD": "0d8d3c6eeb9ebbe86cac7d60861552433c329da9ea51248b61d02be2e5e64030", + "lib/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/REQUESTED": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "lib/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/WHEEL": "9a0b8c95618c5fe5479cca4a3a38d089d228d6cb1194216ee1ae26069cf5b363", + "lib/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/top_level.txt": "08eddf0fdcb29403625e4acca38a872d5fe6a972f6b02e4914a82dd725804fe0", + "lib/setuptools/_vendor/inflect/__init__.pyc": "b719ca22fc8620f81f83bc6b53a6722eee287a4d0236a5312a8aba18c65fe69c", + "lib/setuptools/_vendor/inflect/compat/__init__.pyc": "82639416e0784e7c14b54584863a156f39183003807c128ecb66148984223d33", + "lib/setuptools/_vendor/inflect/compat/py38.pyc": "fabcb6a9aeb7fdc6252cb0200ec37a066d8e850b42ccd375ecb202e1e45e8f3a", + "lib/setuptools/_vendor/inflect-7.3.1.dist-info/INSTALLER": "ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508", + "lib/setuptools/_vendor/inflect-7.3.1.dist-info/LICENSE": "86da0f01aeae46348a3c3d465195dc1ceccde79f79e87769a64b8da04b2a4741", + "lib/setuptools/_vendor/inflect-7.3.1.dist-info/METADATA": "66030d634580651b3e53cc19895d9231f8d22aa06b327817c8332cfc20303308", + "lib/setuptools/_vendor/inflect-7.3.1.dist-info/RECORD": "5d7834ac1ba2612c6801050fde57a7b98b0f36acf88c3c2d4f376fd8911b3091", + "lib/setuptools/_vendor/inflect-7.3.1.dist-info/WHEEL": "cb8997f92397e1f6089289ec0060393743b2fbcfe0238157c391cd235c6abd68", + "lib/setuptools/_vendor/inflect-7.3.1.dist-info/top_level.txt": "9b9dae8dda75d02a93ea38755d0c594fa9049ed727bfeed397b52218d4f35990", + "lib/setuptools/_vendor/jaraco/text/Lorem ipsum.txt": "37fedcffbf73c4eb9f058f47677cb33203a436ff9390e4d38a8e01c9dad28e0b", + "lib/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/INSTALLER": "ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508", + "lib/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/LICENSE": "86da0f01aeae46348a3c3d465195dc1ceccde79f79e87769a64b8da04b2a4741", + "lib/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/METADATA": "20c51a96236c0395f53b1f4c5d458e6a0721e51e16c1bff733b7aba76f5d06d8", + "lib/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/RECORD": "1e9b62bd70e4a5fa26e9594cbb80860ffeca3debfee8773daefa774cd259ca06", + "lib/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/REQUESTED": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "lib/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/WHEEL": "31d8bd3c3370119a6d3a34e551c02d87b5c90c5b4aac761a40c3ee9597810a24", + "lib/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/top_level.txt": "d099cddcb7d71f82c845f5cbf9014e18227341664edc42f1e11d5dfe5a2ea103", + "lib/setuptools/_vendor/jaraco.context-5.3.0.dist-info/INSTALLER": "ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508", + "lib/setuptools/_vendor/jaraco.context-5.3.0.dist-info/LICENSE": "86da0f01aeae46348a3c3d465195dc1ceccde79f79e87769a64b8da04b2a4741", + "lib/setuptools/_vendor/jaraco.context-5.3.0.dist-info/METADATA": "c43b60b897a3d2d37d8845c252fc44261d9aef171e21154111a9012d2afffed6", + "lib/setuptools/_vendor/jaraco.context-5.3.0.dist-info/RECORD": "55197b88a78443297bb2d827a75baae740b33896251d872835d4b4c75ec2f57e", + "lib/setuptools/_vendor/jaraco.context-5.3.0.dist-info/WHEEL": "189eedfe4581172c1b6a02b97a8f48a14c0b5baa3239e4ca990fbd8871553714", + "lib/setuptools/_vendor/jaraco.context-5.3.0.dist-info/top_level.txt": "d099cddcb7d71f82c845f5cbf9014e18227341664edc42f1e11d5dfe5a2ea103", + "lib/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/INSTALLER": "ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508", + "lib/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/LICENSE": "86da0f01aeae46348a3c3d465195dc1ceccde79f79e87769a64b8da04b2a4741", + "lib/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/METADATA": "8b86946900d7fa38dd1102b9c1ebe17a0cb1f09c8b7e29f61f2bda4a4dc51eca", + "lib/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/RECORD": "632aa7c04f7c4bcc01c027af5b9bc76fe8958f4a181035b957a3bd3014ba248b", + "lib/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/WHEEL": "189eedfe4581172c1b6a02b97a8f48a14c0b5baa3239e4ca990fbd8871553714", + "lib/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/top_level.txt": "d099cddcb7d71f82c845f5cbf9014e18227341664edc42f1e11d5dfe5a2ea103", + "lib/setuptools/_vendor/jaraco.text-3.12.1.dist-info/INSTALLER": "ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508", + "lib/setuptools/_vendor/jaraco.text-3.12.1.dist-info/LICENSE": "86da0f01aeae46348a3c3d465195dc1ceccde79f79e87769a64b8da04b2a4741", + "lib/setuptools/_vendor/jaraco.text-3.12.1.dist-info/METADATA": "03359d9ba56231f0ce3e840c7cb5a7db380141218949ccaa78ddbd4dcb965d52", + "lib/setuptools/_vendor/jaraco.text-3.12.1.dist-info/RECORD": "816d945741dca246099388ca3eed74fc0667acbaa36f70b559b2494c3979b1f6", + "lib/setuptools/_vendor/jaraco.text-3.12.1.dist-info/REQUESTED": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "lib/setuptools/_vendor/jaraco.text-3.12.1.dist-info/WHEEL": "189eedfe4581172c1b6a02b97a8f48a14c0b5baa3239e4ca990fbd8871553714", + "lib/setuptools/_vendor/jaraco.text-3.12.1.dist-info/top_level.txt": "d099cddcb7d71f82c845f5cbf9014e18227341664edc42f1e11d5dfe5a2ea103", + "lib/setuptools/_vendor/more_itertools/__init__.pyc": "65058cd7373852a42523deeda9809d69df5877cf81babab61b324cf6635a07e6", + "lib/setuptools/_vendor/more_itertools/more.pyc": "fa0b3fb01b97a6b0570ad96d230f6fc6dcdaace03829d206e4814527514d9781", + "lib/setuptools/_vendor/more_itertools/recipes.pyc": "7e6f88cd5eae58c559870a0a12410448baf7d6e28d8dda31e4ae20fee6fa2b68", + "lib/setuptools/_vendor/more_itertools-10.3.0.dist-info/INSTALLER": "ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508", + "lib/setuptools/_vendor/more_itertools-10.3.0.dist-info/LICENSE": "09f1c8c9e941af3e584d59641ea9b87d83c0cb0fd007eb5ef391a7e2643c1a46", + "lib/setuptools/_vendor/more_itertools-10.3.0.dist-info/METADATA": "0453bdd0ef9f2cd89540ca63ee8212e73b73809514419dd3037d8fe471f737e0", + "lib/setuptools/_vendor/more_itertools-10.3.0.dist-info/RECORD": "77c8e73e018dc0fd7e9ed6c80b05a4404545f641fb085220ce42b368b59aa3d3", + "lib/setuptools/_vendor/more_itertools-10.3.0.dist-info/REQUESTED": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "lib/setuptools/_vendor/more_itertools-10.3.0.dist-info/WHEEL": "ad282afc9a4717d7c7475971e77ab083fd7ed8bca9644fea99cb976d552af78f", + "lib/setuptools/_vendor/packaging/__init__.pyc": "9ae6f1c09b44368762ef76c093baa7559176c68e624d4c9a881edd475794bbff", + "lib/setuptools/_vendor/packaging/_elffile.pyc": "3885f21e9eee991207169c5a1a6baffbe2c39523a3b823e2ad80eb21add424b2", + "lib/setuptools/_vendor/packaging/_manylinux.pyc": "4051d1234d15c8f49330aa850d0b7bbb102c9537e90265403cd3a4356d6c3967", + "lib/setuptools/_vendor/packaging/_musllinux.pyc": "c5f2af63c0819cd3054e58dac1abcdd15548aff4665fefd1067401ba366dd5f4", + "lib/setuptools/_vendor/packaging/_parser.pyc": "47e7759ebca0a29c2e0bc7ba7273375cff17382b93d58eaaddd5d3a3266abfcc", + "lib/setuptools/_vendor/packaging/_structures.pyc": "a5b67eab498b6b0300257eb0b3f1b98c7b28d2d76b8a94638df3243e1daedc43", + "lib/setuptools/_vendor/packaging/_tokenizer.pyc": "f513b146566012e924a9add4f4331a0dee1f59f413536a2c6c302f9d05be7e29", + "lib/setuptools/_vendor/packaging/licenses/__init__.pyc": "98b8393b8b27f265d1518a70db00e87943da882ab105fd012d6e8665c753c9d2", + "lib/setuptools/_vendor/packaging/licenses/_spdx.pyc": "1d44480711bab74897516c7ca943ce474826158582999115adc47d36a887cf49", + "lib/setuptools/_vendor/packaging/markers.pyc": "10f94dc673424e06f99a68da3751f4c3783946236923e17cb48a422bb9714740", + "lib/setuptools/_vendor/packaging/metadata.pyc": "0c417fbfe2045f6e9feeb8cceb5a8fdaa0430ce7487bac86d99570aaaec4dfc4", + "lib/setuptools/_vendor/packaging/requirements.pyc": "ff923482a14a4cd395ff71f1c51642cefffa941a7f301376663f9377ce878656", + "lib/setuptools/_vendor/packaging/specifiers.pyc": "9163141979beb891133567deb72874c04feee0ea176baa07c18369206cecae4c", + "lib/setuptools/_vendor/packaging/tags.pyc": "fdcf20fc9020a70effaed5a5d7aca84987379efb01a8567660a2eda49262ce0b", + "lib/setuptools/_vendor/packaging/utils.pyc": "27977159578170527ffd3c7ffe20dd7b38568d7de669904410848ba01e14056c", + "lib/setuptools/_vendor/packaging/version.pyc": "dda316931bbd4cafa3bc1fb5c21fb1519ba60db618646caac8f4674f2a689b36", + "lib/setuptools/_vendor/packaging-24.2.dist-info/INSTALLER": "e6184ce10e266134fdcfa401e8f1a95005bcd4f18d16b62b757323e2833fe9a9", + "lib/setuptools/_vendor/packaging-24.2.dist-info/LICENSE": "cad1ef5bd340d73e074ba614d26f7deaca5c7940c3d8c34852e65c4909686c48", + "lib/setuptools/_vendor/packaging-24.2.dist-info/LICENSE.APACHE": "0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594", + "lib/setuptools/_vendor/packaging-24.2.dist-info/LICENSE.BSD": "b70e7e9b742f1cc6f948b34c16aa39ffece94196364bc88ff0d2180f0028fac5", + "lib/setuptools/_vendor/packaging-24.2.dist-info/METADATA": "a211fceacea4e6621f4316364d2d0b7127c00de3856b8062082f9bc5957ea4db", + "lib/setuptools/_vendor/packaging-24.2.dist-info/RECORD": "6380eb5ccd0a63402b7f385b0046b52d814fc16dd612011e2f8882a977be03e3", + "lib/setuptools/_vendor/packaging-24.2.dist-info/REQUESTED": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "lib/setuptools/_vendor/packaging-24.2.dist-info/WHEEL": "0a950253178741b44de54191407611268acee407fe432fdf1cc72d710f034862", + "lib/setuptools/_vendor/platformdirs/__init__.pyc": "65ff81dd8c80f3cf3011ba3e6b77b329d71f94ae9cd15c4567b690e0edd4a0a4", + "lib/setuptools/_vendor/platformdirs/__main__.pyc": "edfcbc8c3332d9a3394beb33e8a23337ab5e4ec17e6dbfb86a391f76dce396af", + "lib/setuptools/_vendor/platformdirs/android.pyc": "fa0679c386e91566f48917ba878e75d163664b26c25b3a0289e2b9d9e26502df", + "lib/setuptools/_vendor/platformdirs/api.pyc": "c1e0e07068d32aa50b04ce5f25632d683b34198e03acc81a5bfeb08de951e5ca", + "lib/setuptools/_vendor/platformdirs/macos.pyc": "3d1590df12d9f2206c5e1d840325f068a8d0aa073ed2cca6f31277c0bd317396", + "lib/setuptools/_vendor/platformdirs/unix.pyc": "eec82c97c689dbb3d4532d0d775d51de3bdfb1e6ba5b36e6f1a7d3e37e0ed3eb", + "lib/setuptools/_vendor/platformdirs/version.pyc": "03043acda00803c67f4dcc31ae1d497b6be3386f2f3cf421020f0b51059fec74", + "lib/setuptools/_vendor/platformdirs/windows.pyc": "64527f610490c983d90c308a7d2d02ed71a87f0ccd05f8abd852dcec850e85a9", + "lib/setuptools/_vendor/platformdirs-4.2.2.dist-info/INSTALLER": "ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508", + "lib/setuptools/_vendor/platformdirs-4.2.2.dist-info/METADATA": "ce6b227b4d46d4cb57474c2022fe57a557933bb89daf4596bdf9b12ac296b869", + "lib/setuptools/_vendor/platformdirs-4.2.2.dist-info/RECORD": "4c211d76d42ed40efc3acfcc866d8912a718afbca2b7e51849442366d6e99fe8", + "lib/setuptools/_vendor/platformdirs-4.2.2.dist-info/REQUESTED": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "lib/setuptools/_vendor/platformdirs-4.2.2.dist-info/WHEEL": "cc431c46bf4aaf4df1d68cc6c20e6ff4d4012a7de49dda7a2d2a1295583e8e15", + "lib/setuptools/_vendor/platformdirs-4.2.2.dist-info/licenses/LICENSE": "29e0fd62e929850e86eb28c3fdccf0cefdf4fa94879011cffb3d0d4bed6d4db6", + "lib/setuptools/_vendor/tomli/__init__.pyc": "f96b0c56dde61b4c0b4fa25caa4e1f4e0a2db1d5d67550651e9f6eecd7f83b67", + "lib/setuptools/_vendor/tomli/_parser.pyc": "bdd5c6db222aebd6e7b4934e510d539df2d00df65433f5cdae90f0f381aa1889", + "lib/setuptools/_vendor/tomli/_re.pyc": "ca908493e34ef46e9688879c6dc448bd9fd065bd43de18c9d852ac83b51f3626", + "lib/setuptools/_vendor/tomli/_types.pyc": "46f588e62c31bcc8a36cc5e5a52cf31c83859d5f34e0016dd54ee1f5141f4d7b", + "lib/setuptools/_vendor/tomli-2.0.1.dist-info/INSTALLER": "ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508", + "lib/setuptools/_vendor/tomli-2.0.1.dist-info/LICENSE": "b80816b0d530b8accb4c2211783790984a6e3b61922c2b5ee92f3372ab2742fe", + "lib/setuptools/_vendor/tomli-2.0.1.dist-info/METADATA": "ccf0dc78a98fc0918b5ad67292b1e2c4bed65575a6246cd9d63c914f9942a0f2", + "lib/setuptools/_vendor/tomli-2.0.1.dist-info/RECORD": "0cb9f9a451a1e365ac54b4c88662e1da0cb54a72d16a5258fb0abff9d3e1c022", + "lib/setuptools/_vendor/tomli-2.0.1.dist-info/REQUESTED": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "lib/setuptools/_vendor/tomli-2.0.1.dist-info/WHEEL": "8cf311fc3ce47385f889c42d9b3f35967358fe402c7e883baf2eeaa11bd82d7c", + "lib/setuptools/_vendor/typeguard/__init__.pyc": "c912d3efca1e979b13f7ffa7162817c075d61305b2b81b7a92ef8d5105449bd2", + "lib/setuptools/_vendor/typeguard/_checkers.pyc": "f1ab52a82c59f73cec269b2d672105bb5fa4b4da064ef7ffe36009b155d9f88e", + "lib/setuptools/_vendor/typeguard/_config.pyc": "9a9ae2f5a31c9e25038f366b7df049a4d8cf5cff2c5fbab3b24a695136621e6c", + "lib/setuptools/_vendor/typeguard/_decorators.pyc": "f18d29582699503556ba836ddbe95492cde71f42bd945e2455aff88e4f88cf13", + "lib/setuptools/_vendor/typeguard/_exceptions.pyc": "679cbd8738ebff824f1f93e8eee4a45cd1016153cef9d9f834403400df0524b1", + "lib/setuptools/_vendor/typeguard/_functions.pyc": "f4bfe57f308d4a855f4c737ed6d8ff953f544fc60f2efec0ea53c5fc07da1e3c", + "lib/setuptools/_vendor/typeguard/_importhook.pyc": "ebdc8292dbf327da88e781f08cf9c3550c103570cf80ebcce4b81f2e4c493665", + "lib/setuptools/_vendor/typeguard/_memo.pyc": "65545f2891f79c8a52febcbe9098a6bcb0feb07c4b459c3effa15d678dd6db47", + "lib/setuptools/_vendor/typeguard/_pytest_plugin.pyc": "941edcbbd711086008723b56c195941c8117aad6c94b50ef5d74110e60ecaea9", + "lib/setuptools/_vendor/typeguard/_suppression.pyc": "e6e507e7cfc350d9f6b907975d0f7943bc332bb498e6659b05a8ea00a315e76b", + "lib/setuptools/_vendor/typeguard/_transformer.pyc": "0f67999f8f29e39bc2edce3f5c83d8d0d520a9bc0a45ea626a461c51c9b1b2c4", + "lib/setuptools/_vendor/typeguard/_union_transformer.pyc": "2f4cd5204e9b42ce5a168ee891dc809489b49c4e5c08f5dbd8b1a3892e1dacfd", + "lib/setuptools/_vendor/typeguard/_utils.pyc": "efb378b884de6a04f947d349cabca47ec12b4b7774cd136cb523412e2596edfb", + "lib/setuptools/_vendor/typeguard-4.3.0.dist-info/INSTALLER": "ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508", + "lib/setuptools/_vendor/typeguard-4.3.0.dist-info/LICENSE": "6163f7987dfb38d6bc320ce2b70b2f02b862bc41126516d552ef1cd43247e758", + "lib/setuptools/_vendor/typeguard-4.3.0.dist-info/METADATA": "cf675c1c0a744f08580855390de87cc77d676b312582e8d4cfdb5bb8fd298d21", + "lib/setuptools/_vendor/typeguard-4.3.0.dist-info/RECORD": "48a51959582478352275428ceecd78ef77d79ac9dae796e39a2eaf2540282552", + "lib/setuptools/_vendor/typeguard-4.3.0.dist-info/WHEEL": "189eedfe4581172c1b6a02b97a8f48a14c0b5baa3239e4ca990fbd8871553714", + "lib/setuptools/_vendor/typeguard-4.3.0.dist-info/entry_points.txt": "aa9ecd43568bb624a0310aa8ea05a57c6a72d08217ce830999e4132e9cea1594", + "lib/setuptools/_vendor/typeguard-4.3.0.dist-info/top_level.txt": "e33dbc021b83a1dc114bf73527f97c1f9d6de50bb07d3b1eb24633971a7a82bb", + "lib/setuptools/_vendor/typing_extensions-4.12.2.dist-info/INSTALLER": "ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508", + "lib/setuptools/_vendor/typing_extensions-4.12.2.dist-info/LICENSE": "3b2f81fe21d181c499c59a256c8e1968455d6689d269aa85373bfb6af41da3bf", + "lib/setuptools/_vendor/typing_extensions-4.12.2.dist-info/METADATA": "05e51021af1c9d86eb8d6c7e37c4cece733d5065b91a6d8389c5690ed440f16d", + "lib/setuptools/_vendor/typing_extensions-4.12.2.dist-info/RECORD": "7710002d81971e632aa6a2fc33dc5d74aaf5d7caae22040a65d3e31503b05ee9", + "lib/setuptools/_vendor/typing_extensions-4.12.2.dist-info/WHEEL": "1196c6921ec87b83e865f450f08d19b8ff5592537f4ef719e83484e546abe33e", + "lib/setuptools/_vendor/typing_extensions.pyc": "da914b270569d34f1bae6d27ec4e2f52f4d03767f92117e784d31ace7ecde8e2", + "lib/setuptools/_vendor/wheel/__init__.pyc": "d5c10bb617a24a86afb1c56a2e0d9107ab3cb397cedb9d3138a055838c15459f", + "lib/setuptools/_vendor/wheel/__main__.pyc": "abbf5b5996f1aa202c61163304ab94df1f69db694c736030a8169932c35ee06e", + "lib/setuptools/_vendor/wheel/_bdist_wheel.pyc": "edfbde80971d0fd4d96e4dcac67a757e5b31bc3ac3920087504fe822e75a1a5c", + "lib/setuptools/_vendor/wheel/_setuptools_logging.pyc": "ce6ed48f25f3f5c4651574093fdb37b94fcd88f808b0300ab4bd9dd759c734e5", + "lib/setuptools/_vendor/wheel/bdist_wheel.pyc": "3bfc54ab80ddc1299d8ea6a25d390adcdb198618a14c89bfc071f8e9bac96bb4", + "lib/setuptools/_vendor/wheel/cli/__init__.pyc": "c80f421d6b5af5b9e094d0086db167294818ade74c47135e23a13593815e851f", + "lib/setuptools/_vendor/wheel/cli/convert.pyc": "fe81be5feeacd3d287741796503097a99e976ded49c413e1be13797f45aed3fd", + "lib/setuptools/_vendor/wheel/cli/pack.pyc": "9713017518881a6a83abdc7d22e30e302464d3be3e215b891e96ca7fe8ede639", + "lib/setuptools/_vendor/wheel/cli/tags.pyc": "d6993d6591fa80e6f090a24c003191f6cb3525d313a82089ee5e04b7b7a4c422", + "lib/setuptools/_vendor/wheel/cli/unpack.pyc": "6fbe749e710f9408d14e7ead0299aa078ff3bd0e9a996ea4606818722e5a12e0", + "lib/setuptools/_vendor/wheel/macosx_libfile.pyc": "615fe94e4801b02e811bc90c5bf20a2c5c402eed6d24625bb945ac254aa40326", + "lib/setuptools/_vendor/wheel/metadata.pyc": "1e305bcafff7e20f40b5f5f42f62aa7249ffc810908bf85dc8717c77008e8b85", + "lib/setuptools/_vendor/wheel/util.pyc": "e3793859a800b732ac60f4158e913cdee8f1de9d97f458b670da2300a276f102", + "lib/setuptools/_vendor/wheel/vendored/__init__.pyc": "3a7e03c84717209bea060e233bbf022676c7568ed6e02f623bd5d424bb840015", + "lib/setuptools/_vendor/wheel/vendored/packaging/LICENSE": "cad1ef5bd340d73e074ba614d26f7deaca5c7940c3d8c34852e65c4909686c48", + "lib/setuptools/_vendor/wheel/vendored/packaging/LICENSE.APACHE": "0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594", + "lib/setuptools/_vendor/wheel/vendored/packaging/LICENSE.BSD": "b70e7e9b742f1cc6f948b34c16aa39ffece94196364bc88ff0d2180f0028fac5", + "lib/setuptools/_vendor/wheel/vendored/packaging/__init__.pyc": "b177dd2a3fb4dc4581d9929f2efda9aa7ac370e430a6ed5de0b3a2c9fd437ee8", + "lib/setuptools/_vendor/wheel/vendored/packaging/_elffile.pyc": "b98cab395540172ad3cdfffa48da3b2ef18e439b40ddde4f4e0d2ff924ecd759", + "lib/setuptools/_vendor/wheel/vendored/packaging/_manylinux.pyc": "58c1e57ff7f36872857d53a699f8decde3f3f4aae8125e01ea5826a333bd9dca", + "lib/setuptools/_vendor/wheel/vendored/packaging/_musllinux.pyc": "2f7da77b3d7a2d40472fffd4bf2251926669d9de15fbc3becdac7ff35749d7fb", + "lib/setuptools/_vendor/wheel/vendored/packaging/_parser.pyc": "55a536757c40e98d34bdc4431e2640b5c6223ff3cfb015e3c74a5d34d4aa8a20", + "lib/setuptools/_vendor/wheel/vendored/packaging/_structures.pyc": "8a7ad858469a7b58fa6bdd8a78814cdaf1a1aceb6aba2af01ef3c323ccd2f200", + "lib/setuptools/_vendor/wheel/vendored/packaging/_tokenizer.pyc": "3bd98f43573e80dc2bd70cf6576853b243ebe31afa179c9d36b48b6776b1e93f", + "lib/setuptools/_vendor/wheel/vendored/packaging/markers.pyc": "d854880bb40388a58ac58f3de1ab1124b0dfbc020d94030dedd917327a44844f", + "lib/setuptools/_vendor/wheel/vendored/packaging/requirements.pyc": "f22a9bd65a07b931e95a484ec4a50912544c89ffc0179840be1bcf39e7748345", + "lib/setuptools/_vendor/wheel/vendored/packaging/specifiers.pyc": "e6014a95c1af1b45fd27be131887384bac99da4b8def122b95649c632ef2e044", + "lib/setuptools/_vendor/wheel/vendored/packaging/tags.pyc": "92b8dddb2e7e3259e39e352d3463fff77ff5fa36e006bf21f56d2bd540341609", + "lib/setuptools/_vendor/wheel/vendored/packaging/utils.pyc": "1f065e707e7b9a554dcba35ffedc70c0b41bb9f1ce6799c5829e76df85e14fc8", + "lib/setuptools/_vendor/wheel/vendored/packaging/version.pyc": "10da05712896d347c9abb41a267c6c730499a60956501378383c185a37c1bb0e", + "lib/setuptools/_vendor/wheel/vendored/vendor.txt": "67610d8c1d62e69adf7b3f0274cd5276bddce99c6fdab451a253292e60677001", + "lib/setuptools/_vendor/wheel/wheelfile.pyc": "36f5ea08c3d24a5c1f4efe3a1f30deebb9531e7d1a7fac602e0e0f1b8e61ad5b", + "lib/setuptools/_vendor/wheel-0.45.1.dist-info/INSTALLER": "ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508", + "lib/setuptools/_vendor/wheel-0.45.1.dist-info/LICENSE.txt": "30c23618679108f3e8ea1d2a658c7ca417bdfc891c98ef1a89fa4ff0c9828654", + "lib/setuptools/_vendor/wheel-0.45.1.dist-info/METADATA": "98acfce07ee6ee3b31272cde21c4d53918936f434f315dfd2af3886211a09a30", + "lib/setuptools/_vendor/wheel-0.45.1.dist-info/RECORD": "d639f1ac7c993c3715bd42f27c616189b6b86792fdfd1b17afd77170d6e16984", + "lib/setuptools/_vendor/wheel-0.45.1.dist-info/REQUESTED": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "lib/setuptools/_vendor/wheel-0.45.1.dist-info/WHEEL": "0a950253178741b44de54191407611268acee407fe432fdf1cc72d710f034862", + "lib/setuptools/_vendor/wheel-0.45.1.dist-info/entry_points.txt": "ad363505b90f1e1906326e10dc5d29233241cd6da4331a06d68ae27dfbc6740d", + "lib/setuptools/_vendor/zipp/__init__.pyc": "c6eaea617f04180f03b106c5790821a90b30fddc79aeac97e7c2245e378024cb", + "lib/setuptools/_vendor/zipp/compat/__init__.pyc": "2f01c14c3d42402c5995111e5ab356848df760193f4b57837f293054fa4a3189", + "lib/setuptools/_vendor/zipp/compat/py310.pyc": "f84854b11da759d1b6128087df9417781bcc581d879f8c79bb1db2cb85184f80", + "lib/setuptools/_vendor/zipp/glob.pyc": "ca52a43179a3b3ba7efea98011087c2849700f5aa98ab30015a137bf7910043e", + "lib/setuptools/_vendor/zipp-3.19.2.dist-info/INSTALLER": "ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508", + "lib/setuptools/_vendor/zipp-3.19.2.dist-info/LICENSE": "86da0f01aeae46348a3c3d465195dc1ceccde79f79e87769a64b8da04b2a4741", + "lib/setuptools/_vendor/zipp-3.19.2.dist-info/METADATA": "508ae4fe43081c64b0b0a2828588b3a8cc3430c6693d1676662569400b0dfdb1", + "lib/setuptools/_vendor/zipp-3.19.2.dist-info/RECORD": "f316f2e03fd9ade7ebbc0b154706848e2bb8fd568b90935109f0d8e3ce2b9bfe", + "lib/setuptools/_vendor/zipp-3.19.2.dist-info/REQUESTED": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "lib/setuptools/_vendor/zipp-3.19.2.dist-info/WHEEL": "189eedfe4581172c1b6a02b97a8f48a14c0b5baa3239e4ca990fbd8871553714", + "lib/setuptools/_vendor/zipp-3.19.2.dist-info/top_level.txt": "8806dda121df686a817d56f65ee47d26a4901c2a0eb0eb46eb2f42fcb4a9a85c", + "lib/setuptools/archive_util.pyc": "3884531da5beee64eb72632d05737bbb78680c148bd3513b6862c0a816621490", + "lib/setuptools/cli-32.exe": "32acc1bc543116cbe2cff10cb867772df2f254ff2634c870aef0b46c4b696fdb", + "lib/setuptools/cli-64.exe": "bbb3de5707629e6a60a0c238cd477b28f07f0066982fda953fa6fcec39073a4a", + "lib/setuptools/cli-arm64.exe": "b9a7d08da880dfac8bcf548eba4b06fb59b6f09b17d33148a0f6618328926c61", + "lib/setuptools/cli.exe": "32acc1bc543116cbe2cff10cb867772df2f254ff2634c870aef0b46c4b696fdb", + "lib/setuptools/command/__init__.pyc": "8004debd579263a4d9ed19e351867aacd73ec03fbc336c5f87fa49d731a2c037", + "lib/setuptools/command/_requirestxt.pyc": "95cf95b617bf2e8bc1257c463df997699f8131d160eccd6cf1c5ab0a8d175e7e", + "lib/setuptools/command/bdist_egg.pyc": "9b412b38b91d96a42aef4844c32f34c05eb0aa37faebb88978887c610d09c6d2", + "lib/setuptools/command/bdist_wheel.pyc": "e0efb42143a20402c36a6a0aa012a6baf6d0baca49220d74b2ad9123125615a0", + "lib/setuptools/command/build.pyc": "0decf0237ce7c72ba2ed381558618d570bf077f6a328dbe20507d5e000eb8f51", + "lib/setuptools/command/build_ext.pyc": "25f7eb15e30a6c5e433a9cae02cbb650fd6b7b9937f0ddb3e517d47198d57668", + "lib/setuptools/command/build_py.pyc": "348c1c115d2a10e09a4bae6f63509f3c50f25e73460fce990e77efb4363d518a", + "lib/setuptools/command/egg_info.pyc": "500a79aa9d052721d70a65a32eda302c9529be18864fe18898e545a81e53ecde", + "lib/setuptools/command/launcher manifest.xml": "c652db8d6ac1d35b4a0b4fa195590e2a48923dbccc9a5d9e38fb49fee7029db1", + "lib/setuptools/command/sdist.pyc": "6303574a2a2e88c34c016080f09987bb7e49ad0c6dc2fbf0d32e58a6874c5e1a", + "lib/setuptools/command/setopt.pyc": "4d9ab6415e04c54dc7ecb13b991c3c961b1752dd7a107ab7c2c197f6be309008", + "lib/setuptools/compat/__init__.pyc": "4292941766ca7b70f78e6de1375dcb2de283cf9c9ed7e404837bb47fa24dc25d", + "lib/setuptools/compat/py310.pyc": "d7130aa8543ca4a97b21eff099be4b6e36c164a15ed49f6d9464e4e6e23c6d80", + "lib/setuptools/compat/py39.pyc": "1c38205936205c1b5ebdbff1c8a7be68d82f278bf24bf28d331cc0f31f5d4422", + "lib/setuptools/config/NOTICE": "2dddf08818297a3b89d43d95ff659d8da85741108c9136dfa3a4d856c0623bd8", + "lib/setuptools/config/__init__.pyc": "b5c0e56b296db3c9a198efaf4196e3e03e54d039044c4efb4f71797619c75d5b", + "lib/setuptools/config/_apply_pyprojecttoml.pyc": "08d0056fbe7ad65d6d9de889e7be3032d0e167f5acfaad10532199f3099b8ec2", + "lib/setuptools/config/_validate_pyproject/NOTICE": "5d300dbfa643138b013b75ac9caeee591f951b8b0ee24288c34ccd926c4780c8", + "lib/setuptools/config/_validate_pyproject/__init__.pyc": "7216c3eaa8af39dc71419356f72b14e8f619b23ab04c86e8cf562a572716bd68", + "lib/setuptools/config/_validate_pyproject/error_reporting.pyc": "1425d2264afbe3c1c3e7421488e55b58521de020ce3d7ff00bc265ae501369ff", + "lib/setuptools/config/_validate_pyproject/extra_validations.pyc": "2d087895475c1b3e449eebf9280e3e4781a36aab3ceef3b31a3938da19ea8b2d", + "lib/setuptools/config/_validate_pyproject/fastjsonschema_exceptions.pyc": "c0514fae9f5c646ec9b693c6005d81f338f1c7a47e31a5250d831fad570d7c99", + "lib/setuptools/config/_validate_pyproject/fastjsonschema_validations.pyc": "12c96fce25621ace335b926aba212650167ea551336fc28e383966f00bc8c75e", + "lib/setuptools/config/_validate_pyproject/formats.pyc": "5e59e4b83f508d9bbd5ab9cf0b88a6fb0e1aa11f71b530c0f01b13861a677ef9", + "lib/setuptools/config/distutils.schema.json": "4dca77da44678703911b0ffda7a1848b4f258f6875e6d411cce6016f31a67015", + "lib/setuptools/config/expand.pyc": "ab441c29804cdc62e9433ac288b120a9f4f2c841e5716bd9dc54623306e7ea1f", + "lib/setuptools/config/pyprojecttoml.pyc": "9a3276df118813b3499988812ac71aba564307c775096bfeb5437ab84cbff0bb", + "lib/setuptools/config/setupcfg.pyc": "e3e7c72f6ff987ec35c0b2bf23aa6d111f07a9787a4440d04013c2a252fabc7e", + "lib/setuptools/config/setuptools.schema.json": "759051b921276646ada1596dd645701bca1c4de45d3bb043d31bce58a1f9e0f6", + "lib/setuptools/depends.pyc": "3a9952102810d92e94b4611238d5268c7c67557ef763c0b7c9acce3e3f453139", + "lib/setuptools/discovery.pyc": "031772304fbef6a65e614e5690e62c0dbc5a970b3c8e7e34897a52b3a30942a8", + "lib/setuptools/dist.pyc": "4e0e8da183db87b5ec35c4c78aa4b33a34304b78d37d59567f0294008e350574", + "lib/setuptools/errors.pyc": "3253aab85a484c7142514824688a907f9495be7ebafc233eaed59e59f46f5fd9", + "lib/setuptools/extension.pyc": "273b064991397a306b950edc7beadb49a5c4b2daa9418d1823849a700743d44f", + "lib/setuptools/glob.pyc": "7ed6ceafee2ad85c12a5c2f3f28c58ffbea00a8c80f29d5f1326785462fc46cd", + "lib/setuptools/gui-32.exe": "85dae1e95d77845f2cb59bcac3d4afe74bbe4c91a9bcc5bf4a71cd43104dbe7c", + "lib/setuptools/gui-64.exe": "3471b6140eadc6412277dbbefe3fef8c345a0f1a59776086b80a3618c3a83e3b", + "lib/setuptools/gui-arm64.exe": "e694f4743405c8b5926ff457db6fe7f1a12dec7c16a9c3864784d3f4e07ae097", + "lib/setuptools/gui.exe": "85dae1e95d77845f2cb59bcac3d4afe74bbe4c91a9bcc5bf4a71cd43104dbe7c", + "lib/setuptools/installer.pyc": "63736d66e0521626cd00b028a101c0f1008a50a750fba0a50de0d7f676665e91", + "lib/setuptools/logging.pyc": "2c9d4c28ca72ff7d4a7483243dff2652731402a34aa5a39f9c2e712734578c1c", + "lib/setuptools/monkey.pyc": "3f44e68e4a95d6177e5036f88ca4f3711e5a86c05f4c33ba830348753df98ef2", + "lib/setuptools/msvc.pyc": "6628eedf88b2ebd1d4508f8c1a075b2622876b8548ed7268db428dae8d9ea221", + "lib/setuptools/script (dev).tmpl": "454cd0cc2414697b7074bb581d661b21098e6844b906baaad45bd403fb6efb92", + "lib/setuptools/script.tmpl": "5864ede6989eccedbb73e0dbc7a9794384f715fdb4039cfbf3bda1bf76808586", + "lib/setuptools/unicode_utils.pyc": "90c131fccd873b24541132dc81dd94b76a86fe99ea2b47ca2d716c69e329a571", + "lib/setuptools/version.pyc": "63b4c6c0fd755f0a0c86483330d8f9dce9219855f9c62fd841bcee3e2e7ae448", + "lib/setuptools/warnings.pyc": "9f7a398ceb94e0e72f0738a4aaac55132117fed3088dfb49cab2e499e82104fc", + "lib/setuptools/wheel.pyc": "20214525c717523f33486a0fdcce9ec2aa68d11283a83c87d560b3f359aee300", + "lib/sqlite3/__init__.pyc": "bf01278746800699f96c9defc07f07df31e16f69c6bd176ffe87a38f4a249402", + "lib/sqlite3/dbapi2.pyc": "f2066c047a2e8826d5a70e060863b3a3b929c778dbf32a28aaaefa0ca54bbba4", + "lib/sqlite3/dump.pyc": "0f61344d515e091c2dffea07795d922b5d80639211746c86b885a21f6600218c", + "lib/sysconfig/__init__.pyc": "00c689875539112686f1685a9ecb915d5d1ab56a799ceade3ecb5d0fbc5dbc0c", + "lib/termios.cpython-313-x86_64-linux-gnu.so": "36806c3058952d7be5eedf3aa9d98ca36085a796eebf95465e7cf9353d25b45c", + "lib/tomli/__init__.pyc": "f43362530b3298bdec5fe517d664ce3525ce68c42c393809884b9ffc3dbd706c", + "lib/tomli/_parser.pyc": "bbefe87b746da008fa74347f1b4a6daabbc4328aeff390becde07e15cb1b971c", + "lib/tomli/_re.pyc": "4d61a6fa3ecd4615b4877b6352f51d1e378de7eb82b85705af9c644ee50aafd2", + "lib/tomli/_types.pyc": "b8b7c9f155a21203e1fba76c8e3e12f0c98cfeed8077d6d094189ca55c7637d5", + "lib/tomllib/__init__.pyc": "78a8934f811263c52117a773841d24a78bdcdfb2bf7817895381815fe87f3041", + "lib/tomllib/_parser.pyc": "fb095353e540498bc24ad45ed8abc441554190012ea371d8c875f42ef224f624", + "lib/tomllib/_re.pyc": "504db2bbb78bfcce6ddaa1b7d82b085dde9824c11d04a56d9dbb625e71ca44b4", + "lib/tomllib/_types.pyc": "467f79f09bded6d0c1cbf3a429b25c00ff5172a30041a1581c1674aa513b79c9", + "lib/tomllib/mypy.ini": "01d8afe88929a47bb6425f11573cccddc244af126057165722cd40f0eca3f35c", + "lib/typeguard/__init__.pyc": "004d515f6f1b8727c06c8ad6e1141d3003288674bfe60db1e3c84b7cb0ed5018", + "lib/typeguard/_checkers.pyc": "b56f54dafddb882eab55991c728dff813668728541b5411c461e8a7af9b7d451", + "lib/typeguard/_config.pyc": "9fd684d2bd3ad1c8afe32a2ade6c7a84144e9c7a668b42596faeb0b5c4198a07", + "lib/typeguard/_decorators.pyc": "f8346f854c460dcb58b843dd150e0e23c452eb110a77e340c35fd1289868edf1", + "lib/typeguard/_exceptions.pyc": "81b1024423c798de465cd8d72cef23d7be0009eb3aaef076e6b5819d2080ecf7", + "lib/typeguard/_functions.pyc": "2129b02f09cd2712b49e2c3fac9ba165d4f53fd309adabe4866ad17927ae79ba", + "lib/typeguard/_importhook.pyc": "f8063aac9853d29d2ad980d45ae61d24891c7f81dc374db51f9ffbde2b3bf0de", + "lib/typeguard/_memo.pyc": "8df2193c1c34c3d0103e23e4720506f6f2514ed424bdbdebaa6b29398da3df20", + "lib/typeguard/_suppression.pyc": "5a477628118b4008e0891f13858cbbb6692d3f42432fbb91efb5363371e7ec42", + "lib/typeguard/_transformer.pyc": "87bba79f76826ff010800afac4626869712a0f9a67037acb586c5339240b4535", + "lib/typeguard/_union_transformer.pyc": "ef384bd6995ac2c5683fa331d40cb4aad4decea868e096d26d835e2d990eb26f", + "lib/typeguard/_utils.pyc": "a223bcafb003a24053efc06abb371392e1b8d67065b9ac21976ffcfe50c3070f", + "lib/unicodedata.cpython-313-x86_64-linux-gnu.so": "1e6b4b7684ff58c4aa1b57fe09392cd1dd32292c5a213d9d7aedaf62d9ef186c", + "lib/unittest/__init__.pyc": "dd847182f924066fdd3e7dfb0a8a86d6e0f4d267cc68cfeafc99a1bbc1147f22", + "lib/unittest/_log.pyc": "2460b141248f2d601f5e74f115dd76bb2de606184d290736727f2baefe7f347e", + "lib/unittest/async_case.pyc": "1fcece8cba7287383cb2cac4cd90228702d63004dfbbaeaafe9bfbf2fbf02d32", + "lib/unittest/case.pyc": "641267e3a90b31654675691acdf3df24ae63740ac6d1ffbf996b16b06e85083b", + "lib/unittest/loader.pyc": "36340f5767b3ff59193d934e702e9dc2cee75fff68aff0c8286a11763efd1857", + "lib/unittest/main.pyc": "aa08860e452432ddaccbf8fd9b4a1dc0ad51b8be9312737a122110965f912c0c", + "lib/unittest/mock.pyc": "d4ca9946a23608950a1bf7a0b511d7b227468cebf532f710c7d1394e64353a9d", + "lib/unittest/result.pyc": "866a91396a45a93235d305a388c5345567d38fffaba394e40f1c5d849071dfad", + "lib/unittest/runner.pyc": "ebf543eb0246371879ef57421eef36043ed75da25567685ff53c065aa6293995", + "lib/unittest/signals.pyc": "71224dbaafcc4434429fc87b0be31b1e8aa108cec91ada2ed0d59ee8e66e71c0", + "lib/unittest/suite.pyc": "99285ed731c428be6e7fd83198623627441976fa9af5c819daf06ba85f09ed08", + "lib/unittest/util.pyc": "e0af8ee24640a521d1260dba0ce71daf1d7ee6ff978d074cd41453fac7b519e5", + "lib/urllib/__init__.pyc": "03b5141742e7f6a1994e9c7ababb1d4e6fd2cdb4c4b9fa64efe64b76d202d35c", + "lib/urllib/error.pyc": "c3cf49fd807844d61d28598b14d02af35cee60dc07ea5a588e99ce3b821da928", + "lib/urllib/parse.pyc": "4804d946338f096f789734c78e19b7235a4fc5649e5e1147988c3878a569c9b2", + "lib/urllib/request.pyc": "a084100b492561f64d9a9ba734e2b5938b470912c2504974ff3e772d07c7365b", + "lib/urllib/response.pyc": "6135f1906a1c507c1870deadfe248119a0aa4fd0805926f18542cd4357ea89ce", + "lib/urllib3/__init__.pyc": "572cfaa7ab9e9c70c666aef00687e49d4117a49d268de27e10604f076858ba71", + "lib/urllib3/_base_connection.pyc": "df3bf33a9a39bc608923a520691d9056770793813d5855bc5c461fd5a49ab26b", + "lib/urllib3/_collections.pyc": "f4933654c86016223e6e4b4fba1c5b728faabfa592264fe5b20eb5ce17bab235", + "lib/urllib3/_request_methods.pyc": "bb4f9b47f9244890e13e30a808e60fc2e976408ff505dcaa7c1c341902120a99", + "lib/urllib3/_version.pyc": "28080e33c5ac87e62382120de3604ea1bb0b4c8ed5d02d5824e31029f279cac6", + "lib/urllib3/connection.pyc": "f2338ecb66b213ebd81d6ab8b43b404cb4f02e905d593bb1edf3d5f7e732cb81", + "lib/urllib3/connectionpool.pyc": "735443369c6546d517a781d718622dc8d5274d031340e0648c4d0c60654e6357", + "lib/urllib3/contrib/__init__.pyc": "6e76bf3e0dac01f2f1c61876369341661fc1f73f1b0d6a1c3c0411f9b4a0561f", + "lib/urllib3/contrib/emscripten/__init__.pyc": "b95ef2446e0fd0ffd5fb2b760714a521bdb7e563ffe50345c8c60a07f29866a9", + "lib/urllib3/contrib/emscripten/connection.pyc": "2a42625d2b9d0fc0c617e93d0080389ab4cb83c4c675301392182c62fc4343e2", + "lib/urllib3/contrib/emscripten/emscripten_fetch_worker.js": "cf5937cd9e3f84329ddfeb4def0cf3f0b1e31c2da9c4dfeebbc07793d0fd0377", + "lib/urllib3/contrib/emscripten/fetch.pyc": "6b337a35544753a0c59743f52ab48faed5616df8200abf227cae74c1f8ddef9f", + "lib/urllib3/contrib/emscripten/request.pyc": "66468e885cf2ff1f0af759d94dc40cef08d97eb738d8b3ca14711328ffc30c4e", + "lib/urllib3/contrib/emscripten/response.pyc": "8b18bbe59b9b02a0faa6689d71615fd5bccfca956ac15cbee0bf5acffa971204", + "lib/urllib3/contrib/pyopenssl.pyc": "d262e3e11de44a5f811e8b1e8db3a70668fb4d62403484d0f24a8cd0f54ed6ce", + "lib/urllib3/contrib/socks.pyc": "0ab327753e193c58da3f643bbdd3df1f9e25011a1ce826c41aa04cd17aead3fc", + "lib/urllib3/exceptions.pyc": "05a8b440a0cbe2cb0c423af2c70aef8c48c2bccac18e31c236e9df5276733472", + "lib/urllib3/fields.pyc": "4408cac1cde9bcacd308f4a7808108b81403f6188707b4922ef2878353c74bad", + "lib/urllib3/filepost.pyc": "ac2cb9b4b32871ffcc690d71dbaf8fa96f6e2979240fd8ed251e49bd7845d7a7", + "lib/urllib3/http2/__init__.pyc": "c90c1fa6976c8b989135641cb1c634e44bc455ccc4ec860d10433f1be9282eab", + "lib/urllib3/http2/connection.pyc": "fec9318866c981bfca4668b9192bdb1b0cbd9d1baa56a653a0c84338a53eeac3", + "lib/urllib3/http2/probe.pyc": "392329d5f26e8b3f01173df90c04a9f8a511c10a2b96c9c6727c433112d1011a", + "lib/urllib3/poolmanager.pyc": "6b037794dda4df033ccf430c094add63fb32a67393b5b103a2809976c49ee549", + "lib/urllib3/response.pyc": "3e5d1f7918651fd722525f67db3cd306d6dd356564efa146e6501aa8a8fa47aa", + "lib/urllib3/util/__init__.pyc": "c221c200d2ef4ca8b2c10ae75f92f348f42863b3b2ed1ae718308d8468cf16f8", + "lib/urllib3/util/connection.pyc": "2c36bd4f71ff5a521b926e9294b709ec7e3df9f10af0e935fcc723c619a26f20", + "lib/urllib3/util/proxy.pyc": "2c0eb62eb67aa6109616245b0872fe90c7b473ef9f7f6e4006b74e422eb2b003", + "lib/urllib3/util/request.pyc": "64e851ff9ff0cf9119ca7e680f9c7d5cdaf3a956aa30b88d157f8b8b613694df", + "lib/urllib3/util/response.pyc": "8d3160a8e4a42688921111f35dc2724bb6fb2748c78424d02a56fa3505c91bb7", + "lib/urllib3/util/retry.pyc": "a6c977415c0bc2b9710e79fa77cd4048b4d52260bcfd33a8ad32e8a627d59ce3", + "lib/urllib3/util/ssl_.pyc": "ae5b282899cefe820242258a43955a5d22ca23b913f4c6e2e52ad92f5a53e9ee", + "lib/urllib3/util/ssl_match_hostname.pyc": "280508a085e1c9af633681a310e18b97e0fe9024303da6fb164091ec798712be", + "lib/urllib3/util/ssltransport.pyc": "5756423bb66738b15f2ebf01087a6b785e69b47568f8f8470675132c69c0743d", + "lib/urllib3/util/timeout.pyc": "6e50fef3a6d9ed4437de696ee4e2b79fa6e6117bef84479109ba633ee0050ea0", + "lib/urllib3/util/url.pyc": "65f5b00108d7a1f42ca7adcd39ff4eed6d4d1174598693065ffed3c345d3b1ea", + "lib/urllib3/util/util.pyc": "63d2f6954eb5a7bf7afcae03ade56a208dd733167f3d47b3b6b603ffa8a6a8d1", + "lib/urllib3/util/wait.pyc": "d2fe69cef2e8b19a8588a7dd43b771077633c408b036bda4a546c96bd8c9f26c", + "lib/wheel/__init__.pyc": "4d7d889b754f597e72889fc8be8162346a1f4a93d939dbc71a9951387c8b6b56", + "lib/wheel/cli/__init__.pyc": "7089b6b3f120d255ad195ff5fa8d06adec0637785c43f29b000e0c5b369d0a6d", + "lib/wheel/cli/convert.pyc": "0a7bd716d80dcd594752122886e51ec3db7ac9801ea95b237af7272aa268b1bd", + "lib/wheel/cli/pack.pyc": "fc70c490560c234b7f726d38e154e83abcb40ca7c2d092c69b529281c392ba7a", + "lib/wheel/cli/tags.pyc": "e08d420547dc7dd514c1fb817406bff8f63c05f6f829f70851afed1ef5a0f329", + "lib/wheel/cli/unpack.pyc": "8b0fff83c499d16e9f8205afa3ffd85542625873d2264df861ebb6733459647f", + "lib/wheel/macosx_libfile.pyc": "c7cf190dcb32dc8c41169e1cb2a582587329757f717e9d528fa33e5617bc9b31", + "lib/wheel/metadata.pyc": "49d1a41f3c733c950ba5b5498f055cfd8e571625e890e67eba557d268c6a655c", + "lib/wheel/util.pyc": "60ce6eb949706012e6ce1cecfa03844681a9e96051f1fdb88a43a25f6f7e19f7", + "lib/wheel/vendored/__init__.pyc": "e3da39e89340ad85a7ec4fbad9fc3e09e2cb31a7420eb3e871922272c4eee4c0", + "lib/wheel/vendored/packaging/LICENSE": "cad1ef5bd340d73e074ba614d26f7deaca5c7940c3d8c34852e65c4909686c48", + "lib/wheel/vendored/packaging/LICENSE.APACHE": "0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594", + "lib/wheel/vendored/packaging/LICENSE.BSD": "b70e7e9b742f1cc6f948b34c16aa39ffece94196364bc88ff0d2180f0028fac5", + "lib/wheel/vendored/packaging/__init__.pyc": "80479669a68e5256c1a4ddaeaf8f2203eb7e11cc3c4684fead625d7db51b7e7c", + "lib/wheel/vendored/packaging/_elffile.pyc": "e88c8b109ff2efad53652a941d02fe505be9c74a4decec213f38d66ff9b7abb3", + "lib/wheel/vendored/packaging/_manylinux.pyc": "180e52a68ce98f4b3f50c9ccedb33b0b4525a9e4c41f309555ba400102eec8a5", + "lib/wheel/vendored/packaging/_musllinux.pyc": "798de16920a5546bf2707e89410b8d0bfb4f6c612e43dcf2485669b43951bf38", + "lib/wheel/vendored/packaging/_parser.pyc": "f03bbeb5623efb9086fda423c952da099fb158474fc05e96b003718ae3a497b5", + "lib/wheel/vendored/packaging/_structures.pyc": "22b0a6aabba1058c02c78b05f7a84c32aa24994686eaf7d3994d5a7edb48525a", + "lib/wheel/vendored/packaging/_tokenizer.pyc": "bd8f1bd7528e191628eee4a60af880a6627e25082b90baa061064179f6744923", + "lib/wheel/vendored/packaging/markers.pyc": "228055651374e0fce2d1028c2ee2329d036477f8612e7f7c8461df245888d810", + "lib/wheel/vendored/packaging/requirements.pyc": "5832f8be94a3e36637d178361fdb6238cc6615a3dac85b87ba5122125b586723", + "lib/wheel/vendored/packaging/specifiers.pyc": "fb5885876cfe96e7f919214cfccf5b34f8db6f24396eceba9c954b0e860aa68b", + "lib/wheel/vendored/packaging/tags.pyc": "f980aa6a07ad0a705042bf45e8388c31ae42dad89d57dff698749ce4a03c32ab", + "lib/wheel/vendored/packaging/utils.pyc": "e24bb430b6dd9f2173963a48adb186a943bfe0880c80a075c0a68bc878ac92cd", + "lib/wheel/vendored/packaging/version.pyc": "297e14163314827e72eb966b89e9138fb70460d8ba42f01840fa442e333c72f5", + "lib/wheel/vendored/vendor.txt": "67610d8c1d62e69adf7b3f0274cd5276bddce99c6fdab451a253292e60677001", + "lib/wheel/wheelfile.pyc": "a0dbf12baafef3be74187e019dee395ca9824ef3d0968f7b6a9a840f1817973a", + "lib/xml/__init__.pyc": "9177d3232309c928dd96c85a62352d67c2f4c37ad3d07d0050f11f3033580c55", + "lib/xml/etree/ElementPath.pyc": "29ed4c81e659358d70c7f4bff6ca1245e9910335af6d3251256f07fe557fa354", + "lib/xml/etree/ElementTree.pyc": "0a27d4f191994bb3e513de25cf76999d8222b92995d3cf13049ee254d8180322", + "lib/xml/etree/__init__.pyc": "c328156773b33cc48527e36cb3a51bfe7e3ee245211d44bb83453319edc63a5e", + "lib/xml/parsers/__init__.pyc": "84386dcb76c6944289daa220e64121cfeaa583b437de812288c777003a94af91", + "lib/xml/parsers/expat.pyc": "f754e4e631df65258b21f58ba7c92d7a3c37a09762fe890cada7a77ff6860679", + "lib/xmlrpc/__init__.pyc": "b0744b1586f91f2175fb7cd0fff4f3c5d9f8c9750ccf11cc0f413ac72fdb17c3", + "lib/xmlrpc/client.pyc": "77eb247db9027e6ffdedd21bb3ec70af9f7d1d0c38691bbab1477bdc7bcb00e1", + "lib/yarl/__init__.pyc": "c69c8827c6f5f612e2af39d5a208c9fac4149d1bee8684e08de18f619c002c7d", + "lib/yarl/_parse.pyc": "c0431f57225363867c19d0a649525e728bfc21e1f688d89d16ef3e9fd38ab13d", + "lib/yarl/_path.pyc": "d8ab4a3ea6cd1ffaee11d977f2a38b762aa070ef447dab7179d224171b88850b", + "lib/yarl/_query.pyc": "452f0a4fe4258573359a1097550b41176f65a2810bf3eddfb028783b367ca04f", + "lib/yarl/_quoters.pyc": "2e8ec8ebc027dd2df89bf30f594d99ef813878761631a32b052746bf9a693108", + "lib/yarl/_quoting.pyc": "c9f5c3beb96cfce5af777258641a951794c7bebb92ac739b166fb3965b73ca7b", + "lib/yarl/_quoting_c.cpython-313-x86_64-linux-gnu.so": "3233ed1a24637c44884ef552f4b6f2760c3bbb2ce20163fccb51e4bd7f96470f", + "lib/yarl/_quoting_py.pyc": "f4571d0a4124be753ae1f6cc4913d1b391d6838ea7af18885a652d33a909d2db", + "lib/yarl/_url.pyc": "e6d30e37f69216da3c91016e2345d1863e51c6f2891997558d079a4a86405808", + "lib/zipfile/__init__.pyc": "746f936e06288779289b3b6c83035b2fa2eeb3b4f49893e03ff20da8b71a6e17", + "lib/zipfile/_path/__init__.pyc": "fbb6ba0c090a3c38f741e35e9d97b1fcf5b9f8f504c63e0963388ac2a46c958d", + "lib/zipfile/_path/glob.pyc": "6c0b0262f579d54a0789bf9902deec5ccc7146f6519bc92dd3138082414154e4", + "lib/zipp/__init__.pyc": "335ea547ffef6fb62b340f3f4ffd3fda13eefec54ffbd9b826db799f4a6d848a", + "lib/zipp/compat/__init__.pyc": "c9eb73e989db393939b9d9e1a6a320bbf3c7ae02afc38edfb0d496633ce17973", + "lib/zipp/compat/py310.pyc": "aa6211d9a469de134e78bad832b45f46d1e1c69156c133d2fef15e4f7d06feb5", + "lib/zipp/glob.pyc": "ca3801700493820e71ddc5f5526b83fabfb964212cfef5b46c2894a9f2c7ece6", + "lib/zlib.cpython-313-x86_64-linux-gnu.so": "b6da4d4090c31432d18dafd573115ff4fb83c07855e3e0652bba639f0cc4116b", + "logo/icon.ico": "f0ca1240f4bc0bc6dfdedb7bdd03b4e39a1b25840ad5166bb4dc67864fe5f247", + "logo/logo.png": "2d73e0e18141cbcebf0a38c31c2f5152370291f6eb8eeb65a7fd02a29d9b82da", + "public/assets/AboutPage-0IhYgVnf.js": "be97f886fd21bb730da22f3d86dd395c7bba9ee607b59320a399dbb82a089d81", + "public/assets/AboutPage-8fEiI5uK.js": "ea611e6c05060ab6113a5257fe1567289edcac8fcf7b8296f31b43a62deb4a39", + "public/assets/AboutPage-BKLttI6i.js": "b875d7ee84f7f21916109e655ecdbc9a2aea276e9dcdd293ea4df5ac984f6a98", + "public/assets/AboutPage-BMjlT6TK.js": "a819b1bd3cd16a9e724526f1b70e1e3b9122dd9e06593907d0205a4efe117cdd", + "public/assets/AboutPage-Baol2fuy.js": "68e8abd9d0a1f76f8ddd0b33f2cbb4ff3b9ab7091ef561565c5d73967a50db00", + "public/assets/AboutPage-BcCaFooV.js": "d963caa627219ce5688dc4d713711033e2660e5aaa48540295db17d24a5984c7", + "public/assets/AboutPage-Bn9rvwVK.js": "a6b193ef20eac72b320ceca8ebcd4bef596dddb493e96be21763f1d58bcbebbe", + "public/assets/AboutPage-BzBwKHSG.js": "f87555d7df8436a3ceb96229c75a9e577854c7ae83370d9e0b6b492d76831285", + "public/assets/AboutPage-C9JNCYeR.js": "e89333d84a9e990e25c89dcd4cb14604087d6c3f06b162e79a69a1658d7a31d2", + "public/assets/AboutPage-CHatkEki.js": "b790af35e013a477024c26cbcd8579ebcb319aefce9a1ec7fa695edeafe9e897", + "public/assets/AboutPage-D4r8SBwq.js": "38fd9844b860a9f32e72e89027313cc136e139d451bdee39fd971efaf77adef9", + "public/assets/AboutPage-D8YSes0g.js": "a705ef6cb7bbadcdcca2bc95fc41eb131448d1f639ef1ada24ccf4ab4a876784", + "public/assets/AboutPage-DAC1QiAp.js": "20cd57b43a7b3f84ff35e3c3b050d52eb5cbe17f222622176e8458c8c6aeb96a", + "public/assets/AboutPage-DCeZPdz1.js": "d488356ed2d2c4cf6bad1dc1a76fac40ddd5cf8ae9f15c700a2d86266be2990c", + "public/assets/AboutPage-DDJYGtfQ.js": "6824866eb30a454bf1ae261e399af0794334749f3fe9a4b57a4aba202d27764c", + "public/assets/AboutPage-DrUL2TvN.js": "a085bdafd2fcc7f374a8a44df7210b485fd887e373f77f7c992c6b32ffd980c1", + "public/assets/AboutPage-N2UDxc2H.js": "7d112575b42b15e099768502474e9351dc6c6187c7746c93baa407941eb16ab6", + "public/assets/AboutPage-cO7wDO0p.js": "52a488610c8761150402c5fc97a3fae6fe8ae0226a9e3fdeea48349948e1902e", + "public/assets/AboutPage-jCiPes_8.js": "290f1087991d8b33569e8bf9b3e94646c0c3ed0925186086dc19b5b00b1be40c", + "public/assets/AboutPage-mT6yCyKK.js": "560e6a3f5ac5837a50005ee2bf022bfbe081bea4edf5a2bbdb858cdc4c2913a1", + "public/assets/AddInterfacePage-8U5lyEuC.js": "a54d4e83b86185c420ff1ce8318ad3d5d1e0e7f770ea76a1136e4ccf63440690", + "public/assets/AddInterfacePage-BCtbSofF.js": "58f202f4dc213f5fa1e24d04c3a43896ffac4a6a4ba84252a1ce3678a7c23e03", + "public/assets/AddInterfacePage-BMaqdHgt.js": "405f581dddb488a46a1a38edfac866ad4fe74341d7a257176c65c2fd380cf0c6", + "public/assets/AddInterfacePage-BTcYysxX.css": "61dc0b5468c223aaff8acc47626e4284e72e07262b5a0a19d36707888f7208eb", + "public/assets/AddInterfacePage-BUgU4mHN.js": "0e93cbfc04d75845850fe092ad62a3728070dc94f41239d8031a357dfeab23f6", + "public/assets/AddInterfacePage-BZsc0GRV.js": "719d721bb9d8ede61d49eb952ba97921924a64c5f78cf287b8b6bf6cdb72387c", + "public/assets/AddInterfacePage-BdMCP1YI.js": "204a083e1dc0cc14eb6c6a4576c623d64c79b0a873a0fffecddb5eeb794118e4", + "public/assets/AddInterfacePage-Be5myeHR.js": "4d018cd57da9cec137655ca974763ecb13e3291ab4c58b8abc68663f09a0aadf", + "public/assets/AddInterfacePage-BmsAxVL1.js": "7fe441daea357e273d99cf203bb3a04639765e94905d78346f3a74784873c3fb", + "public/assets/AddInterfacePage-BqSlOb8S.js": "ff15f4d2720903de44609e10ee2161b315d2285d1b4420f02318620f2a3ca248", + "public/assets/AddInterfacePage-BzRcwDV6.js": "c8b85385f076fd7137a02c0104059492de64500281e54c809af820dc4c24de04", + "public/assets/AddInterfacePage-CHsX34aM.js": "c0c86def1cf79086fcf251f5bd56ec72e8a3943cd96fc94f1417bcf67a1ba6bc", + "public/assets/AddInterfacePage-CK7nWyjv.js": "42f25fcc18cb40dd0546b65c5f167aacbf40348b9511a43ca98bac1d6e307ff6", + "public/assets/AddInterfacePage-CYk70Bnr.js": "6e71d5bbd13d27dd77b08ecebef797d946d5b5336923acca7f62e6d050eddffa", + "public/assets/AddInterfacePage-Cp0aXqUn.js": "ded3735137237672936d6726ae6d75a091ad2a96e625192db1129ee657a1d9c8", + "public/assets/AddInterfacePage-Crr-YNaw.js": "2cd4c836089ea6aae5eed770e32616cf953a38ea6385e817cde4796d81aba9b7", + "public/assets/AddInterfacePage-DVuvwyDC.js": "4037e6751c12ff9db02915ad9f782fdb7729efec3a16a3fad6e313dd578e8145", + "public/assets/AddInterfacePage-DiEX5AfZ.css": "03ec87be159836fd2f2bc256a1cf6c19a206e6f0b6b17e3ae4f7ec6891687a08", + "public/assets/AddInterfacePage-Dk6b4P9D.js": "6940d4c0d65b20b9b4d5c937fdddee735c5c4c3df657a45f6ef62517c65309b0", + "public/assets/AddInterfacePage-Y5-VKBIk.js": "bf511802432a98c3bb2408bf9edfb6d75c1532a6ee26a7e6f38fb04ab02beaa1", + "public/assets/AddInterfacePage-udEolizH.js": "ce6eb44eea6d61b67562e9d69092634d7383dea1c4bef0a211f7dad7ae223462", + "public/assets/AddInterfacePage-zIW8kofQ.js": "a97fa4b221e628d246be8420d0c2508690fdc1c80d9140949c1b17a72a603f06", + "public/assets/ArchivesPage-3ZoRbsmi.js": "fde1c3442c645107042a8689e613225a9432926ccdbe03bdb75450fd50e6efed", + "public/assets/ArchivesPage-7LB1KeTH.js": "a22c8b1aa71747240dae715b155f4a1b47fe6c303fa57b9d57b5b4359c4f6532", + "public/assets/ArchivesPage-AaES3-lS.js": "f8bf7a93042bdf6b6532106886afd1455ed14fe0246589441e2b22af89f4b13b", + "public/assets/ArchivesPage-B15552h0.js": "443edf93cd2f63ea6c3223ac2ba6379321a06b32b9a25a2966523df5fd85c8ec", + "public/assets/ArchivesPage-B8bIEMTn.js": "2c4f39ff0cdebfd0f306aa40bd660be0f2a401137cac8d9188d462974b047edd", + "public/assets/ArchivesPage-BLofx5Zi.js": "e9eea40e43079084781a8df397c652b52b7049252b282e779cfb629b34abdae1", + "public/assets/ArchivesPage-BeHVXSmu.js": "7fdbccaa7c8d9cd2ba710824d278978268a0fd5d31ad43bd84f27a0ad8b9e725", + "public/assets/ArchivesPage-BoD5FNM0.js": "74ffd82412d7f1411283ce2a328d69f3afa1de6cf8327ccfbfbdb7d248c4b328", + "public/assets/ArchivesPage-C1yHbXva.js": "485a6363fd0229c6778b45a96121145006eadc3a4c1f531ce1264406a8161759", + "public/assets/ArchivesPage-CJFohVhF.js": "d6bf0fda552c71fdd9912ac5394401301ce71900bfacce94df8bbf2df3b0efb6", + "public/assets/ArchivesPage-CPxaPYQo.css": "f8cf0bf5a3d3c7c61b339e4246174b90e8edd0f01fdc87f5fd76e99c32b1bd5b", + "public/assets/ArchivesPage-CjWmGi3s.js": "9f9f6c9f1476e44525aabdc1cf6d2e1c6b2ee841fb85cd5a55e767abcc0930b0", + "public/assets/ArchivesPage-CreAUQ-V.js": "cd57436865376503b20a3263b1b014fc39ae59102910aca718f1979f57a5067f", + "public/assets/ArchivesPage-DCznv-zV.js": "d1a2a730f22790ef535db226771f70735cdcf14ca21104ed762e98153eb01641", + "public/assets/ArchivesPage-DQNKVWWo.js": "8be434387e152fb31cbbb5b32c0cc4b7ccb8c63784f80cc7163a11e45c8240fb", + "public/assets/ArchivesPage-DfAEykmy.js": "df01fe9cc5b6013e2a84907fb923edb87e2a22bd821b65638d1527ccc84bfc30", + "public/assets/ArchivesPage-Di-dIsoJ.js": "bdc86a5ca40adfcf7fd09da7f88450c0c77e65209b9ee0b9133511149af5cfb7", + "public/assets/ArchivesPage-Doi98rCD.js": "f91519241562cd872d3784d793a283864a131b8f85a3c598e58750abab64d400", + "public/assets/ArchivesPage-DqLN89ND.js": "70217190b4b707c524563a537bb08ee6a5976e80296f59185639fea3a55a05c5", + "public/assets/ArchivesPage-MQE8c1mh.js": "14d23fadb15611de351a698a2ba4629aae6db1f254398a351812b07dc2b1218c", + "public/assets/ArchivesPage-SegXm3vv.js": "aac23f598e672781342506f453e9d573f7924162b8f9f219f3664aae564279c0", + "public/assets/AuthPage-B8fvh-c3.js": "ef3b4603f62ae490b274b10b69784d2cb305cabaeb25494d5832e5801b45295f", + "public/assets/AuthPage-BQii6kbQ.js": "5e46fe0dd5d098071ed41146c0ccc60a209a62039fd481ee1915c5395e1c53ef", + "public/assets/AuthPage-BScK_nq2.js": "a227df74dd7e182188fd8d5b0a66b6e915695ae7dae21726a87e6fd3d7e3a563", + "public/assets/AuthPage-BWX5PNrJ.js": "f5e9e870e3c059a7203def71892fcd4603d3236e2945e3d4fb75bcc8a2be585e", + "public/assets/AuthPage-BagJfDyo.js": "bfb4fbd35bbe9dc6b50d9b8f1ba93109df451750ca3f662618580a3516ab4528", + "public/assets/AuthPage-Bfh9quB9.js": "da133fbe8bb18280d2c53d14853d6bae92786b91237297967ec2fd4507c46845", + "public/assets/AuthPage-BytNkU35.js": "1c1c7fb89f0ef26f26bfab5e20275e838d3e16bfdf6394840785d94ddbbff160", + "public/assets/AuthPage-CFC1s3eA.js": "a2c0f1f63836817e708a94b54ed4c66620a46684cc53e0c7b69d8de5856642bb", + "public/assets/AuthPage-CIDofeln.js": "c6087eb9c56f4350fa098ad1e1d978045244c08382f3483b12880c03768bc36c", + "public/assets/AuthPage-CbO-FPqt.js": "40b5a6050fde24bae4afd6597e33ec1d01a46577613956e3798cc2ba9b969177", + "public/assets/AuthPage-Cl_ZNA9t.js": "de9b317c4abb001603c5434af2f19b7167c2feacc826cf828a0c1bb5f3833929", + "public/assets/AuthPage-CnLp5Bef.js": "ab3beb2fbe4a68f9a8e790655cd3a164f25c814f4146632e7a47ec90ee933f0e", + "public/assets/AuthPage-CsBUr8cw.js": "70f63f63b6ec11c27baae6b832f371e85ca2ce6394b29271eab9d717f6da4ac6", + "public/assets/AuthPage-Cuw13OWi.js": "c9ff77da541874cb4700f1723136ee746f49506162671cbc2cee4b9f97fc9c5c", + "public/assets/AuthPage-DE_R8ybi.js": "65b917ee43a2b8e24d78266a688fa6bb7e9709997f7dc1a5a351ad18f6981c95", + "public/assets/AuthPage-DPOdVS_2.js": "313265c078c81380fd4f5c59611c8afac6aab58e86c95016a55fdee8533d42f5", + "public/assets/AuthPage-G6XYwO3I.js": "e690d7c33cac1460e97230c971009cc32082e5be7929c992a271d8b87af4c641", + "public/assets/AuthPage-XSiZwR92.js": "a3641bde2eaa53c066c108c4f5a186497631edbd4b75b32b8449e46ee718573d", + "public/assets/AuthPage-d0SgjC6f.js": "913b4001bcff6aa1a0c09493294be92101d1a2fa43b3aa55fe2fb13da87c4d4d", + "public/assets/AuthPage-mqiDR_K5.js": "516d1705303c381461be758da87a3e9ef065809bed5d2588d4841d8df8a88f68", + "public/assets/BlockedPage--w5BAQVc.js": "afe83111a422725f289dfc6e2ceb04e37e6e30ca2cb5bfd94a062b5ab7a1725b", + "public/assets/BlockedPage-BKlUYsLN.js": "9acc91d041d1592316cf7620ae9fbeab79cc5e16970cb162c9345a1052570118", + "public/assets/BlockedPage-BOvzaN_C.js": "7d6b544b81c5113c166616d4fb3dea5f02036b3443989d947553fd03af44f4fc", + "public/assets/BlockedPage-BQwf8_om.js": "b2c148b9f9142f82d56033258fcac4af4fb761d3cc61587016c37d3b4480678c", + "public/assets/BlockedPage-BSMLtAQF.js": "8cde5e3b110c9b2d5123d7939fb7ba9b8bf1679e853ed27ec8aad4ab0e5e1089", + "public/assets/BlockedPage-Bb8MI4BS.js": "bd992e2c9e7a5346b00bca857800a023b8f2c9d159f3aac8e8d22bf108d93b63", + "public/assets/BlockedPage-BbR4aTPm.js": "3cfa7a06970b0f7a143436239720cb04bea09e16393a453cd59019d7c845f2fd", + "public/assets/BlockedPage-BcyInvbm.js": "6dfe1f392487ded7f2455dc75497b5e588c1e8867b667990c2cc038a4a3a5b21", + "public/assets/BlockedPage-Bl6NIBrb.js": "b8b36625b41a0156a4819c9abf392734d4030768dd3c7c89b7f72c93421db8c0", + "public/assets/BlockedPage-Bogen_i_.js": "9d7ebb2b710eaf14e769b444433748692759c8662d22aecb498e8fa5289d28ed", + "public/assets/BlockedPage-Bve9i13H.js": "4ae68ec7f8f4b7c2a17a086c4d68ea247cc9fa55b5fc12a07660162b4c0b388b", + "public/assets/BlockedPage-C70Xjfnm.js": "d12008d486e83ea90dd21583c3b9af0f323af2faa04831838ec4403925786c91", + "public/assets/BlockedPage-CPTT-CSB.js": "cad34fe06f109b33e4ae7b1cc796fbd7a2411d93f689f5521945e4bf70d99546", + "public/assets/BlockedPage-CUTBR0Kx.js": "39cf9f0af4bc86db7fa3d5bbe3d2c97d901b3e034031278d4f0bb48d18d6c024", + "public/assets/BlockedPage-CUv4mTjv.js": "551d31be0d5b5306335be88df76ed1dd8d013ed980b48fd4dd07702cc8903346", + "public/assets/BlockedPage-ChJxX-YD.js": "fbf75b23bf09b612f8f9bd0a80d03e7ae1ed88095963635d6d24bcdfe94c8859", + "public/assets/BlockedPage-Cj5wW2JY.js": "aa8223bf9f1909465b89b22f76749a991c39bb783ec27b423bef12b0a6b2cf64", + "public/assets/BlockedPage-UO9kbItm.js": "51cd72d47cf9782036188b0ca22ea85fbdb63759a0adbc3a7f46bbb881a35270", + "public/assets/BlockedPage-fglMXFtz.js": "edfbefbc2caa6fde26004a5eda5cc41ad27ac1e3b63e9d52bd365301934601b3", + "public/assets/BlockedPage-nnfC_qop.js": "0afd8a8d1ac138accc46df7e0e3cf480fbc4f0b84cdf712aa14d3bedc9f17fbe", + "public/assets/CallPage-B9A5VbTO.js": "d4a90455473540966994d4404557eeecd37318ebefc4787b31f12e244fca3cf8", + "public/assets/CallPage-BRIKPbmi.js": "fe836a0cce17b7370e7deb03cb8bcaa4272bb81251981eb4047263951b0c8388", + "public/assets/CallPage-BqqYln35.js": "b9b149e7a963374a939b2b6e5e66c75eca77906eba091441599e7be0e573de61", + "public/assets/CallPage-BwAxhKKp.js": "756ebc63cb1e87d716d8d46d47380bbc1e1f10de8a6a8c469190b91af4ad11f8", + "public/assets/CallPage-Bwf3B1oK.js": "930180e1a993f6252e56a9d74ffe99553fc652341944ef2e549638a987f5beed", + "public/assets/CallPage-ByNY39ve.js": "5f4f0fb49fe376afcfd491661f7d9959c382a3e9c453901ebd2797f1804ed740", + "public/assets/CallPage-C5kSsHhI.js": "73c6790c08a44d3cb9131b4990420483fcacafad90d1c58c04e92837d7ab046f", + "public/assets/CallPage-CkKTpT7n.js": "bead262cc1028fac6fc7660d854a3db3f383cabe202e9667c94580e71ba53ff7", + "public/assets/CallPage-D4jb_f8Y.js": "2ff9e913d7e05765eed2db1beba525cc17f17eb6cba0ec4bd92bd3e167b76e55", + "public/assets/CallPage-DAGAK42u.js": "4e0045609ef9b149388d2987d51fc58b22ed12a3382cbb228abeb0d532680862", + "public/assets/CallPage-DD0NVwu4.js": "750449435b386e063260c66e8f601de78270cb333d0f5c476c077117da21e02a", + "public/assets/CallPage-Da055DPT.js": "a4c3f0c7185ecd3a88cb40f41ed9bd46c1fce904d920a252e7e8046827f32f75", + "public/assets/CallPage-DcfOes9s.js": "b45be33fea18b0ccef9003690e1411896ec9a9e9913d92d2ad2be17d777bbd33", + "public/assets/CallPage-De8paHKH.css": "8f3c50ad7162d9ca7f0738bf4714eaca03b36f1f609ba158b7d8d7344e6f7ad5", + "public/assets/CallPage-DfOmVy8A.js": "7eff0286f3df1c2d74284ba9241bb5919d69947a7775cd717725fde5804cbefc", + "public/assets/CallPage-K4yaGC9s.js": "c996db74e2c08d8f08beffd464565eff597d96d1ae75a74250a5bc28bd08984d", + "public/assets/CallPage-dxJwwjb1.js": "02c8551f07a3c93cfbf5f7af1d682dbff5247876bf8ea1b322a8560c89947b10", + "public/assets/CallPage-iNLpjZ37.js": "2ecdf1321a3382783e66df5dd61e4fffb210c7a2c9d8c34be236f279d53a2f32", + "public/assets/CallPage-k4WQa0my.js": "453bb574d9473f8238a5dd0b8505dc98843cc24f0ab6aafa09b6ee7521938acd", + "public/assets/CallPage-pUEXQpMp.js": "8de02a002921ae84bbd595b4ecab0df71649b5fe21bf359f71348921b263026d", + "public/assets/CallPage-yAxsVFe7.js": "83cf69b23964fa3dbf4a0cffb0caf7af66e4a289d2d586763f3ec296082c45e1", + "public/assets/DebugLogsPage-4zJ9O4eQ.js": "9d4653a52e93befc50cc6edcb19c08920411e4f8364a3854cd697be6bccdc063", + "public/assets/DebugLogsPage-5UW3nsMS.js": "a6e0960ee21d89409dbbf0e9b990d1984269bb9fb9468873645d3e1391b2bd49", + "public/assets/DebugLogsPage-B3SOBo9X.js": "a3d20f64b34b7a217a1cfc0f525547d31e5c78072233fb782d44bc1590e1f60f", + "public/assets/DebugLogsPage-BNl6PdKw.js": "095ded4961531b67392ef7127f5cfa91459a5221464f2fe2e8c80eea5f9e6795", + "public/assets/DebugLogsPage-Bn8RD8Zg.js": "5a3e958cfcffd6ded7a45c719827cc400fa9a018d666ef96fc9fe4ceffc57265", + "public/assets/DebugLogsPage-BxPvNzLG.js": "16d67d2d2a4d825360c077d7529565958506923b539436bc756398304bba8bd8", + "public/assets/DebugLogsPage-C0L8VN9V.css": "7e293009b33eae8b7b2ebdbc0b37b7a6c7e10d980f9399145ddbbc171bdbe6f5", + "public/assets/DebugLogsPage-C6xFRLE0.js": "e9d2213c42749b082dc182c1e190314f5ba52f6bd88ee051f9bae285ffcedd95", + "public/assets/DebugLogsPage-CDvs1-mH.css": "c974af1f0bccc095e14ee2d34861daf60fc8b5af95acf50c18687c48ad132a23", + "public/assets/DebugLogsPage-CP3MkkCv.js": "c762f17081abf972b557e111546f666033d304cf0e67374d95e08e0e05d17206", + "public/assets/DebugLogsPage-CZJEcwRM.js": "1aa967b389ad8efe5d529ad13a2b4613526f185c358a43412070e7a1349f91c4", + "public/assets/DebugLogsPage-CcJfflzG.js": "3f650e18c92aff0ad7ec979d4b4d2f2ab335944176b00eedaf22c74af1b27264", + "public/assets/DebugLogsPage-Ce4ZfS-b.js": "019f27cd38c96ca22f4a4c2b8831cf6d6b5fe4d66caefd00f11e60cd22400068", + "public/assets/DebugLogsPage-CevruSTZ.js": "3bd5f85166055f20c93cc52ff2127701309f4c6339f22fe2b9e62449fa25af1b", + "public/assets/DebugLogsPage-Cs9qaJhW.js": "d246ade48fce67dfcd40621f4fe907415486d801480a0c4e52f4e74a5a96397e", + "public/assets/DebugLogsPage-Cy8As8Ax.js": "998ae00f250b91067b7060bdfc380580e4799114b53ac391aabdd60a4ea91143", + "public/assets/DebugLogsPage-D3P9cvkP.js": "1a0c5af94a21032a9d48865ab471131b32fbdc3a66a316e85e6dbaa730792141", + "public/assets/DebugLogsPage-D74Sftux.js": "97ecc1b085a5284fa375a039457c3b4c0e5c55aa0c425b2aab06156d280b5df6", + "public/assets/DebugLogsPage-DehBhZqo.js": "80e0cadc8d7d66a1a896cc9fe1b69b1b0627be083393b2d32c4678645f61eb42", + "public/assets/DebugLogsPage-Dn0-LMnJ.js": "b68d5ea0b6fd21006400f3850137bd8de9f740faa39407b64d837029cc9ce86a", + "public/assets/DebugLogsPage-Dzy3VE6l.js": "3a8dfc210519a32fc18817a28a03bc765429a063a2ca689b8ac9273d4c7b5265", + "public/assets/DebugLogsPage-gQY3fUF0.js": "147125c86aa4fcdbe729a86f66787099c5f0c5ec9b6ff407f280f1f841efd1f7", + "public/assets/DocsPage-2_adKWz5.js": "e5b89209f8d2a62c89e263469111f0a2d0d196b6879d96d4d6ace990d1a08e07", + "public/assets/DocsPage-B-m7mgh5.js": "f8b24884d2240fea52c8c8213195745aeb25b2ca8b77a773de4e47532f567dd3", + "public/assets/DocsPage-BEg7eanQ.js": "36ff4f8aaa910e62c8b5e0c1369952cc4376eb8dfee455eab2fb2da90ad34803", + "public/assets/DocsPage-BKOCiRrr.js": "f2f93c9dcb1d75d91d9bbc6c91f50f44a8daf0407b4a449fc1d7a9f54c4beeff", + "public/assets/DocsPage-BS52EMoo.js": "49d15c52092ee5bb639e04ea3a043955a5ae65fa51abe02e1f26fa8e05958ce6", + "public/assets/DocsPage-BTY2zrzo.js": "efac452791ae3f908f1a01ae071bd47380038b86f63ce67b2ded287ae5c81f10", + "public/assets/DocsPage-BXX9iq1d.js": "9a6a297a95504b6b32fe96b6f09ff3b756ff4ae3e5f73a8a393f96caa270a515", + "public/assets/DocsPage-BstDjHTu.js": "389e9c0144ddcf099fead7044caf9d75a178b6eb7058701f3d7e61ac59460101", + "public/assets/DocsPage-CNRrTRn2.js": "bd18fab4cd464a806c56dce2e1bfd4d42892a5f6e89d4cef9bf09bbec9f5b570", + "public/assets/DocsPage-COB1YgpN.js": "d3efa697d7e41103982dfdf907bbe71185f5d3737a51c3deedb227e34f34393e", + "public/assets/DocsPage-CYi8pzEM.js": "907e925475080cf1e4d92740d00281c3581d5afb149822c17dddc00950b37e79", + "public/assets/DocsPage-C_rhvfLw.css": "8fbae748c54f0d0898d860634da36f5b8556351db68d72cc1a6824b2b5fa8d87", + "public/assets/DocsPage-D4LG5S_A.js": "88874fe49a120f0fe8a302268f22871a7d13ae3d4af568d05d59c3c6bbd962df", + "public/assets/DocsPage-D9i9itaR.js": "8696f8038aa7e16f50ea7260e5954c47af7b8b204dbebb821e4487608d3753bd", + "public/assets/DocsPage-DKNLCnf3.js": "a144235811aee1e8e77c7b6edff3660233f96308edc87b4be8bc68e39c5a2266", + "public/assets/DocsPage-DZnaYyVW.js": "63daacfe84767a03c02ae3b21955b0ea0c5b2b4df39017f532f07bc23aede3e0", + "public/assets/DocsPage-DcP31Aw9.js": "9a37b54e11a8fcb5562133a3e4dee291cea99e846e45ae7c93dcf5d7e428129f", + "public/assets/DocsPage-DfBdX1MN.js": "6d8816b65a3ea61eed13a19f4ae976fe59355b5b79db89d499385fc03c3c1847", + "public/assets/DocsPage-Dq-wqU-E.js": "1262db491a0ddd6a242267d58856707d1de4c475b1353b9371b17aa32685b562", + "public/assets/DocsPage-DrRohStP.js": "2312be0223d4949903f600dd264928c304896bb141d93e6592070b9153be7f87", + "public/assets/DocsPage-DxRL1MsW.css": "2727fa188637b6cb7e9a5f854bb64f00052ed63731865bf349b323048e20d948", + "public/assets/DocsPage-ddW0eLHn.js": "7d0a9a47baf19596d8fe6d0b7212afb76cff464031a63cba6f9ee209b40d2e49", + "public/assets/DocsPage-hDlg1Y9s.css": "49d69be6aa44d8d062396fad2278d54c9d1da81d18d5a5b9d5c64d8329a3f04b", + "public/assets/DocsPage-yrWtkKMx.css": "a0c64c62a6e8cf347bf8720ef650cec044115cc70782a64c4e0755409c48e050", + "public/assets/DropDownMenu-BRb-5XM2.js": "0fdb2c12b97d1405c07be38da940815b2302f951418c1cd501a86a69f36e79e1", + "public/assets/DropDownMenu-BSIRDIhA.js": "280ab9ee2aa11071e4835ce1b7064c3dd25649aef321b11f25cdcb42f8835a32", + "public/assets/DropDownMenu-BTUTU14_.js": "dab91982ba3e31220cf86dba63202015c4fa6c91cafd28cd3764f1a2130d0374", + "public/assets/DropDownMenu-BV2CC1ni.js": "00dd4f073a965582f227b43cd04c836791323d1e958922457d32698e5a711b73", + "public/assets/DropDownMenu-BXmJSeiu.js": "9e22d613436eedb7c468b6386597c162928fb1cb3a0fcb04d6fd0fdac3a47377", + "public/assets/DropDownMenu-BwNpCqI2.js": "3b4a947ba178592addd831612cf2566c4f8fb270ea7f23970ecf49050c2639b8", + "public/assets/DropDownMenu-C3oTXFDX.js": "45bfdae74e0a7208bdfc1cbb8a0ef5b476fd38fa87c26034e8ce3f7425bc269c", + "public/assets/DropDownMenu-C4IqVjVV.js": "5825129c0341007a531725f77f8d9c9f9ee0adc2e1be1dd817fafe6e03961c33", + "public/assets/DropDownMenu-C9ic1-Kp.js": "c9e1b41300d8bd68e2362331821ca1681203f30a098faf76b16ec9b78eeaf332", + "public/assets/DropDownMenu-CCJZnVsh.js": "e5f950f69e9153793b9aaaac57ff0c37ea2f3b4ca29754237e4d7030059325bc", + "public/assets/DropDownMenu-COST-XEn.js": "474565edab04754aeaf1f2af6cd5d4e4aa8aba47f5aa624209d76b42b00f2081", + "public/assets/DropDownMenu-Czu8e35G.js": "d458923a01f011a92bd04b5b7d8e3a6711b23821fb0ff30491d80a9497d2a466", + "public/assets/DropDownMenu-DE52OS4K.js": "2d777670085486fa390e57c19ef9f818f8cc4f68766d95992201972142484fd0", + "public/assets/DropDownMenu-DTkGrpcz.js": "c902ba83ac75299c8fae12753b8cafd1ab08943d3d51238db7beebe7463a26c0", + "public/assets/DropDownMenu-DiaJpxda.js": "013d798b58e1ba50da4355ef1a70799005cd72e75a3a3b42440ff9fb59fc9e90", + "public/assets/DropDownMenu-Dt4WcFld.js": "c84fb19e2f12e38aba20d8dff358cc5bf0f4b962dd0e25e3ffeff9fd31329b66", + "public/assets/DropDownMenu-Dtgo4qDk.js": "77e94d3864978537c1dae82c8f92cd11f778bdda1f0ba9c0f7d45fb4c0ea53d7", + "public/assets/DropDownMenu-Muyb_dgX.js": "a24c874efd47d0e5d6aa87ee98f0249f7b1bcc1ef714c3af8410062c4bde056f", + "public/assets/DropDownMenu-OitbrUhj.js": "0aee8c48585c6e8a63cf1c74b6f938288e0bf103c0bee051d2f710d66ea9f261", + "public/assets/DropDownMenu-ePZ8FLXc.js": "87cf5654c0d3a008b929a51b78fbe17c1870c3dac140b0ed753080ba8dfd7642", + "public/assets/ForwarderPage-ASnZ1fk9.js": "7f236bfc466b3f1d7c7c708a71bb9e63a9f4df478f6c8f3ba8a4a5fb7b0978bb", + "public/assets/ForwarderPage-B8iqJoSA.js": "ff127d7a026595be6f57034f2326749430eecf56a27b9c314b7f55a652742430", + "public/assets/ForwarderPage-BMLJ8L8K.js": "74c1ee101d3458860179c6bea6764d658c6b865e99c8c3f980444fe507e95768", + "public/assets/ForwarderPage-BRot3TI7.js": "9544d8f26f4479e386f429680d953494cc754cf13f3b71dc797f42cb8082aaf4", + "public/assets/ForwarderPage-BYX9iOuW.js": "53f8838207db7e588cc6b8e8fbdd2acdf9474d8ea89af9703d78c0474b22351c", + "public/assets/ForwarderPage-Bh0rnH3g.js": "76f3f0accff62acdbb77e4c8c5a1d26746d0b3e5efb8568a4a79868d1ee5e0e6", + "public/assets/ForwarderPage-BsOm3cTt.js": "330665ee3b4e3c2fd5a52e55fb66ff655faaf94ac462638d877e834e9005c429", + "public/assets/ForwarderPage-Bt0FsK9I.js": "a1c0e218aef1f0cf3743aeaf70c78d46e9ad0061d3947d62c2b1800842bc5922", + "public/assets/ForwarderPage-CBP8CERR.js": "7ae9ec04800f07619bb1e929f09bc2e46d80bd4274073380213077a7055fcd2f", + "public/assets/ForwarderPage-CHhMqC1Z.js": "ed8ce04c20195e56b4250e31fac01bd42190bc6262701f2700dbcc0b8b1afe1b", + "public/assets/ForwarderPage-CQq9bhew.js": "b6bb0a2be97e33b41823464e42086dd33337a9b5a85b57d234e6d9f667f11170", + "public/assets/ForwarderPage-CbhYpLxX.js": "adc51db70a275fe19deaee1aabc4bac2df85d5677915cec0d554bea5fc8cd759", + "public/assets/ForwarderPage-CguUvBJJ.js": "a3aa0d7f2995ebfb0ee52537cff5b782ca032b8c9eb396327ecfb68ee111dd0c", + "public/assets/ForwarderPage-CnvdX6oJ.js": "b96d61b7742e46407d42a2ba9e5f26442855bdc76f2b72414dc98c5d33d8adcf", + "public/assets/ForwarderPage-CozsIxph.js": "1059df94b80eaee93b4b6da6ac381864feda3ebc4df685b08c2f1b7f1bd8f8a1", + "public/assets/ForwarderPage-CvBwYLAT.js": "72180d2d5dcd43842eda609a9a10f476fbf3590e338f354a224324cfecd0a42c", + "public/assets/ForwarderPage-D143y7qD.css": "c58183223cd2e32a62ab89be2dae42b891a01fc94832abcf87df2dbff8374b5a", + "public/assets/ForwarderPage-DF74u1Mk.js": "7ef45302504af0d69e4606e8deeb76f17c4fcbc22234511102e2c5f9c46ef0c5", + "public/assets/ForwarderPage-DShkAayA.js": "75753c0e310f07963b34d2dba65c80f44327e87dbbe880dd4ad58d9604bca561", + "public/assets/ForwarderPage-Y7chGBck.js": "0c5efa10fc520c03ec748f80e59a10f8c8a6c8542f9032e8d495e1f3d627dab1", + "public/assets/ForwarderPage-Z0455sJm.js": "abcd71db6571b1eb9b33c8d3c0795a562f0a960c5e1a4a9ed92f3d151706cf83", + "public/assets/IdentitiesPage-2u5Olo1e.js": "dc8bb5d634d244eb401170bbcf5ca96d9aca886d542998fa0f7c6949a73a8b49", + "public/assets/IdentitiesPage-3202l5tg.js": "6fd6e09cbae3288e2d421deaf960fb6bfa807685612297b5e49a886df85d5d04", + "public/assets/IdentitiesPage-6a2u0dbv.css": "955a6ccae0fbefc482b24ada826c8a3f3005980a358ac9ecfaa461d078d50da5", + "public/assets/IdentitiesPage-B6Ryy6cT.js": "eb46b7f3b6519dc9f6d47dfd5caf2c0432d3f71c1f204b02efe3f099160decd4", + "public/assets/IdentitiesPage-B7rMKJwT.js": "a3321e4ada43934ea9c0a49e1f5769e34f88459debc782bc3cd51d7593beb114", + "public/assets/IdentitiesPage-BBn2a3pF.js": "9869c8c075800e1a49f7a23b5c25d6cd5f89d3fa9892dbb3480db355b857dd45", + "public/assets/IdentitiesPage-BD4TvGn4.js": "6b35f365d95b39e27cc7656dc7a073a9ce190d5a6e4cee843dee745a2845a860", + "public/assets/IdentitiesPage-BT8t-ScD.js": "538e27d9b02a2bad13b56f926bb72c6500e8c6f56f6778948c70cc872049905a", + "public/assets/IdentitiesPage-BYvn1GRy.js": "5d7cfbf16828a8be6509135f0261e719e43f09f366c6dd2877d37dcc149d6a4f", + "public/assets/IdentitiesPage-BmUB8ygV.js": "f7198ab68c28ff6e7761632a2b0e547b919eba4790973aeceb78c46ab142140d", + "public/assets/IdentitiesPage-ByIi0vE0.js": "8a12361618c8a15ed6647ff1bf92f5d9c8ca535fdf0bd47b22386e41eb6d4c61", + "public/assets/IdentitiesPage-C1Sqy8sn.js": "1c98bd91885c79c991a68aa49700659c2c5083d2687b2795abd52fa7ea825b94", + "public/assets/IdentitiesPage-CFFXsLLv.js": "7c53af04f56e8422e9c169f05602ff43ad8565da025a7be41c1684470883fc0c", + "public/assets/IdentitiesPage-CGgBXv9v.js": "6dcbf64447789963e7e83e880162d52f417a2b3afd0a35efcb84c0e76037b85f", + "public/assets/IdentitiesPage-CqU8xv8N.js": "13bdf898258cadf1b237dcaeef4b342ccb8b32d4d5ff6f655d3e0e3c8624029c", + "public/assets/IdentitiesPage-CsDlV8Ey.js": "9ce634bdb2108792f1c2f1adeb06ecf80fb52f9c3c023d2bb83435abd75b871b", + "public/assets/IdentitiesPage-Cz-Lldsg.js": "20b1e9061348169b31dcc7a2dda28495946b57c291f9af1ae8c171a433a4d0e7", + "public/assets/IdentitiesPage-D2x-Np_g.js": "000fd4d14140f5e939a971eb85b2adc3cb33747fa85fa27490c002cb6cf3b75f", + "public/assets/IdentitiesPage-Da7yzPOK.js": "77c314f43a647fdc64ebc84bc0572832023d3ead55c26135d8e73967cc1cec14", + "public/assets/IdentitiesPage-DcQ25KvW.js": "9c73fb8c7906e36ce19da94be0658dfc4b6205d90e358ed1f85bde3c957ef8d6", + "public/assets/IdentitiesPage-DgA739OZ.css": "64ff5fa2623696104b41f9d70010c4700307fc77d8851f0fd6a38e13df926f22", + "public/assets/IdentitiesPage-atAVP6Od.js": "242bf7c16efb2d6e38c4ef24791a7de2ce1e362bf51129503fb843747508e264", + "public/assets/InterfacesPage-4MWHd8dj.js": "14b9ad609180af4211beecc2dd6bdc03aa769c30ae0a8777481918fc02b4d100", + "public/assets/InterfacesPage-B300_rSy.js": "0e6f6c305d1f3643361307304701a4a3162af9af3f8d9971e3321d6c54a3cf75", + "public/assets/InterfacesPage-BAUi3br-.js": "ab9d664fdd1c9c0671074d8db6c3efd68e8fccf7885e84d75cf76df33a2655d2", + "public/assets/InterfacesPage-BE69gBFL.js": "f54210b1b611f17cdcf1ad3530b6bfa05df9751518755b32e7cc0a8b86c02f48", + "public/assets/InterfacesPage-BGTCDXHz.js": "0a2330c449c6abacdb5292d0b60d1248b020b81945d67178754b545d396e6ff3", + "public/assets/InterfacesPage-BPjlbmnf.js": "11a0f91d1a7bf462cabf22ebed6201f908d00e95f03db799f4aa4b969a558f04", + "public/assets/InterfacesPage-BW-HN4Ty.css": "c1bb16c277c10876ee2e1b3c170aee4129d69078ef64fa8a1cdc256213f79eb5", + "public/assets/InterfacesPage-BYPjrZcT.js": "e3080bd373af904971e3f00c7d7263c186a0a57516cbb8f0a222d4213e378a35", + "public/assets/InterfacesPage-BjDKDL9X.js": "1b3eae8280e260cdcfc9fc5b3fe9da188f9094efecb0bcc958d772174d497afa", + "public/assets/InterfacesPage-CA8G16Gi.js": "c6af69449342a56592151ec3e768c829763989f2753dc5a3fabf3c5ba3f70862", + "public/assets/InterfacesPage-CDwvRlY5.js": "0ad1d3f4550df6c0e8476e78f9461102b11d7d3f33069a2bcc13e48438cf02bc", + "public/assets/InterfacesPage-CJb8W80l.js": "48c9ca5acba4399b805a3d9ce94d8c8f9b3b18b45e87b850a0ccd7a7d79ba0bf", + "public/assets/InterfacesPage-CKI4gY94.js": "e8ee4a65e71c7607b5dff78f3220253ec83697519ed1b1147fcadf88573a0566", + "public/assets/InterfacesPage-CYmlWTfK.js": "c22b12853a76517e5b1c5ae4eb45115283ad4b1d7373a1b28ec166a5d1a46db3", + "public/assets/InterfacesPage-DdK02uqg.js": "b3435163b32495ce97529aa8551137f478c4b026bd40069c127d9c0ea6b8bbdc", + "public/assets/InterfacesPage-DjKGl6a9.js": "bc94f216c405ddcc0b15cc9d76068d4e8f9224ddfc42bec581ac747c77e6ca22", + "public/assets/InterfacesPage-DlDyC-7K.js": "06ba8d692481ebd666841757d09817434f732aa85c6177924be0d523b8961cec", + "public/assets/InterfacesPage-DylPN8vf.js": "d65ea3603bc16a3a52ab34225f80d4610b22f9a27e2c6be0bd8ad6b7155361dc", + "public/assets/InterfacesPage-cVtkeZQp.js": "7043132cde70233b1e79845396fbb00d7307f8d293ee095131b4be7c920fc487", + "public/assets/InterfacesPage-fQMOZ4y9.js": "15368c12a9801a265237d3f3bf8b82033833c215b486b7ba45f566caeb9eaf9e", + "public/assets/InterfacesPage-s-bbz0cT.js": "4d0d337c473046a6427528cb1c942d3f405e5d3f1a4be56260e7fdae4318a18d", + "public/assets/MapPage-B0XYXEb_.js": "0b2865d8cb6abf6141b728d858e310c572c75972ae534b84c82cbd6964b1855b", + "public/assets/MapPage-B6E4IMGb.js": "2ea7e8547d4bdd512fdf213c3e4e262e9fefe4268ac0830f4ae8e6e70059c23f", + "public/assets/MapPage-BH_84XDd.js": "227048268485cc3e2539dfee1bd2034751da3b95bcbaf734068c0f0e324ca949", + "public/assets/MapPage-BJq0AFv1.js": "1d379b48d6f5502f3ba4af4a56d29adb387171aa546008cd5b22c157fdfce088", + "public/assets/MapPage-BLd4rfbi.css": "ba3e4e77c15d60098baf9097fa691e517a06d6caddf69ed1a03a5d8617a58c8d", + "public/assets/MapPage-BPQ-qtZn.js": "f735ca520d41e7839dd398fd1e1e58e4ff3ce629f85e3ecfeb37ffa604cd7957", + "public/assets/MapPage-BXb3DCaj.js": "4bdeb6c11209f0851ffa56320016c969909825a0fd928310702809c6c2ce53ec", + "public/assets/MapPage-BZ5D-xHr.js": "8ddee5ebafcee1cc7e62cff2507951a69100d0116a6b0fbe5cd05e6be50a41d7", + "public/assets/MapPage-BsSuGB7U.css": "363b6a79d3006ec1f9d7408f68d1e74a4913f7d4c2fba8b5f9365ae22ad63732", + "public/assets/MapPage-BscXmA_E.js": "f92d188c4afc28dbd0a36a1fd0b9070bc64d90707fa0d2eefe0cc6f869428a7e", + "public/assets/MapPage-BtS0PlIc.js": "420ce457cfbfe878bc492f55e23958d94213251e7930a21f549b48fc91f83c1e", + "public/assets/MapPage-Bw5IYwuF.js": "02ed3ef11aac8d4166699a2892b8000d1dcaac7718052628607b3173c6046f16", + "public/assets/MapPage-CMFf7rDs.css": "6ac1628fd5ddfdecaed27cde430856a39876ceff82b7ffe81e2e71c275d174c9", + "public/assets/MapPage-CT51EQsq.js": "8a15a6349c46440ab2b0ef88827de3b87d187798e5b95322a5543293be1fea2d", + "public/assets/MapPage-CXzhmmQE.js": "b9e431d440b3a93fc4f29404ee301c306a07fbe9883e430040ec0d4a94d1a565", + "public/assets/MapPage-Coz2HXkW.js": "94722dd14c824edec7f4ad474afe4bf6a97e8716529feaa6efff071301f46f69", + "public/assets/MapPage-CvnvsezB.js": "4cffa5d8b88e29a32e1282154bb99b5ee927430e7f703571a15a5ab6ec57f65e", + "public/assets/MapPage-DNKwPg3D.js": "c7ae2ebbbaf1c63e4434aa1e038e7c8863177b067259ef2ee2c855c0e699a45b", + "public/assets/MapPage-DrAjZhQB.js": "4fd9573942b463b55a0fe2b71d53e537714699d759a385418bfa6ee14b60f7e5", + "public/assets/MapPage-Eo71eMvW.js": "ee05b8df42b77309edd1dc7b2e03dc0091d5cb62b7466d252c5c0e4a39e1b266", + "public/assets/MapPage-MEfcwtYj.js": "bcceda5970102ee5e1402fef2fa4e4c7b95b7e9e713cdab1be1169d1c778cbc4", + "public/assets/MapPage-V-HR1n5s.js": "2f1495c1b9965707392aa18b5f29d8e8e31679c1a5ea44acc711812ee2edb689", + "public/assets/MapPage-bENFa5lt.js": "feb4e79151ae8f33ce45a587ec27f4b378faf84475bcaa0a1921859def670cbd", + "public/assets/MessagesPage--b4Wkkmz.css": "f7570ba32576861d4451c7258b68b2b3a6c61f3d0d20b3f2d31e608e11700337", + "public/assets/MessagesPage-B61ii4Fu.js": "496cd8b3c5d389764a3e7190adeb3535ab10406a6eae0614b4950d1c9c95a65b", + "public/assets/MessagesPage-BF2U2VwR.css": "cf00bca52630bbfc7778444cc22718191f4e88716db7d88f0b93bb543ee2ca1f", + "public/assets/MessagesPage-BVpsGmWC.js": "4095c4084da602868c0940bd85327d92178d6cfdfaa8e5bd4aaf3439782be3f1", + "public/assets/MessagesPage-C88C1Xta.css": "148fd8eec5e7599cc138f4351df7a92046ce0d6798f725d5258869683d63dc5e", + "public/assets/MessagesPage-CAEN_2MV.js": "1f59035de93b2f8655a58196fcc4f98477ea20b443d83dc2f099890c1580c7f2", + "public/assets/MessagesPage-CNFsm2Fh.js": "2e24f98ef452bb49c086431a6fdda90691ef76fe4ad69bb7b1c1a1dd6f0bf7d4", + "public/assets/MessagesPage-CQNx2QWQ.js": "6ed122ce71e914b539bb3dad4834ced5163e5b9711db6c7be9eb859bf9c09dc0", + "public/assets/MessagesPage-CRDsD-DT.js": "bf646c9a91a7a1a832fd31ebc1c33ad38bd28c761489b3f14f9215cc343cb447", + "public/assets/MessagesPage-CUmqFQTq.js": "a769783cea4371cc89dd49243dfd4bd9cc460f10c36f7366c93d82fd22f88843", + "public/assets/MessagesPage-CxK5eF6i.js": "a9564996fefcbe6cfd7141f561e19bb6a92c47b29a3dd34ed9d61cae478f98b5", + "public/assets/MessagesPage-D7cLbQ9T.js": "b5ccdb25280135468a730292797fe4ddd7f6e28d22dfc2997c9ec38d974832d8", + "public/assets/MessagesPage-DL8Ws2UA.js": "7c0e33cfb316078145a42028ce94922d2626cc800484e5817a2c0d3f236524a0", + "public/assets/MessagesPage-Dh3eLASI.css": "570321b3601218331b24078f06c7b40cb7e2e739afd8111bbffd4606aa0b4e04", + "public/assets/MessagesPage-DhZT4s8A.js": "ced00fde1a1401059fe352e4a3bf411c9afd77b474da4ad89d21f724ccd31a71", + "public/assets/MessagesPage-DpjT4gW_.js": "ab47d8b2e4908f30fa123b1e67276705e6d62289a3522df8e6fc5a76b336eaa3", + "public/assets/MessagesPage-Dqh-J0Od.js": "ab22c9f13eb0d5876e01d68ec0f45204884cbf4ffd272ff87905004c48451e9c", + "public/assets/MessagesPage-Du-48GAP.js": "79e0f9f3d430554ce42b234970f606f23dae34951f385c2a9356507a9928f156", + "public/assets/MessagesPage-DvFnDOIP.css": "5787045f5c79d86259fde1fe5c8b3fb5e39ec73c7ae819817426309831919ab7", + "public/assets/MessagesPage-Hu-e3LT8.js": "08b878369365367dfc2268d18d7301477e9b3dab4eb8dc0955ce84ce41d2c0e9", + "public/assets/MessagesPage-NF3gl6RX.js": "36880373b540cb128d1711302d94071a8bbeb7a771bad705a23ede89cc3c9e50", + "public/assets/MessagesPage-bEGvW-60.js": "cadc06961d54d4c25b54193fa2b458f4b085cb1f6b977d230590459b81f09c29", + "public/assets/MessagesPage-jKakSR6S.js": "0ff478841e8836f0a25e7dc735d3a70993cbd236c599a0995bfc56b06ca12779", + "public/assets/MessagesPage-oFRIoqSr.js": "0aba7d2d1c6c9ad26ebcf2790c099da6ca84e50b9a1b8e633411a70f645a9bed", + "public/assets/MessagesPage-pwpd76Ze.js": "fa1a2b018ed960752a3e2d194a10e57df5b169a3904111c7f108ad95b315a5b2", + "public/assets/MicronEditorPage--WEqT3jg.js": "bedba40e087a5784a1098d6b7aae29c0a5a8463909cc88f813f900a654b2af7b", + "public/assets/MicronEditorPage-9474FCyd.js": "0f5b634bd5025c9aadefd61968cda8d7b2931114571f879b4a9045a8268a1896", + "public/assets/MicronEditorPage-976EAUIE.js": "e4e3f9fcdfc251a0a120f223651c84192c565d3ca83ba53b304952f9c945b1f1", + "public/assets/MicronEditorPage-BBK1A7cJ.js": "7c836c05853341cde4fecfd845e241f2e93627212a88592bf059eda1f4121698", + "public/assets/MicronEditorPage-BCfmF0Wu.js": "0d999ec2b7df643461725ef07ecfacf3956ee00d6eaddf71038735f3601aeaef", + "public/assets/MicronEditorPage-BDnlIDRb.js": "9fb055f8d44e813c000203d0f70e6479028619341a40a29bf97af001e0f8e70a", + "public/assets/MicronEditorPage-BEdSGsGl.js": "73f89cc0c3ac2afc2a349b70b10328d3dc3f978a057806ef6facafb1e2ca6062", + "public/assets/MicronEditorPage-BH3qvvuF.js": "d08db84c0e551de6932170d4e61f47eac2dee80cf8a426f6528ae3835f8cd0c1", + "public/assets/MicronEditorPage-BPN_tKAj.js": "c9de06c8c5fa69545d090cf4735cc36789580cf653ea4c157ffe6717f71de649", + "public/assets/MicronEditorPage-BljohsXU.js": "08e17145a05c7487d8d27df6aa4f44b0a51d4511c02a7cda84a39b2e4ea0b789", + "public/assets/MicronEditorPage-Bp0OQGCk.js": "0f5f283ea6649fcb729e97b2098a9086b9bb653a895e742ebaa26decae65ecf6", + "public/assets/MicronEditorPage-CdnSK4Uo.js": "a010f2c15924f8aef47907dbdf81217ae3a0fa6915cc9996f63d009b4a1d55bf", + "public/assets/MicronEditorPage-Ct9TtKxc.js": "31cfd93234267adbb1c5f58995f767cbb449a3145a2b45925bfc3d1b78a58171", + "public/assets/MicronEditorPage-DD85pikX.js": "1a35027d1104d65940feb305d34e32c86a43f8be6cab8a90217629efc7db4682", + "public/assets/MicronEditorPage-DIIopU7C.css": "0be40b9c9ab8f83f00ec13cf9fc10e64919159ff7216c4372a51d56846894c09", + "public/assets/MicronEditorPage-DRot3z-g.js": "867c7187a1e4f0dd77f5e891cc2187b977d0dd5d217dfcf3702bdf2157f42585", + "public/assets/MicronEditorPage-DTspJuUx.js": "2e75831a4a7baedee6bdc62c8d23460a2da4d5d680a566f397a5bf843675bc7c", + "public/assets/MicronEditorPage-Dky2E00O.js": "dd81f19e9c6b24f2281bcee3b6dda33271739d7e9dded6963c8d5134bbbc3266", + "public/assets/MicronEditorPage-DwnzZIiG.js": "d04289bf13209dc38bf468b251574367539c343409863b3a5a7c0ad6a6c0035a", + "public/assets/MicronEditorPage-WPZtDcMa.js": "cecab947536885253b085a126417bfff9005a2c860891900c389a225a30d2a3a", + "public/assets/MicronEditorPage-r4qbXEV_.js": "bf6a408d57acb7bc2b7dd870268c5626ef7a612913c96d39a6ddc2559d7b00ac", + "public/assets/NetworkVisualiserPage--VwAGE17.js": "912200e3d8e05aa651d0923f954f865a821e9725feaed761c0b4d3b7d671fb7e", + "public/assets/NetworkVisualiserPage-6HbZhKrv.js": "995e639984fb1e476fb0cac9958961a13bad35b5c78bd93d9007150308bd44dd", + "public/assets/NetworkVisualiserPage-8ldrPBdg.js": "3aa7dc00f60dfe7da6d8b89f19ac2782e5da1a50cad76f85a12626437629a08a", + "public/assets/NetworkVisualiserPage-BDZxaSEp.js": "cce59294587c2a9ec808d3e1b987d77b4894ad1d560e126602f4a7ab1165831f", + "public/assets/NetworkVisualiserPage-BloCX2-J.js": "7f740fb0be6d44d87007ee53deced22e59c97a362f8855cbc8920f24c81fce46", + "public/assets/NetworkVisualiserPage-BtNojdhI.js": "a7d40d0e0f9ab1a9ea61fe29b71332dc84e9e57cde7e088ca2b31e5cc750e6e5", + "public/assets/NetworkVisualiserPage-BvE1g6F7.js": "259df4f4b3142f5d0ea8118ed921028ea191e9995425edcb21f8bd8f4bcf7c6d", + "public/assets/NetworkVisualiserPage-BvtorWAa.js": "87979f662e9e4b1cd7446bc7d52a7a2d4a9c2a21f0663fa44490ca400ee68298", + "public/assets/NetworkVisualiserPage-C8FN5v1Q.js": "dd52a894134bc261d28daecc1e81bf63dfd282fa52aa91c6cc900c57c9802915", + "public/assets/NetworkVisualiserPage-CBTVsRc-.js": "feb5e5b7ec33c934a6ca1f24e089e7c449a061597a749762dfefef35e06397e7", + "public/assets/NetworkVisualiserPage-CN0_L7zc.js": "6aa642211adfc6541a0fda2000e69f3a0fcbf3d3d24d19b5387fe86588841185", + "public/assets/NetworkVisualiserPage-Cr4wxUcz.js": "ff9258c107ca71d8e730affff883ad765b35584f532770dd467790f163dae33d", + "public/assets/NetworkVisualiserPage-Dn4VoH5z.css": "7d0a1e2356c59fba617e055c685a2eb25fbbb7b720cf631afc7a11b1bba34eea", + "public/assets/NetworkVisualiserPage-DscY03Q-.js": "e6c70fef298e1ebd676a7f834ba1072fe436fea1a4b5e0c276fb735dc7e8697e", + "public/assets/NetworkVisualiserPage-DtS-D5Hu.js": "b4e64c4d47b3dd0afa2c6a7bcf67bc8a0587f0c95c05922f645034aa9bb05eb9", + "public/assets/NetworkVisualiserPage-LIs4u1pt.js": "7d7e553f04575225659d6ceaa018ac999808d9f6ea7e60abd5c456533c37db2a", + "public/assets/NetworkVisualiserPage-Z9_V0oWs.js": "fd14a74bc258d981747923b12c77eb2d34f7063e87c9d2c0979f3f2d78750f56", + "public/assets/NetworkVisualiserPage-ZF3d6qt6.js": "3417e5e80b6eaad815bbaede43bd7aa674b7f7c94a698c5145d9bc185e2ddd37", + "public/assets/NetworkVisualiserPage-bODOn8Sk.js": "410d83434602664b68c62e5795509d9c814b2dc2e1a8d6fc68bd3380adcd8c4b", + "public/assets/NetworkVisualiserPage-m92CsmaM.js": "2718c0c31bcb5551ea1be5901e3952b2a26d0ec90eac4a3ea15acdf5952b6995", + "public/assets/NetworkVisualiserPage-veyxCtSv.js": "ac2fb50a11f9ffd94467f29c83d93e2cb7e866686324aeefecba60f5497123d0", + "public/assets/NomadNetworkPage--nZVf6wV.js": "6da1a86a34cf1e7b6c0bb0937d126ca48a7723b19d13bbfbfd8869983cbbc22d", + "public/assets/NomadNetworkPage-BEqPSuu8.js": "bfea82c51f2e9ca1c78e8825f9652e7d495d7feec707be97cf9377165b5e8f4d", + "public/assets/NomadNetworkPage-BYwb_6pU.js": "695d3cc1b51e9b0b2c29fd09d7a900d8513b8030dd2f3b84d20745fb377fd8a8", + "public/assets/NomadNetworkPage-BfZmUe0y.js": "d6aa4fc064f83f595929497cde4ae7fddb3f1bf7f222f5075c36dbb718bb3654", + "public/assets/NomadNetworkPage-Bo8owhTU.css": "1f5299f7bac61900cbfaeaaabfd6256df60aa7be98986301a6e3e52b84ba6998", + "public/assets/NomadNetworkPage-CUUy1oU2.js": "e280cc7e6ad16735c69734cca855902a6d27619e55fd029cfc7995a9f638a88b", + "public/assets/NomadNetworkPage-CWAnzZ1T.js": "4a8a368800a8b4b392a7bbc96fbbe25fb8169c0376dd6da637ad02c4278bb23d", + "public/assets/NomadNetworkPage-CYSpqOgP.js": "62a3398b493b3ced17ed1e5c43c3a0f461cd6aedd6472ce62c49717e59c10887", + "public/assets/NomadNetworkPage-CamExDiU.js": "11045fbc6450f3964b31cf3672717b97ec758903b76898d14606a5e97cd5aa0c", + "public/assets/NomadNetworkPage-CodVPnoU.js": "22cced8c83fd77a6fb07bdc64d6683866e07b10e7f0c8af441a5e2f35245e10d", + "public/assets/NomadNetworkPage-DFZNgTOH.js": "9c33dbe7d486dbc69b5f648b546a7adc20a6b4bb891dd3d005329475cae02dc3", + "public/assets/NomadNetworkPage-DMPAhzup.js": "bac6cbee021c9a6abe918d136320d47c2b7045cbd74f09cb4d05103dab3d8129", + "public/assets/NomadNetworkPage-DVhS4FAr.js": "e4c02cb86ef491ed688544cc1c5ff8e555d4be7c318000edb51441d46df46abb", + "public/assets/NomadNetworkPage-DcVc1rHg.js": "5fdeba15fdbf851e105db4ccea70cee8ba82691eb31015c0a00a763a3f9a19e6", + "public/assets/NomadNetworkPage-DnB6nLtl.js": "186869fa630e44007212160f4f39af1a4e7f865ca51ea1f75a2eb943d2dd2143", + "public/assets/NomadNetworkPage-DsSzKmA1.js": "efc383c8fb6ed7690388c4ba242790e94461a9cb8c4ca4a9c64478338fd65044", + "public/assets/NomadNetworkPage-Lmz1epzk.js": "6751a0618c9e70f96555627c2d99a1de182a5f64a3d1a8cfa5bb48a23e41118c", + "public/assets/NomadNetworkPage-MSgWwiBK.js": "f27cd7706a29f5ce8a8f24bcaa95b7be2d250ecb09dbda1dd8ed97ac07f3e73f", + "public/assets/NomadNetworkPage-QTjm-B6C.js": "cdbf955e3a5742a5891b0fcb32ca900eff8fdcfdc8cdcc10628dc45a459890c8", + "public/assets/NomadNetworkPage-VPo-EVAj.js": "f2d82299408062ef154613716b3bb3c48a09d2d2918e6ba2ea1c72e2c8c31086", + "public/assets/NomadNetworkPage-tfP4kQ4u.js": "648ebcff2daa09aa170c266c689d2c9d172441ae89ba558b93d51b4c3812089f", + "public/assets/PaperMessagePage-BNCpEUaL.js": "37e7da26ed299d23062c931c33b995451bfc28809bbdbb8461da05e628944a08", + "public/assets/PaperMessagePage-BaF3Ut5B.js": "b28563c579d55ad363e115f4786ae9a24fd572fabe076a71af790ca5709d37aa", + "public/assets/PaperMessagePage-BrAvwrKv.js": "cc9b8c171ed0a44a11e45c99d980a408a923afe7836388da60eec03b8125fa44", + "public/assets/PaperMessagePage-C9k9SS0q.js": "6fb204be6abe32835eb3b590b6112f172c527c47776cdaad60c03e08e5c1e562", + "public/assets/PaperMessagePage-CC8g-I04.js": "d8d4dddb5565ef0ccf868c5dc4fe64d78431a72203a0ff6fa43fa39a8cb0b036", + "public/assets/PaperMessagePage-CE9vlmu4.js": "703ed77290fd3310cba4f3edfc8a11ec6600823ee0c358e38122ea6bf7c055c0", + "public/assets/PaperMessagePage-CPzgyW2-.js": "059d204d8231a79330b020d3d16d1c56ef8592a230a0e5daad17ba22ee4f4d88", + "public/assets/PaperMessagePage-CR1V2V1Q.js": "d696929efe4bbf5f429bcd81496c976205c7c3f825ece4a0b8cf989a16de4454", + "public/assets/PaperMessagePage-CR2WQUUT.js": "cbea36eed1fae62c181af7125fedfebcdabcaf67d4a1eae2f4b399e6ff233198", + "public/assets/PaperMessagePage-CwTlYRnA.js": "6f1a74dd40d2c2e554dd6ed398b63049780afb905d71259613de8732b44e6d32", + "public/assets/PaperMessagePage-CxO-Nb-0.js": "1cbdc4089c95abd1bb1262f7c5b3479968ca1d515e87bae541cd2aa8d90ab6fc", + "public/assets/PaperMessagePage-D3Cx3Pe6.js": "8d032d4ee0f767899b1976e017dace4dcfc9c6141ed70d06b3a0d822dab205f3", + "public/assets/PaperMessagePage-DC0KnRM0.js": "da6c5b1cb130119fdbc72e1276256f5388d97c48ef3351be403018b2801f5468", + "public/assets/PaperMessagePage-DGV26OvG.js": "6ff07c8dc9a5f67a864a9582b372fdddc29aac387143fa3a204cd5f8af77c7b9", + "public/assets/PaperMessagePage-DUbO946r.js": "2e7ef1df4126acfcde0a3aa55e90ae840a170054e9c481d632df1020a1078fc4", + "public/assets/PaperMessagePage-DWEk-OOr.js": "e1732d589989226b7fe67ad22cf6b538f5e582e9a7a163c21fd014f86b7675a1", + "public/assets/PaperMessagePage-DsjRDU4I.js": "010eccb77a7163b29ef8453231c2c76c7b2dd0bb48a637872fcef95c98033631", + "public/assets/PaperMessagePage-DsypBSmg.js": "30267a6d3b2aebfdb60cf840665c9189015b3d108478ec1a5200bf224cfe1478", + "public/assets/PaperMessagePage-iD5rlYTd.js": "d23ae2b554b231ecdc7ee34e0cfc23a92a2837ed2387cb33ba285dc2c0d10a51", + "public/assets/PaperMessagePage-mJGpcVHl.css": "bf27a06adc2d396d3bc30145ad14051877a21ada4435ca8115283bba69e7db60", + "public/assets/PaperMessagePage-wWLADHMp.js": "44cb324770e919fbc456a9ca3684eb6cb9fcabda4cd654a60182b18281af63d2", + "public/assets/PingPage-605oZnat.js": "cae3acbfeb55381902726b96bdf364dba3b89aa7267facb73d0449c12376cca7", + "public/assets/PingPage-8DCvEeij.js": "e897d5276b2b301b090b43575e583d511e7fcc00386b6aefa27328919d0b7451", + "public/assets/PingPage-B1nA7XCv.js": "0a467a82e0a785ea53151dd6b898461c5408b8072935b9f0074aa367f12e5d8f", + "public/assets/PingPage-BNNtwpel.js": "4ac6d361cb8abb2ba5556f0f00b9717331db905846c46a4b521544daec515e99", + "public/assets/PingPage-Be1jI5Ws.js": "c70fb31837f876b55d53dad392c039413150e704d7a701ba7aeaedbb0c5166bb", + "public/assets/PingPage-C7D9ck95.js": "522a2dfb346b45773495bd8c672bae359d6e2486e8fb03170e79718486d65951", + "public/assets/PingPage-CA_r1-ZQ.js": "b5044ffd384aa56366e0bc67880d0961eedc686a75bef0ae7ec8c727a61faf93", + "public/assets/PingPage-CBeqTAu8.js": "d9d5e70f41909e28a730022a599af6f00c8ffc077785909458ba9e94323a03f7", + "public/assets/PingPage-CYN3BZxh.js": "ec69a104a389bf8b99e05deada955bb8b768d52c8e1b641f26053c281e7cddcb", + "public/assets/PingPage-CpQX1R42.js": "00719d5d9932cc8b56d071eb5263098dee39c44e07ae73e88a510691507367d7", + "public/assets/PingPage-CpVPR4vQ.js": "c3343fc90293c7884b2fc97248c2df7730d3424542ed995733480f1eb1a3b6aa", + "public/assets/PingPage-CvqXFI9h.js": "9dff7fca0683fb0c11a962d050536c9e367577e97833bd75901ef5b57fca746d", + "public/assets/PingPage-DFZmoCHH.js": "9438d54dee0bac8361b2addcc66c749ba5f9be81da06015663f3bf4ebe11580e", + "public/assets/PingPage-DP51KWFg.js": "a7102d863bb393007c655cd34e7d4f3131367d1303ec2bcb3202ab355bf7fb35", + "public/assets/PingPage-Dxnwuj7k.js": "2e4e5577fc06745d21f293035a41fb71e37ebbbf30cb11c93738af37e9d48434", + "public/assets/PingPage-GbQtaXL7.js": "3c18baf3a849db5d8293d54cee7159fe2a8d853cf4865827e90aa067a6ee730e", + "public/assets/PingPage-U4P81pR7.js": "652a19ef53a979842e38ee1910b196cb09a6655e16ba1b653b792bd798c39674", + "public/assets/PingPage-jV34_kWA.js": "3f1971ea08110ecbe8aafd5d2391cbd774315048c13381626fc12ab6a901946d", + "public/assets/PingPage-q8ykEogI.js": "2b8044568df6f10ac934b45944e17479b16b74fefa58ea1ea96c64e118519462", + "public/assets/PingPage-wGol-jpK.js": "80a2d4b926ad5ce5810dc9c23de5ce547cef8b33e2fe688003170fa8d9446857", + "public/assets/ProfileIconPage-BD8um3u5.js": "d8539b579d44bf5241e0bd3a0de2e112d4ec22c76139222ff67cdaa626f00873", + "public/assets/ProfileIconPage-BODy1ADP.js": "98e3006064df0e54dbc8b82e94ad7f2afc29ac3529114d6930358719cc243980", + "public/assets/ProfileIconPage-BWQJwqVh.js": "e9733ff0cfbdd95b46ff8bec57a20603a2b2a4cab080e0eb13b988c9121d8bce", + "public/assets/ProfileIconPage-BkGnbcAy.js": "26d75d8beae39d0efbff4f4274eb592d0cd8708f6940e4eac2f54d308694dda4", + "public/assets/ProfileIconPage-BtfXSHS1.js": "e42d424139f7177ea67e9cdc6c6d17022e8366a1a2ea919924faee97a2a13a22", + "public/assets/ProfileIconPage-BuLRxDLh.js": "4ab27a738d6c86b6570a92efae3aa95b62d05ff19c63db04a12ddee55136ae67", + "public/assets/ProfileIconPage-BwLzG_fH.js": "93d54bfa9a1bd718fa4cac24b54944ad678158ffaf57a941f773297e1dd67dc0", + "public/assets/ProfileIconPage-CE-MQVgM.js": "418e440cec8d731f57f638ca4a4c7e104dbe1a655bec6e87569f67f81cfc3a65", + "public/assets/ProfileIconPage-CGj4CTqa.js": "e4294feca7cb8edb9c6ce2ecf776538efe62ab8ada4145c382637251e38892e0", + "public/assets/ProfileIconPage-ClZ6J3JQ.js": "4b5dd8253e715db5650144ac9097a9a45afadb2cc06a538a39766dd3ce6beb83", + "public/assets/ProfileIconPage-CpEQ7Yyg.js": "9dceb67d757e79c807d5f1dbf1849f478b9eadee21eaea9dfa92be2e8c123dd1", + "public/assets/ProfileIconPage-CzfhEjEM.js": "ed580980d6d4d365d98f467e56a44e884e437d1ab006ddf38dfcaa32678c92cb", + "public/assets/ProfileIconPage-D-tHvyk5.js": "353890704a641df34db34882ca061db9a76cfc2ed69b80f2a31207798c5fdba0", + "public/assets/ProfileIconPage-DDfbIMis.js": "c3a8d462fe4fc6f1756c5257baa8252ebf5b824366749da14f14e3354212e9a6", + "public/assets/ProfileIconPage-DcqQYExK.js": "005bed1af7252eb57c1bdcd6afd591fba77f126a42197c6f201be00832433b82", + "public/assets/ProfileIconPage-Dq31ODIj.js": "cb0928b38f7d94391c96d8110c966ab49345aa882cb133aba6bcf849dee9d427", + "public/assets/ProfileIconPage-DtLNk3ld.js": "53706e3c730a11cc0157da441fb35890f050c28092f4e787a750ac4075c0b8e0", + "public/assets/ProfileIconPage-Nafv9Djw.js": "6ffa92b0a3549b66ace1ed267184daccf439e2c827335b869b39620bc88881aa", + "public/assets/ProfileIconPage-e3G5YCSe.js": "9bf5f5ffdf1fa88cac8b054eef6907a700a70dfd0fe3495559d0461e82c34f2b", + "public/assets/ProfileIconPage-lXDI5s8D.js": "f68d3d8adf327846a4d1644d967a2389e37d4f7aaba49f10aa5e5ad1288ef938", + "public/assets/PropagationNodesPage-BcSeS9Oh.js": "6c2cbe7ae57620f030b04cb755054d791419e6b11b1282473d836949f6b4ed29", + "public/assets/PropagationNodesPage-BpDBsaK9.js": "1c3bcfe5b31344ca6769192c9f8ba5cb275d2a36337a19af39a45f1646d687d2", + "public/assets/PropagationNodesPage-Bs5QHHR4.js": "fb7dbf624aa0c5808dc32194044a30aebbe55a5773410b164b34819d0b523ed6", + "public/assets/PropagationNodesPage-C29jypnG.js": "1a402cfe6ac25cfcc28d3bd7604ce7af5650f42dacabc9043a04f146f0fdf3fb", + "public/assets/PropagationNodesPage-CFB490RL.js": "b14819a49885b54e9a290581521362552289221c38f1971fcbbb1c1cc0dbe1d2", + "public/assets/PropagationNodesPage-CfkUQJzn.js": "46f2690d94afce7b9a26898ed22e736a82beb924f9d89d83555f0ad4adbbfb62", + "public/assets/PropagationNodesPage-CrySA9JB.js": "950545402f7f96e64670228dee6756e2810cbf063d739eedc2a946a3030beaab", + "public/assets/PropagationNodesPage-D-VHRWQh.js": "b822e5b3e57e790d21c2f50bd0d60f2ecf13c0d5a08a88da6b6103bf7250c4df", + "public/assets/PropagationNodesPage-D1EJyBZo.js": "f212cd93629abb4c1f2dcb121ba22473c792969d3072d039a9f79511efe457d8", + "public/assets/PropagationNodesPage-D41vW7jg.js": "c301a492a8ce193a55593b9a593d6babb4e1185909055e1057e83e555bb0ab4e", + "public/assets/PropagationNodesPage-DgRJ3NNC.js": "18d710653e439d2be54e883a24284e616edd48279b8162b6d4d5a04a47c97482", + "public/assets/PropagationNodesPage-DjvSg0ye.js": "df2b4f23c70912ba06a0d6dd969a7e8c6408c9d1e9e263dc521b6572b863f7b3", + "public/assets/PropagationNodesPage-DmXJ1PHO.js": "aa7273a38e9d64ef28bd0401e6e142147dbf8074d20ad288846855bd087b10c0", + "public/assets/PropagationNodesPage-Dzh9c-1R.js": "044407b1accfc35c00a98096cb390ff01c4f3f6e705e47e9623113c0d2480ff7", + "public/assets/PropagationNodesPage-PivWmPbY.js": "29b8070e2f1c4c74bd5cb9ba908a8fce6b220d98f28c7de161f0ac140b84fda1", + "public/assets/PropagationNodesPage-QdoqH-DF.js": "b2841eab2f4ba9015647ad52320fb9db007fbb21bf870f5b00adfc6d852e5598", + "public/assets/PropagationNodesPage-aJ6q5dH_.js": "3a5ad9e493aeb28148fec23ecbb96126dc38ecb3a3491c1d60a24388342bddae", + "public/assets/PropagationNodesPage-dBBjMlwj.js": "d5ddd0e826409f2c500918bf14fc43483a606488c48e3bf12aa3ef7f7c3dc96e", + "public/assets/PropagationNodesPage-uqS_uhdD.js": "c7562fc2d49282b1ac3f65979921775cea32851ff4d208eaf73b0d438b144dc9", + "public/assets/PropagationNodesPage-wZWgAX0h.js": "a7d6ec9e4562e2e09226bf34552164433a715133494d00d03d5a81bd008c250c", + "public/assets/RNCPPage-B4w8obKN.js": "d84eb4b02e52c7efbd4ec9fef1e438a4d04e320fe00c408e25c8f7d582a6a7a9", + "public/assets/RNCPPage-BNHm9MT4.js": "aa6d05aa788088669cb42a184572a1e657e2fd3752c46cc0fd9d56d41dfab2a1", + "public/assets/RNCPPage-BZmPFdcq.js": "e40f5ceeb86d56eec72029be77a0303ac69ef70ad22bda2721516efe5458860f", + "public/assets/RNCPPage-BtJWBJUf.js": "320592191ec00d0aa225a6f055750272e22c0711cfe013476ed5bf2849adec54", + "public/assets/RNCPPage-C51Rhf4B.js": "ce3a3d8115d808737e25d75b853f1c99a294b239a37efa1697f8af3027617bf1", + "public/assets/RNCPPage-CLVdPZCs.js": "ea9408eb8b1f709bff1001288975f1b939c495f17bcf72488497fc77948434db", + "public/assets/RNCPPage-CWuifO8N.js": "5ce0e2cfdb777e61ce9f2741952597576c8a6ba5373dde50e4c09aa3ad146169", + "public/assets/RNCPPage-Cd-_YgyM.js": "945b90df6d16e164ff5a411df9718ca7864276d9da5f74f0f60a57667919be5c", + "public/assets/RNCPPage-CrlLp6sn.js": "14f68628e9aa2a669cede34bebf7b5ca41141d5fffd44d9af298695f6783c5a3", + "public/assets/RNCPPage-DI7MX88L.js": "6638e5b1847e9c4e6ef6e1ceec14aed7576da2a68ae4e8bc5720c14e21bf99ad", + "public/assets/RNCPPage-DLCuqLGc.js": "394b53b1d265847926b5ae568991780e1ef2b90cd69cd7afd8ea5caf5af6b55e", + "public/assets/RNCPPage-DLRqUp5O.js": "284c7222030f948aafc5e3f28a0713acf124ce9433bebeef9086c92cfce1e84d", + "public/assets/RNCPPage-DScEWctG.js": "4eda3b5fe8e143cfae990e276e1000aff19e03fc6af2641e23767381c59386f6", + "public/assets/RNCPPage-DjZnwIhz.js": "833cd918a561932fb6ab58094e2420ccba8afacbef727b947ab10fc0ef0eef9d", + "public/assets/RNCPPage-DkRYbHe0.js": "8dc9862ad7f7a77ac7e523e559b517298c734dd061065b5ad225699b7e28b917", + "public/assets/RNCPPage-DmJzoask.js": "6e8fbdb27c643ba75c2e2d0a35c3061ad5faede25dba0cb430c2ec0b48c93ba2", + "public/assets/RNCPPage-IAjOvgS3.js": "34475e562c053b1aeeb51ddc7bc17e187b0bac4f8e244f1de716a4de6d27f992", + "public/assets/RNCPPage-Vazu-YB1.js": "90628311410d963b3db4c3887d692e7b281c1f15340426853a9b09698f468132", + "public/assets/RNCPPage-c0FDPWtf.js": "e19b0d7804856c5257b53f1e6298651e928b0ad8790600c1b602c5a3530174d4", + "public/assets/RNCPPage-n6SAd7z8.js": "11a6ddb12363253ac02cde23b12c6c350899ca1a11a457949c5a3d713420d0d0", + "public/assets/RNProbePage-B4l8yxQP.js": "d608a7f434672ab7dd29793610b58085a9ef0117757175e70f3d9ee95d02d0f6", + "public/assets/RNProbePage-BIk8vXT2.js": "fcf82ca4dc1afa8f3b418a030bf3d6988fce9c515eddd789536fff8b1f750eaf", + "public/assets/RNProbePage-BKIWaXrV.js": "5e96a825ac3b3432874384ae49c0d7d5511ead8ff92d9754da0e2ee04b225834", + "public/assets/RNProbePage-BPocFDc_.js": "7bb8c8ce6c168b539c11fab16583d4efd98c4584fb212091806789d56cd3bb8a", + "public/assets/RNProbePage-BhmRwqjI.js": "339030561bbe2ff01e8e965e53e4b527251d9cbcc1722f35714180345d3dd0bc", + "public/assets/RNProbePage-BidNyS1i.js": "a2e0f2ea394cf1a5030caebd4590e936a97f5aec0e7d5ca109c850f6a50f2e39", + "public/assets/RNProbePage-BjKRvght.js": "f100b868ad40c2a64a29aa99fcb0c5abaabf0ac551dd538ed1abe87d59b5d02d", + "public/assets/RNProbePage-BvM_mqle.js": "34cc1ab6077855ddff0d69b7f8bac4eb574ff67e7a590f0e4935c0ae416dfe19", + "public/assets/RNProbePage-BzdcUd_3.js": "dd27703b77dd21ddac38bde4ca6edf4ab53346ce1b819e425fefe52f766086a5", + "public/assets/RNProbePage-C4UerEa8.js": "a11dee743d699b68332088931b4059028e71e0f134ad830b121bc846c579511d", + "public/assets/RNProbePage-CKfF2j6U.js": "a1ac77ecb045cef88a123c49a2e9d51df562a674d02ad58b11d184a6480fe457", + "public/assets/RNProbePage-D3ABqDbl.js": "881a386c7f66bbd0a52bcd1c87318341cc3d9a2bfa8005b46f535cae684f8899", + "public/assets/RNProbePage-DBadiIiD.js": "f304272b3e6dd6bc1510f7132f3b29b437ce5dd6c4ec844f41dba80007a66c6e", + "public/assets/RNProbePage-DaNPh4kV.js": "5d77863939deaceeb5672d82fed43698166bcd3b2dea06e09da6ed89d6b537d5", + "public/assets/RNProbePage-DdT2pR73.js": "703d83f7334f2d973c3a1107463de732e626aa7541d97d70580cfbf2606fb5bf", + "public/assets/RNProbePage-DpJgKra4.js": "5667f806e57c3eb3bdcb3d7ccf9c9d53200968c6438728b14628be191d1251a3", + "public/assets/RNProbePage-JTwuc4jR.js": "6eae7a3bc772c335e647bb886fa88e091c48c38e396a98d0a7a1de8167e4a52c", + "public/assets/RNProbePage-f3FJuUps.js": "24f588621a7ba733067e0cab9f87031b8de144e3d9f707c21eb7002dadaba4e7", + "public/assets/RNProbePage-hYBvGAJW.js": "c77416dadba9c37c0fa96b07099fc649693d0fdb29439e0a4c1672e139b0277d", + "public/assets/RNProbePage-pZHdmx6n.js": "de5b8e59636c2bb4e16c968c78c85354b4ad2444a32b4ea9ec52f11757e1d94e", + "public/assets/RNStatusPage-BEByD0uG.js": "8b9b4eab8e483c3ff9ee5f0268b5f61a847ee82c616284b5d6e8c44a0c2adfe0", + "public/assets/RNStatusPage-BLUgxsr9.js": "181956b34a29f769f3e3c4a593f3ad83c1767a1a024773d51279d4d5f3205f0c", + "public/assets/RNStatusPage-BMKr50iV.js": "e6493c806b2066cc915c2b3dc077b398f2393d2aaeeb3f3e02647a65e2905b3e", + "public/assets/RNStatusPage-BceiBbcN.js": "3b12a91d98cb48e82f02e7544aef46073cbee13d8b2ff081c41c7ac64648b6de", + "public/assets/RNStatusPage-BdHwTC35.js": "72a4808601d35076078be711d988459d3202d560d1149844b6548d2242f3da35", + "public/assets/RNStatusPage-BdytMz1p.js": "7c064e4a2ddba253abe1b83d34783392625e6232ffa077eeb1b656c1be5bd59c", + "public/assets/RNStatusPage-BrGcmhTG.js": "d2414c00cfed6d4c4280d95792765b1d75d7d09f84392c3dea3fea78ab5bbede", + "public/assets/RNStatusPage-Bt4n9T2V.js": "0e65f9f5ed8f93b68b76d36831cf9f1e0d847c9e31272fecaa76da1578fd29a7", + "public/assets/RNStatusPage-Bxsv2zmp.js": "838a611d479b56733ad854c2246db5987d2a0d0924bfdce41602b4af9cd0ed9f", + "public/assets/RNStatusPage-BzMMLgMU.js": "09d3397a3a86ca943a4391ce9c536789eac066ed17db29497d23e7b2cbc0c62d", + "public/assets/RNStatusPage-C8bB1KWP.js": "a2d07ffdbab07d003ca7ae310012cd2c2a463e4aa4ac45b3647c77e647403096", + "public/assets/RNStatusPage-CW332LiS.js": "b79932f83bafd4cd80977cd546926919e5194e709e93ae05c192cc59e77b8594", + "public/assets/RNStatusPage-CWOe58fZ.js": "3b36994a5b6e887c1f1fed3361414aa5f9987b758716fd3c0f69e51bc0973dce", + "public/assets/RNStatusPage-CYMG2EzP.js": "8c0f303cc1673da4c4da3de9f36cc1e5e713543fdd9a379aa39be5ef1c157aa0", + "public/assets/RNStatusPage-DHVEJlF1.js": "062867d170eee11cb1cce527b710d5736003e7d74a4896e053fe121beed8014b", + "public/assets/RNStatusPage-DHhXEvh5.js": "5894df2e4273208476cc1f88d9f027de224c61a4abbc8b0a697bdcae1e60dd32", + "public/assets/RNStatusPage-DTAG6m-B.js": "4b8564acbbc45104a50dcae3186ecf210cbc4516b721c29bbf0830fbb37f4d81", + "public/assets/RNStatusPage-DyHIMWIS.js": "7c8371dd3c400a31cf0795e3befc0481cfdc24a03d57f1e55eecdc3d7dde5007", + "public/assets/RNStatusPage-LNxrqC5V.js": "0ff1be162d4b5c36fe66994164f4606f6f7dca4be994909d3a648207ccfff86c", + "public/assets/RNStatusPage-nP-NnBNq.js": "42a63d8ceb7eda9196589ffeb151bfc5fade25d6e5b4ab60c05fc26693275435", + "public/assets/RNodeFlasherPage-BlEe_16U.js": "aec2b876192ae6d3a8d023fcf389ccf5eab7e7b9fe08ce242de427ceedffe0ba", + "public/assets/RobotoMonoNerdFont-Regular-DyU2aSNn.ttf": "3357fec1cce2d30c9a547ab35f5bd1742c005ce6343096427750bdf160be0a8d", + "public/assets/SettingsPage-B2NvFceQ.js": "1e3f221af2616af7a0289612f8023ded731106b07e1e30339f03d5d24bd53379", + "public/assets/SettingsPage-BQUh1tUa.js": "817973d93d98e4bb34ccac5dba8587801192e8a0b7fa51be1017008bb0151550", + "public/assets/SettingsPage-BTA4iAYq.js": "cb85dde7aa0476910bf0dcceb0bad242a1648f05a6288e67bbf2a50991318380", + "public/assets/SettingsPage-BUGPHwtI.js": "32e696172462d5baba26443be246224e55b69770880a2d3ac5a8fd5483cf8c11", + "public/assets/SettingsPage-BWB2qV6C.css": "6e1aee2c65ab471e2a4890178ac10f88c3849a59e2c0aa4a8b0c571e1b50a240", + "public/assets/SettingsPage-BaHpJhSS.js": "110bb4a3563a16ca0f9df53fbe9552f6a0f93012141a23a9a4f27eb8cac461ea", + "public/assets/SettingsPage-BlPc9PlL.js": "e6bf5a61abeabaadf9cc8c1d3868a3cf1e9b2615db3d691cd30e0b605fb4e67c", + "public/assets/SettingsPage-BmssvI6y.js": "c9108a55864e8f2088d4708b515f5172b78102ded19096774271b79ff42fd427", + "public/assets/SettingsPage-CYfLWd5w.js": "01ca1f7909c2adc7cf633386bb7f9a96182c4b1497f7bc1bbe2db3373e7ac440", + "public/assets/SettingsPage-Cb2_nZRb.js": "89042a562891d54d72057f05974c83b898ab607f3a8025a9248fd6c105cf4898", + "public/assets/SettingsPage-CnxrWsZe.js": "c9dc0924b67e643038c95a85448cd50d24952bbe93ea4e8ad5d19a31aefe335b", + "public/assets/SettingsPage-CtjAXkUk.js": "8469127b83d144af1a7feab00cdb9ad815fe5477c5c2f8d9f73808a5f9cc7156", + "public/assets/SettingsPage-Cz0lg0G9.js": "ae091a131d1df1224c04e831c84bdcc639886735975f4ffaf3e25cd1a3d2f442", + "public/assets/SettingsPage-D8v1LYHM.js": "edbfdac8b0fff4002a028d4b0d6f0a4f7e59c018841e63933b5d566d582b25f8", + "public/assets/SettingsPage-DNNaUueI.css": "94a4efae5d8a2181edb8c0084c6bcd146fa5883d458f087c3595185ce8613d9c", + "public/assets/SettingsPage-D_ODgYVz.js": "5b5d35973c93c935f9c731cbd09f8a672bb9e5b58c08438a86e2c69bc50fa859", + "public/assets/SettingsPage-DdgbM7p5.js": "3594fb935e9a5588d2e72318e2eaf9e852dadb4a5034166e2073058387a1498a", + "public/assets/SettingsPage-KhrqUKXb.js": "9060d18dd1bd03b008a2405fe3fb27e036c3f09b255680b08d7130c81db734f9", + "public/assets/SettingsPage-MkP7lVSP.js": "e7ea5e652fb54bed4779fc8db322f715d1cc2dfb831f3f607bc261e8c5f415ad", + "public/assets/SettingsPage-NdYUyyj7.js": "025db968ff36975cf2daed3f4ae5b16018dfd45236087d765e4a9afaaa6ca6d1", + "public/assets/SettingsPage-Z2YLdAhU.js": "a7e64da0d50c60ec1b1fca6f0ff592d7d685895dc0c599a06d03ee1b9a6b243e", + "public/assets/SettingsPage-_E4HIBwX.js": "d4d7cac2313b0a543615e58506f690f99833c883ac6d2b4ee2b26e5956a14275", + "public/assets/SettingsPage-piUsDFph.css": "749db426c7e6ac1908c73a6c0a09f9cd69fb1138958d043c026359f5d4dc73b4", + "public/assets/Toggle-59RCn4jY.js": "e190819576e499d02f118d1df8c06db03d7be266558d0100e6d3872398ea1beb", + "public/assets/Toggle-B23P06Ql.js": "1b5e45f32cf433ca71e96a12d516011acbb087587b916709e3d1fefa6d64eb67", + "public/assets/Toggle-B55QR0su.js": "02950f5a68b6fe738e39825dc7dcc5c0afa82677227f723d2013006f978d3a41", + "public/assets/Toggle-BHYEi1VG.js": "6ac766ce0ce10d61e286f0256b6f31fd95923571e8afba7e05bbaccbf6c5800e", + "public/assets/Toggle-BIziF9Iw.js": "bee87aa9038b535997584f6a1692d54b673e78d40e4781719bf652b8359a03aa", + "public/assets/Toggle-BJ3cL4O6.js": "e8b719abef326ee4c5a98c6b32604ed50c0eb2b169d0757039be55980d59b68b", + "public/assets/Toggle-BOBxd7lv.js": "9da76aac7f4801dfa49585425c45ee1a41d870730fa86aedba2d300283dad3a7", + "public/assets/Toggle-BrG7ascc.js": "395c73f3f1c433d3766fab564eed61ea3ba1e895ed7f16a6777c86b4163fcf07", + "public/assets/Toggle-ByyvHWcz.js": "2ae6a710b117555f6b518435c2cec1a8698077a4e1e3bc0237a0e52cc00ab0b7", + "public/assets/Toggle-C1eJWi3P.js": "28a4d307b0747821c42e1effa69f2483cc33c8a058dc0961d581087c92e5531d", + "public/assets/Toggle-C7yZtT8y.js": "4a31e89c1740bf907060cda0ae313fcc1fe6dffc9e931385a52718bbc743620e", + "public/assets/Toggle-CDqze-uV.js": "581f0b6631799fe8351eb639eaeae77fbeb414797ba376425f59c93faa70286d", + "public/assets/Toggle-CfxT6VP3.js": "e32283617de5e6488b5104bf4a976265fa8edf562faa28bcc8efbfc40e972a99", + "public/assets/Toggle-CvZO6wRO.js": "2382f825d23591b759638762352e216867c3e16bcfb6de05b848ab7cd52377e5", + "public/assets/Toggle-Di6uCFp1.js": "6cb9e7aaa5f99c1935653b5d67cd3e4955e68280a80e3d3524b22a33627715cc", + "public/assets/Toggle-DzZB-Ca-.js": "caa25fee9d0e1639382fd21ac5874c0cb404791ab92c98575153e241a47e53df", + "public/assets/Toggle-KICF86_Z.js": "73c5d62feec43e4689a84d08d172ee564ec127e8d23ae707206220f245feabd2", + "public/assets/Toggle-pfLCooS1.js": "d379760972f52e18e054a447e6010aeeac1d2c011aaaffa5dbd154e5f8c81649", + "public/assets/Toggle-q0STuMn3.js": "84d6968318b4d0d3c2284ceed841eee6f44e9c51a803de564624474b1a9b34de", + "public/assets/Toggle-qWK8RBtX.js": "05664494a7771378dbc527ce656d0c333a8799b9f9dd0624b43c6d0926c3f584", + "public/assets/ToolsPage--Z10aTLi.js": "5a2361fcc06573315270a10bbeeb16984d0bd8c3cf56d7deb5135b10879a9afa", + "public/assets/ToolsPage-B0FlDgbf.js": "3ba77f6b36b4bddcc2df5651ed87441762ccafd8c7e78fbdd94a48a76412fe6f", + "public/assets/ToolsPage-BAorvmOt.js": "a2a09143a3421c068aeab24efdaed1e7145e3748d1c62f18bc8678620efcb1f0", + "public/assets/ToolsPage-BE5NkXQB.js": "0a278f92cdbe177e13ca9fa6cedf774698f3c9f6b6f4e690cb3c5bb9a8ff67fb", + "public/assets/ToolsPage-BPN9J1bu.js": "b85977f856521310e5eca3524d655323afbd4c52052637b49d5a98abd8a2867d", + "public/assets/ToolsPage-BY5bRSRr.js": "2391ed3b659feab337ce254a150a8ba798a409ebf8139569b3ee8d5fd735cb45", + "public/assets/ToolsPage-BgNfJ8fh.js": "57546c75f72bf14e66c4769da529a4b7cb95f88ed7f2dd2127937aeaaccda18c", + "public/assets/ToolsPage-CCZUezpR.js": "f43dbe17e466c75d05e1f7d9fad87473c55627ffb0e2091d9f1f7df0b1bb7201", + "public/assets/ToolsPage-CIL1rxRX.js": "3929db20ca506dd8a0f5d472a05020b6d17ff19b05d1f5fbfc4de29c06a3c6a5", + "public/assets/ToolsPage-CPSXRsrJ.js": "6be53f8324013a9bf5ad594ef306a855153dfc61fbaa4ab7ca78b788ea2ff356", + "public/assets/ToolsPage-Cew0Sqhi.css": "e1b9d743705fa603a58891abe0593e8926429aabed9c8cd5d691bdc63a879e27", + "public/assets/ToolsPage-Cm6ojBq3.js": "ef96587aa53a4d8c372a6568d023766a15f855cb1285bcc5ec60736b5fc4b7df", + "public/assets/ToolsPage-D-IbKVrq.js": "a86c77d33d8d74e3ec54ff4a44134f0d0fcd7d9476a3b7f0f5337416fca56d08", + "public/assets/ToolsPage-DCqZsXeh.js": "0915f4ea91b2fd2245268693e263c2bab301e9102cbe3c9cc4ccbc5f6504639b", + "public/assets/ToolsPage-DHKGnt7Z.js": "514cb6228d057782556f7339071527cfc18e8bfddfb21ae90692feb252b7d71f", + "public/assets/ToolsPage-DTD8UxZd.js": "d91c74ee0ac8a88e73c60630edd6cc2081edfa503023dd00d266d65cf65f630c", + "public/assets/ToolsPage-DWpU2afb.js": "98d2bb2d51a8ce7db8d76bbb11ecf314eee807bd69b55b3c47cf60eb0c37dd90", + "public/assets/ToolsPage-DfjQvRAF.js": "f03a9b547353041bd26219408e1bad31e9986771c96e3a8c692fc62ca49b20c5", + "public/assets/ToolsPage-Dnc_orjh.js": "b1d79f9bfbe3f62b905b060100c9e4790834210fb02473ffd0318866966457c5", + "public/assets/ToolsPage-DvDwVZ8q.css": "8b40bbc801fb539e2346d30fe073f355e22a7c6f4f1fde6de2e4ea9ddd46d0c9", + "public/assets/ToolsPage-L38MWtvZ.js": "0dad49737c44ba1114cb0bdb7b8799f9ec0d49f0200c2a6d8af0355c4f95ae40", + "public/assets/ToolsPage-jGJtt1FO.js": "8fe7a078df4e0f36d6cf8ac4fe5dfd1db3cdd511cc5cf730ed1fd51662e1634c", + "public/assets/TranslatorPage-2Yezyf6n.js": "bcdc4098efae54479ee44c4a19f76f8a4c54dffdf580f979d005318ec6805979", + "public/assets/TranslatorPage-B9lOpJC8.js": "952cb88dcef6a892dbc871ae5b69def1f4fdc3b0d1b010e5d32dabcb1d8548f3", + "public/assets/TranslatorPage-BBnOy-9j.js": "3b350824bea7bb7abede2d7d4be55626706470ad69719547527e817b6a9a3e43", + "public/assets/TranslatorPage-BhB_cOYa.js": "dbfa31d1769aafa320be2de0b3e5c7d520296f8a57dae24777c56f59fe679271", + "public/assets/TranslatorPage-Bx-iamx_.js": "3b4268fa07113dcdf7fb7572f2ed8bba09bca596bb9cc7be1ac0988260d490d9", + "public/assets/TranslatorPage-BxiE4CTi.js": "88db0f1398eec72b401b07b94434d09bf56767ff3823d15f8e99a550d6f07658", + "public/assets/TranslatorPage-C1MrKE6r.js": "beb6a5f7ed42c0662044de209efd6e6d1a026e6c7d7e4cc46854ce1d1376bbfd", + "public/assets/TranslatorPage-C2D0qvec.js": "3f321eaf12c7981a6944df496dd8ce427e0680e758441093ca24a8c8f8633fc6", + "public/assets/TranslatorPage-CQs4_NoK.js": "a8d8838e74d631444196a11291a7299e4a75d378476510c46a294330d7620ac7", + "public/assets/TranslatorPage-CZ__7xGT.js": "7f765bf40e4a2c0382a8806142e67a1255a164fea3a3c124a498eaa584320964", + "public/assets/TranslatorPage-D0lqy7LK.js": "e24560834361754885f6e9b6b07233adc076bf109e769fb4a397ee857dd77078", + "public/assets/TranslatorPage-DU0_fIZo.js": "a0127d8ace8a56e1f5de1a844b40f100f6342258ea5c729147e6ce18db7ad9cd", + "public/assets/TranslatorPage-DYyPNK-E.js": "d38688427bdfabf261aaec97d5ae5323434887147869018e818abca639529d37", + "public/assets/TranslatorPage-DdhsGqd-.js": "2d3628cc34aabe5c667396046c96c61e3a53736745dc8f39f6cba38d09c55a6d", + "public/assets/TranslatorPage-Die2Kti8.js": "9b0d0a594e2b147a2fe1430cda8770d26e463ef2211644be2f93ee22e4609e2d", + "public/assets/TranslatorPage-DiyAD1yE.js": "d780a4aff40db62a2c57859c87f6b48b01b78c23e4b23c46488740cb1dbc06f1", + "public/assets/TranslatorPage-Dnyns-3_.js": "ceedc57a5251f582c21abb8848cbe032daeac2de2b94e589ca63117ae6834537", + "public/assets/TranslatorPage-Dvv62_Nt.js": "fda3d637c566626f81a0e0a7b35d82b3cdfb3d1d7536ee8725a1112411b35358", + "public/assets/TranslatorPage-Dz54TokK.js": "e825e1ab1b1bd1ed7cac4412a89841765aad1a70079b63c614a1c8b816ce306c", + "public/assets/TranslatorPage-r2ceAdNq.js": "832a2bb19c517aa4915101213d375b0891ebbfd7cb1163ee896702938183d2a5", + "public/assets/app-2fy0ix7T.css": "601334eab816b5d14c18632e689131acf4b5a36b223e63c5bf123acbae866d2f", + "public/assets/app-B6j1Aqua.js": "6c5e9758d44fc3096cdf20bb16d82a4e9ac04f83faa3dcd1793cc55824040ce6", + "public/assets/app-B8CKyts2.js": "c3ed5f12accc876c7f3597eff1ed212eb501fe8e73832b9715e4cd0a388e9a23", + "public/assets/app-BHB7Vsxd.js": "5831bb7c937c5bfc9597032a522f4952f9730f64e11c956e5be4bbb793d55a9a", + "public/assets/app-BOBXDFxj.js": "20b7aef1b45421bc64a7c8a8c1e32ae6e32c831a28dedc051c5ff5861aa84b52", + "public/assets/app-BXuILOrd.css": "9fbdfe449e583ed793c389fbaea80ad69b0a3f38025cbb4c1109eefc8819950a", + "public/assets/app-BaDr5OMd.js": "ca195a3822dbaaee8442308144826a57d2ee81d8d73d93aa5f9923c421bb79de", + "public/assets/app-BbDj6Q8X.js": "ce7025732322005c795d7202dfcf52a9cd4ce143149969cc1073d41fe6381a3a", + "public/assets/app-BbY1SChk.js": "dfc0594a5d3142b9220853d26bbf19803ab5d0721001b4f42f47131dd40f7190", + "public/assets/app-BmpTRjdT.js": "c2af7991c823b38c43d1e91bc824e1b984f76aa38b1c636326b19e1d96378726", + "public/assets/app-Bohj3HPH.js": "439c99979819fe2f65c621b8b8bae00fef9f6dacb520fbcf2acf5685f290a87a", + "public/assets/app-C4nDn0Na.js": "77d4d6975479c3fb608238b69b0abc50f1a46eec980a0c1be53d9622bd2d4a8d", + "public/assets/app-CE3Hv6a6.js": "81aca058b7bd320fca3b65d92e5a7c5e6e851318fcaa854cbe712cdf1b670696", + "public/assets/app-CTRkibwF.css": "b8f7a7d52f31af48e35ca0c2a8670edd64c4f28361b4eb412a00f28597221e90", + "public/assets/app-CTqOzAzO.js": "6aa9e4f4366a4769220f697be7dac38146d645658190e33c7145bee4bfb98e02", + "public/assets/app-Cj_1FtQw.css": "cf2e01aaf6fad80d752baf7a3f07d4d7dc08ea4d38316f341d5634e1c952c926", + "public/assets/app-CnWI1kjY.js": "890f181a79455eabdbf26cc9ca4eab34ea3091da92ad3b905de8297c9a8f0e7d", + "public/assets/app-CwKr_yxB.css": "caeb23a9c6bf10c22b8d156e1d96dbc3e72d18ee76ac37be9885831cd62868ab", + "public/assets/app-DTD_JJvV.css": "8f549a4267d38e01ba9af00e4287bc93b9516e68aae18819f6bc5ea1d509bab9", + "public/assets/app-DTNPJDnD.css": "795b62ed84ce576bf737e9e43276b4a09fd7087233abfdb6b50bf33a8c46b011", + "public/assets/app-DjEvJFWn.js": "9b78392a3df0b616fa569cab8f441a338573e9a028471405892ba0368014d56e", + "public/assets/app-DsETXe-k.js": "b935ea6a5c9ed4cf93c1128812803ba272a2d4d77eb857631a949f35e6fb0ead", + "public/assets/app-OYNH2PgU.js": "0888811e513a882dc4259a6b94fa29279d95c68bb258a975583cadeb312f55a4", + "public/assets/app-QAFEbTCA.js": "9c9e9e3313b36c9e03aadb705c21fae67d232290218796a00419bbde748e27e3", + "public/assets/app-RFBX_G6w.js": "63bd0ea6fab70f05d4801aa7b95c3461246c3ecf20d5fe4a7da34ad664a33b96", + "public/assets/app-_GNIkRr2.js": "1351b5f5973f2b41a814d2e938eeca2581313a247463a3fd76c5686d635a46e7", + "public/assets/app-zuyAIlIs.js": "a7c41ab6e15ea121781a8b7da09c33a67431219a2253ba78dabb588739aec470", + "public/assets/images/logo-chat-bubble.png": "2d73e0e18141cbcebf0a38c31c2f5152370291f6eb8eeb65a7fd02a29d9b82da", + "public/assets/images/logo.png": "2d73e0e18141cbcebf0a38c31c2f5152370291f6eb8eeb65a7fd02a29d9b82da", + "public/assets/images/network-visualiser/interface_connected.png": "a6f2e0a1efb5949789bc47a15922e3d2f443d51cee30b984b50d7576a5e95e7f", + "public/assets/images/network-visualiser/interface_disconnected.png": "948f78f1957ffa821114bd18d4cf13986c65269055eedd106be252b44274fd9a", + "public/assets/images/network-visualiser/server.png": "9f995a1dbb06232d71be176267199439b923d5898e076c890dea01b6a9b16535", + "public/assets/images/network-visualiser/server_1hop.png": "7a3ad9dbe673dd2ef8a5b7d90ac9c276d436d8b1d16bb69f8ce84e40f5bcfb92", + "public/assets/images/network-visualiser/user.png": "bcad4e7a6bcde488199f23e9fd6c60a6fd928c05f079175499785c5636f13796", + "public/assets/images/network-visualiser/user_1hop.png": "91aa213e0d7d8ae55c5d89c79e77cc37ff3bc5d405876af91cb70ea1ac16cd2a", + "public/assets/images/reticulum_logo_512.png": "035f499a1619cfb6d2da2ca99539e9e9d122bb18addf2ab83d3413592e7662f9", + "public/assets/js/codec2-emscripten/c2dec.js": "5771ab23ccd1fc7c99b1b9a257461951454918dad23ecd8b549c651540cc078d", + "public/assets/js/codec2-emscripten/c2dec.wasm": "24f8611ba983641ee3582f1ad12163697b582134308bba2449eec1ae30935547", + "public/assets/js/codec2-emscripten/c2enc.js": "e7b155ab6333b71ec2fabe32a55fc443db167be7491c27bb68948388c162d402", + "public/assets/js/codec2-emscripten/c2enc.wasm": "4cf5e44036256236b5f440bc6dfd338d9d049a242a3bb90756dac68a43b31efd", + "public/assets/js/codec2-emscripten/codec2-lib.js": "9d0a78ea1db26314d34dbd09921d625df866ae47cd8db511b0bbb2e78f0e950e", + "public/assets/js/codec2-emscripten/codec2-microphone-recorder.js": "b7bd6721b30881f1c3ec8d6461e15d6bba94a8c6a4eac6be0dc8214a3b0863b3", + "public/assets/js/codec2-emscripten/index.html": "67b3a8c8777f87a5bd9383ad188e6fb5025c6131628b354d8c0c0ebfae6175b7", + "public/assets/js/codec2-emscripten/processor.js": "efe9a88a4b1ba8ad72373480e976b496632097d0344997bcf4b93d5e7c7b6bd9", + "public/assets/js/codec2-emscripten/sox.js": "e1c13c18a90e7b1518f0830cf1d2b263856f2276381278eb78afe25b28814a70", + "public/assets/js/codec2-emscripten/sox.wasm": "eab8957398b7df78550e5d74bdbe38dd232ad5e6d68fc874daa78a9ed669753e", + "public/assets/js/codec2-emscripten/wav-encoder.js": "dfeec66f1ffeda1b783d240afa85141c77df3e5e6bfb0f12caa89c586c3e6b18", + "public/assets/js/tailwindcss/tailwind-v3.4.3-forms-v0.5.7.js": "1829e78dfbc21c0929c4fc257e849d054dd7162f4bf2a5f5676617fedd990e54", + "public/assets/logo-DZE3PCxd.png": "2d73e0e18141cbcebf0a38c31c2f5152370291f6eb8eeb65a7fd02a29d9b82da", + "public/assets/materialdesignicons-webfont-B7mPwVP_.ttf": "61e8aba5a4e981fe22cf7c8e8bcdbea00476e75c62c37f01bf7ee33361d68428", + "public/assets/materialdesignicons-webfont-CSr8KVlo.eot": "0b183104d2fc5f26196e773c77bdaf2e05509fd4259d2d15ecedca79b87e84f9", + "public/assets/materialdesignicons-webfont-Dp5v-WZN.woff2": "662fefa8f2f8a95c18588d21774789c107c64e771cbe65a69af46291c4311afc", + "public/assets/materialdesignicons-webfont-PXm3-2wK.woff": "a5928a0d5c2f624e46f98d9b15c2f60045377f7c594dd78a1759132ea3b463eb", + "public/assets/proto/audio_call.proto": "db67d003f56bf1f8317913deeac6ecb55760c573c82f350cacfd6450da4260fa", + "public/assets/vendor-axios-C1it03rL.js": "03842a2abe5c255e5e77227c5a50978b76230f5639302ad531bafe5552ee16e7", + "public/assets/vendor-compressor-DH721-V_.js": "0d60c566c6074e3a14899a7eef34de5fbf100c060cdb7f91c85c17393ae2df12", + "public/assets/vendor-dayjs-Bm9JdU5I.js": "0e7b1d2a8b6a9f404245fc05c44363797e8ff0a9263796c593aba3924ff15591", + "public/assets/vendor-mdi-BDiqFXHQ.js": "bf220609d423893e0a456f755b3146cc5c8477891b2d5bb999fcfc8f5c61e737", + "public/assets/vendor-mdi-Cx2MC6_s.js": "2e568519042465df31a18333c29eb8d32d4a935f2ed033f76c8eb147bea222f3", + "public/assets/vendor-micron-BSEEgE84.js": "a66dee6052d9e0008f7295d581178addecb939553f72f536bf5b67bed87285fd", + "public/assets/vendor-micron-DU_TH2sZ.js": "1b0bf55b194ec42669c46d877185f82ec71d88dbb878ba93381c42db0a8adf7d", + "public/assets/vendor-mitt-BHPWSuhB.js": "ed25e2504b52c9fe7e4ddd6942bbcf1963d347dd112bec223f25666dfd8b6845", + "public/assets/vendor-other-BjIYm04z.css": "cfce4b37252781143ea9b1c6bdbdb1348e0b77194ec89ccc19a5e00d2d365e2f", + "public/assets/vendor-other-BtPCEgEn.css": "7f80cd941e5d83568410726dadb7f2a05e47fd819961b76c744b88cbb64d0519", + "public/assets/vendor-other-C0noCZhC.js": "cca9b42fdf038917f8866c1f9d4750081d5f402bd2042b61346190da94b3bf35", + "public/assets/vendor-other-DktJSGWy.js": "cca9b42fdf038917f8866c1f9d4750081d5f402bd2042b61346190da94b3bf35", + "public/assets/vendor-vis-CfGaKk2g.css": "29ca7c5984322088d17495b1e842dc3b612893a0d07b3d004a00dc3a37c23be9", + "public/assets/vendor-vis-DW7fmx29.js": "9e93cc024f5ff1bcc50a5cd2a71ba6184258109d7160aee1e9fb66ae5941ca3e", + "public/assets/vendor-vue-DpQ2LQiZ.js": "887b6b1c046857e64597df74c7845578798ade35dacdfa88ecb569b20debeb93", + "public/assets/vendor-vue-XbqVpb8f.js": "ac54e340d86d33d265fd8a3f3e3c64334ec3dd50106506c100defbaa80a9dc81", + "public/assets/vendor-vue-router-B-dvAhom.js": "38550e69ae685e1d9f5c405ce019b70a808d84bfb2a6ae46ac93a18a2aa44a9d", + "public/assets/vendor-vue-router-DNECaeJa.js": "8f40faea305bdf48a74b198e2a4cf57aad2584d27c649926908092dfe3346614", + "public/assets/vendor-vuetify-BLqNJyZz.js": "ab7479f05c00ded360c0dabb266e57a260385782ee1db27973907892400b8793", + "public/assets/vendor-vuetify-CZPGfs0P.js": "65924b51d3aa97e6b2b6c2537a6de5e03d5c502cfd6a32a763efe3f4090539a5", + "public/assets/vendor-vuetify-Pi5piU4G.css": "3bfdb31e32b3a58f3d73a72709fa746a49b5080afdb80e6312d142bbc2d1b3e6", + "public/favicons/favicon-512x512.png": "2d73e0e18141cbcebf0a38c31c2f5152370291f6eb8eeb65a7fd02a29d9b82da", + "public/index.html": "12b6b63d5bb8164a855a6166e742792db319a3e26ec32ff91f2c277ebc4b3874", + "public/manifest.json": "3087f201e01ba1e4783999433b9cbd34071a634f737b932c288bd2b0bbba405a", + "public/meshchatx-docs/meshchat_on_android_with_termux.md": "66b5ddd5611a5bde02072e6e3ec4a6af01c7baaba90531b2d3e385ea5ad58a70", + "public/meshchatx-docs/meshchat_on_docker.md": "6c0f0874d08188435d694f0d73114485cbebcfa16459e4c52ecd3f86b794fc4d", + "public/meshchatx-docs/meshchat_on_raspberry_pi.md": "6a9db4284c00ea2e0443bdab124e256d3daf89489482141ed124c8115a62e360", + "public/rnode-flasher/LICENSE": "4e590a1cbb467d60c6c55ca547dc71517955098d13d5483e3d9191fc03af44df", + "public/rnode-flasher/README.md": "d453c7d31a69ff39fea6d096cba10fb8025a3eeef9c17e310ff38ce60adf311f", + "public/rnode-flasher/index.html": "496fbd47d8879846812ba1e8895d3ea2451dc7686b374f3a47e4420b2f915865", + "public/rnode-flasher/js/crypto-js@3.9.1-1/core.js": "4c350747271d3901045e9f6939ec2f0edd40dc6140bec6b8e540b66d80310b86", + "public/rnode-flasher/js/crypto-js@3.9.1-1/md5.js": "1d7f30238bedb8d3016abb0f4096480d960e1d1668720668d47dd39f80f24a48", + "public/rnode-flasher/js/esptool-js@0.4.5/bundle.js": "6320195516fa7974926025e3f33d0fd4a18cab3e1cf26526b9e2c079007176b0", + "public/rnode-flasher/js/nrf52_dfu_flasher.js": "f7f48c88357dae487d724cbb735af12a93b0843aa75183d1dfd51b4be82c6f54", + "public/rnode-flasher/js/rnode.js": "31583723b56724d3485873d49a8eb4abe07587462f700dd25a2f9eae02ab4f22", + "public/rnode-flasher/js/tailwindcss/tailwind-v3.4.3-forms-v0.5.7.js": "1829e78dfbc21c0929c4fc257e849d054dd7162f4bf2a5f5676617fedd990e54", + "public/rnode-flasher/js/vue@3.4.26/dist/vue.global.js": "c71ec2d9f47acae53c0202acbf771c1e06e13943708c8e7a4ef76f733b91e2b5", + "public/rnode-flasher/js/web-serial-polyfill@1.0.15/dist/serial.js": "739e8a556a1453c87a619b2520dcbda39f0cea55c5d0bf865bc5967e7e4fcad0", + "public/rnode-flasher/js/zip.min.js": "4435d44e680530b0965c7219227f14601f56fd703a27dc7844c1b78fa4501b76", + "public/rnode-flasher/reticulum_logo_512.png": "035f499a1619cfb6d2da2ca99539e9e9d122bb18addf2ab83d3413592e7662f9", + "public/service-worker.js": "33d3c60e6a84f1e43ffdb03a32a96d8d87e716f9dbf3828896810c91cc694d5c" + } +} diff --git a/electron/main.js b/electron/main.js index ee86e31..40f541f 100644 --- a/electron/main.js +++ b/electron/main.js @@ -350,7 +350,7 @@ app.whenReady().then(async () => { "style-src 'self' 'unsafe-inline'", "img-src 'self' data: blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org", "font-src 'self' data:", - "connect-src 'self' http://localhost:9337 https://localhost:9337 ws://localhost:* wss://localhost:* blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://nominatim.openstreetmap.org https://api.github.com https://objects.githubusercontent.com https://github.com", + "connect-src 'self' http://localhost:9337 https://localhost:9337 ws://localhost:* wss://localhost:* blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://nominatim.openstreetmap.org https://git.quad4.io", "media-src 'self' blob:", "worker-src 'self' blob:", "frame-src 'self'", diff --git a/meshchatx/meshchat.py b/meshchatx/meshchat.py index 8df3c8d..8f8fda9 100644 --- a/meshchatx/meshchat.py +++ b/meshchatx/meshchat.py @@ -1756,8 +1756,8 @@ class ReticulumMeshChat: timestamp=time.time(), ) - # Trigger missed call notification if it was an incoming call that ended while ringing - if is_incoming and status_code == 4: + # Trigger missed call notification if it was an incoming call that ended without being established + if is_incoming and not self.telephone_manager.call_was_established: # Check if we should suppress the notification/websocket message # If DND was on, we still record it but maybe skip the noisy websocket? # Actually, persistent notification is good. @@ -1812,7 +1812,9 @@ class ReticulumMeshChat: target_name = None if target_hash: try: - contact = ctx.database.contacts.get_contact_by_hash(target_hash) + contact = ctx.database.contacts.get_contact_by_identity_hash( + target_hash + ) if contact: target_name = contact.name except Exception: # noqa: S110 @@ -2264,7 +2266,7 @@ class ReticulumMeshChat: return web.json_response({"error": "URL is required"}, status=400) # Restrict to GitHub for safety - if not url.startswith("https://github.com/") and not url.startswith( + if not url.startswith("https://git.quad4.io/") and not url.startswith( "https://objects.githubusercontent.com/" ): return web.json_response({"error": "Invalid download URL"}, status=403) @@ -3330,9 +3332,48 @@ class ReticulumMeshChat: # update docs @routes.post("/api/v1/docs/update") async def docs_update(request): - success = self.docs_manager.update_docs() + version = request.query.get("version", "latest") + success = self.docs_manager.update_docs(version=version) return web.json_response({"success": success}) + # upload docs zip + @routes.post("/api/v1/docs/upload") + async def docs_upload(request): + try: + reader = await request.multipart() + field = await reader.next() + if field.name != "file": + return web.json_response( + {"error": "No file field in multipart request"}, status=400 + ) + + version = request.query.get("version") + if not version: + # use timestamp if no version provided + version = f"upload-{int(time.time())}" + + zip_data = await field.read() + success = self.docs_manager.upload_zip(zip_data, version) + return web.json_response({"success": success, "version": version}) + except Exception as e: + return web.json_response({"error": str(e)}, status=500) + + # switch docs version + @routes.post("/api/v1/docs/switch") + async def docs_switch(request): + try: + data = await request.json() + version = data.get("version") + if not version: + return web.json_response( + {"error": "No version provided"}, status=400 + ) + + success = self.docs_manager.switch_version(version) + return web.json_response({"success": success}) + except Exception as e: + return web.json_response({"error": str(e)}, status=500) + # search docs @routes.get("/api/v1/docs/search") async def docs_search(request): @@ -3875,7 +3916,7 @@ class ReticulumMeshChat: initiation_target_name = None if initiation_target_hash: try: - contact = self.database.contacts.get_contact_by_hash( + contact = self.database.contacts.get_contact_by_identity_hash( initiation_target_hash ) if contact: @@ -4230,7 +4271,9 @@ class ReticulumMeshChat: "greeting.opus", ) if os.path.exists(filepath): - return web.FileResponse(filepath) + return web.FileResponse( + filepath, headers={"Content-Type": "audio/opus"} + ) return web.json_response( {"message": "Greeting audio not found"}, status=404, @@ -4240,6 +4283,16 @@ class ReticulumMeshChat: @routes.get("/api/v1/telephone/voicemails/{id}/audio") async def telephone_voicemail_audio(request): voicemail_id = request.match_info.get("id") + try: + voicemail_id = int(voicemail_id) + except (ValueError, TypeError): + return web.json_response({"message": "Invalid voicemail ID"}, status=400) + + if not self.voicemail_manager: + return web.json_response( + {"message": "Voicemail manager not available"}, status=503 + ) + voicemail = self.database.voicemails.get_voicemail(voicemail_id) if voicemail: filepath = os.path.join( @@ -4247,7 +4300,10 @@ class ReticulumMeshChat: voicemail["filename"], ) if os.path.exists(filepath): - return web.FileResponse(filepath) + # Browsers might need a proper content type for .opus files + return web.FileResponse( + filepath, headers={"Content-Type": "audio/opus"} + ) RNS.log( f"Voicemail: Recording file missing for ID {voicemail_id}: {filepath}", RNS.LOG_ERROR, @@ -4288,6 +4344,13 @@ class ReticulumMeshChat: @routes.get("/api/v1/telephone/recordings/{id}/audio/{side}") async def telephone_recording_audio(request): recording_id = request.match_info.get("id") + try: + recording_id = int(recording_id) + except (ValueError, TypeError): + return web.json_response( + {"message": "Invalid recording ID"}, status=400 + ) + side = request.match_info.get("side") # rx or tx recording = self.database.telephone.get_call_recording(recording_id) if recording: @@ -4302,7 +4365,9 @@ class ReticulumMeshChat: filename, ) if os.path.exists(filepath): - return web.FileResponse(filepath) + return web.FileResponse( + filepath, headers={"Content-Type": "audio/opus"} + ) return web.json_response({"message": "Recording not found"}, status=404) @@ -7105,6 +7170,14 @@ class ReticulumMeshChat: response.headers["Content-Type"] = "application/wasm" elif path.endswith(".html"): response.headers["Content-Type"] = "text/html; charset=utf-8" + elif path.endswith(".opus"): + response.headers["Content-Type"] = "audio/opus" + elif path.endswith(".ogg"): + response.headers["Content-Type"] = "audio/ogg" + elif path.endswith(".wav"): + response.headers["Content-Type"] = "audio/wav" + elif path.endswith(".mp3"): + response.headers["Content-Type"] = "audio/mpeg" return response # security headers middleware @@ -7135,7 +7208,7 @@ class ReticulumMeshChat: "style-src 'self' 'unsafe-inline'; " "img-src 'self' data: blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org; " "font-src 'self' data:; " - "connect-src 'self' ws://localhost:* wss://localhost:* blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://nominatim.openstreetmap.org https://api.github.com https://objects.githubusercontent.com https://github.com; " + "connect-src 'self' ws://localhost:* wss://localhost:* blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://nominatim.openstreetmap.org https://git.quad4.io; " "media-src 'self' blob:; " "worker-src 'self' blob:; " "frame-src 'self'; " @@ -7335,7 +7408,7 @@ class ReticulumMeshChat: ctx.message_router.announce_propagation_node() # send announce for telephone - ctx.telephone_manager.announce() + ctx.telephone_manager.announce(display_name=ctx.config.display_name.get()) # tell websocket clients we just announced await self.send_announced_to_websocket_clients(context=ctx) @@ -8629,7 +8702,7 @@ class ReticulumMeshChat: announce["app_data"], ) elif announce["aspect"] == "lxst.telephony": - display_name = announce.get("display_name") or "Anonymous Peer" + display_name = parse_lxmf_display_name(announce["app_data"]) # Try to find associated LXMF destination hash if this is a telephony announce lxmf_destination_hash = None @@ -9452,7 +9525,8 @@ class ReticulumMeshChat: print( "Received an announce from " + RNS.prettyhexrep(destination_hash) - + " for [lxst.telephony]", + + " for [lxst.telephony]" + + (f" ({display_name})" if (display_name := parse_lxmf_display_name(base64.b64encode(app_data).decode() if app_data else None, None)) else "") ) # track announce timestamp diff --git a/meshchatx/src/backend/docs_manager.py b/meshchatx/src/backend/docs_manager.py index 7064a17..513839e 100644 --- a/meshchatx/src/backend/docs_manager.py +++ b/meshchatx/src/backend/docs_manager.py @@ -19,29 +19,33 @@ class DocsManager: self.storage_dir = storage_dir # Determine docs directories - # If storage_dir is provided, we prefer using it for documentation storage - # to avoid Read-only file system errors in environments like AppImages. if self.storage_dir: - self.docs_dir = os.path.join(self.storage_dir, "reticulum-docs") + self.docs_base_dir = os.path.join(self.storage_dir, "reticulum-docs") self.meshchatx_docs_dir = os.path.join(self.storage_dir, "meshchatx-docs") else: - self.docs_dir = os.path.join(self.public_dir, "reticulum-docs") + self.docs_base_dir = os.path.join(self.public_dir, "reticulum-docs") self.meshchatx_docs_dir = os.path.join(self.public_dir, "meshchatx-docs") + # The actual docs are served from this directory + # We will use a 'current' subdirectory for the active version + self.docs_dir = os.path.join(self.docs_base_dir, "current") + self.versions_dir = os.path.join(self.docs_base_dir, "versions") + self.download_status = "idle" self.download_progress = 0 self.last_error = None # Ensure docs directories exist try: - if not os.path.exists(self.docs_dir): - os.makedirs(self.docs_dir) + for d in [self.docs_base_dir, self.versions_dir, self.meshchatx_docs_dir]: + if not os.path.exists(d): + os.makedirs(d) + + # If 'current' doesn't exist but we have versions, pick the latest one + if not os.path.exists(self.docs_dir) or not os.listdir(self.docs_dir): + self._update_current_link() - if not os.path.exists(self.meshchatx_docs_dir): - os.makedirs(self.meshchatx_docs_dir) except OSError as e: - # If we still fail (e.g. storage_dir was not provided and public_dir is read-only) - # we log it but don't crash the whole app. Emergency mode can still run. logging.error(f"Failed to create documentation directories: {e}") self.last_error = str(e) @@ -51,6 +55,75 @@ class DocsManager: ): self.populate_meshchatx_docs() + def _update_current_link(self, version=None): + """Updates the 'current' directory to point to the specified version or the latest one.""" + if not os.path.exists(self.versions_dir): + return + + versions = self.get_available_versions() + if not versions: + return + + target_version = version + if not target_version: + # Pick latest version (alphabetically) + target_version = versions[-1] + + version_path = os.path.join(self.versions_dir, target_version) + if not os.path.exists(version_path): + return + + # On some systems symlinks might fail or be restricted, so we use a directory copy or move + # but for now let's try to just use the path directly if possible. + # However, meshchat.py uses self.docs_dir for the static route. + + # To make it simple and robust across platforms, we'll clear 'current' and copy the version + if os.path.exists(self.docs_dir): + if os.path.islink(self.docs_dir): + os.unlink(self.docs_dir) + else: + shutil.rmtree(self.docs_dir) + + try: + # Try symlink first as it's efficient + os.symlink(version_path, self.docs_dir) + except (OSError, AttributeError): + # Fallback to copy + shutil.copytree(version_path, self.docs_dir) + + def get_available_versions(self): + if not os.path.exists(self.versions_dir): + return [] + versions = [ + d + for d in os.listdir(self.versions_dir) + if os.path.isdir(os.path.join(self.versions_dir, d)) + ] + return sorted(versions) + + def get_current_version(self): + if not os.path.exists(self.docs_dir): + return None + + if os.path.islink(self.docs_dir): + return os.path.basename(os.readlink(self.docs_dir)) + + # If it's a copy, we might need a metadata file to know which version it is + version_file = os.path.join(self.docs_dir, ".version") + if os.path.exists(version_file): + try: + with open(version_file, "r") as f: + return f.read().strip() + except OSError: + pass + return "unknown" + + def switch_version(self, version): + if version in self.get_available_versions(): + self._update_current_link(version) + return True + return False + def populate_meshchatx_docs(self): """Populates meshchatx-docs from the project's docs folder.""" # Try to find docs folder in several places @@ -134,6 +207,8 @@ class DocsManager: "last_error": self.last_error, "has_docs": self.has_docs(), "has_meshchatx_docs": self.has_meshchatx_docs(), + "versions": self.get_available_versions(), + "current_version": self.get_current_version(), } def has_meshchatx_docs(self): @@ -340,32 +415,36 @@ class DocsManager: return results def has_docs(self): - # Check if index.html exists in the docs folder or if config says so + # Check if index.html exists in the docs folder or if we have any versions if self.config.docs_downloaded.get(): return True - return os.path.exists(os.path.join(self.docs_dir, "index.html")) + return ( + os.path.exists(os.path.join(self.docs_dir, "index.html")) + or len(self.get_available_versions()) > 0 + ) - def update_docs(self): + def update_docs(self, version="latest"): if ( self.download_status == "downloading" or self.download_status == "extracting" ): return False - thread = threading.Thread(target=self._download_task) + thread = threading.Thread(target=self._download_task, args=(version,)) thread.daemon = True thread.start() return True - def _download_task(self): + def _download_task(self, version="latest"): self.download_status = "downloading" self.download_progress = 0 self.last_error = None try: # We use the reticulum_website repository which contains the built HTML docs - url = "https://github.com/markqvist/reticulum_website/archive/refs/heads/main.zip" - zip_path = os.path.join(self.docs_dir, "website.zip") + # Default to git.quad4.io as requested + url = "https://git.quad4.io/Reticulum/reticulum_website/archive/main.zip" + zip_path = os.path.join(self.docs_base_dir, "website.zip") # Download ZIP response = requests.get(url, stream=True, timeout=60) @@ -386,7 +465,13 @@ class DocsManager: # Extract self.download_status = "extracting" - self._extract_docs(zip_path) + # For automatic downloads from git, we'll use a timestamp as version if none provided + if version == "latest": + import time + + version = f"git-{int(time.time())}" + + self._extract_docs(zip_path, version) # Cleanup if os.path.exists(zip_path): @@ -395,50 +480,104 @@ class DocsManager: self.config.docs_downloaded.set(True) self.download_progress = 100 self.download_status = "completed" + + # Switch to the new version + self.switch_version(version) + except Exception as e: self.last_error = str(e) self.download_status = "error" logging.exception(f"Failed to update docs: {e}") - def _extract_docs(self, zip_path): + def upload_zip(self, zip_bytes, version): + self.download_status = "extracting" + self.download_progress = 0 + self.last_error = None + + try: + zip_path = os.path.join(self.docs_base_dir, "uploaded.zip") + with open(zip_path, "wb") as f: + f.write(zip_bytes) + + self._extract_docs(zip_path, version) + + if os.path.exists(zip_path): + os.remove(zip_path) + + self.download_status = "completed" + self.download_progress = 100 + self.switch_version(version) + return True + except Exception as e: + self.last_error = str(e) + self.download_status = "error" + logging.exception(f"Failed to upload docs: {e}") + return False + + def _extract_docs(self, zip_path, version): + # Target dir for this version + version_dir = os.path.join(self.versions_dir, version) + if os.path.exists(version_dir): + shutil.rmtree(version_dir) + os.makedirs(version_dir) + # Temp dir for extraction - temp_extract = os.path.join(self.docs_dir, "temp_extract") + temp_extract = os.path.join(self.docs_base_dir, "temp_extract") if os.path.exists(temp_extract): shutil.rmtree(temp_extract) with zipfile.ZipFile(zip_path, "r") as zip_ref: - # GitHub zips have a root folder like reticulum_website-main/ - # We want the contents of reticulum_website-main/docs/ - root_folder = zip_ref.namelist()[0].split("/")[0] + # Gitea/GitHub zips have a root folder + namelist = zip_ref.namelist() + if not namelist: + raise Exception("Zip file is empty") + + root_folder = namelist[0].split("/")[0] + + # Check if it's the reticulum_website repo (has docs/ folder) docs_prefix = f"{root_folder}/docs/" + has_docs_subfolder = any(m.startswith(docs_prefix) for m in namelist) - members_to_extract = [ - m for m in zip_ref.namelist() if m.startswith(docs_prefix) - ] + if has_docs_subfolder: + members_to_extract = [m for m in namelist if m.startswith(docs_prefix)] + for member in members_to_extract: + zip_ref.extract(member, temp_extract) - for member in members_to_extract: - zip_ref.extract(member, temp_extract) - - src_path = os.path.join(temp_extract, root_folder, "docs") - - # Clear existing docs except for the temp folder - for item in os.listdir(self.docs_dir): - item_path = os.path.join(self.docs_dir, item) - if item != "temp_extract" and item != "website.zip": - if os.path.isdir(item_path): - shutil.rmtree(item_path) - else: - os.remove(item_path) - - # Move files from extracted docs to docs_dir - if os.path.exists(src_path): + src_path = os.path.join(temp_extract, root_folder, "docs") + # Move files from extracted docs to version_dir for item in os.listdir(src_path): s = os.path.join(src_path, item) - d = os.path.join(self.docs_dir, item) + d = os.path.join(version_dir, item) if os.path.isdir(s): shutil.copytree(s, d) else: shutil.copy2(s, d) + else: + # Just extract everything directly to version_dir, but remove root folder if exists + zip_ref.extractall(temp_extract) + src_path = os.path.join(temp_extract, root_folder) + if os.path.exists(src_path) and os.path.isdir(src_path): + for item in os.listdir(src_path): + s = os.path.join(src_path, item) + d = os.path.join(version_dir, item) + if os.path.isdir(s): + shutil.copytree(s, d) + else: + shutil.copy2(s, d) + else: + # Fallback if no root folder + for item in os.listdir(temp_extract): + s = os.path.join(temp_extract, item) + d = os.path.join(version_dir, item) + if os.path.isdir(s): + shutil.copytree(s, d) + else: + shutil.copy2(s, d) + + # Create a metadata file with the version name + with open(os.path.join(version_dir, ".version"), "w") as f: + f.write(version) # Cleanup temp - shutil.rmtree(temp_extract) + if os.path.exists(temp_extract): + shutil.rmtree(temp_extract) diff --git a/meshchatx/src/backend/telephone_manager.py b/meshchatx/src/backend/telephone_manager.py index 9b22c17..ceebab9 100644 --- a/meshchatx/src/backend/telephone_manager.py +++ b/meshchatx/src/backend/telephone_manager.py @@ -1,4 +1,5 @@ import asyncio +import base64 import os import time @@ -61,6 +62,7 @@ class TelephoneManager: self.call_start_time = None self.call_status_at_end = None self.call_is_incoming = False + self.call_was_established = False # Manual mute overrides in case LXST internal muting is buggy self.transmit_muted = False @@ -82,6 +84,8 @@ class TelephoneManager: self.telephone = Telephone(self.identity) # Disable busy tone played on caller side when remote side rejects, or doesn't answer self.telephone.set_busy_tone_time(0) + # Increase connection timeout for slower networks + self.telephone.set_connect_timeout(30) # Set initial profile from config if self.config_manager: @@ -109,12 +113,14 @@ class TelephoneManager: def on_telephone_ringing(self, caller_identity: RNS.Identity): self.call_start_time = time.time() self.call_is_incoming = True + self.call_was_established = False if self.on_ringing_callback: self.on_ringing_callback(caller_identity) def on_telephone_call_established(self, caller_identity: RNS.Identity): # Update start time to when it was actually established for duration calculation self.call_start_time = time.time() + self.call_was_established = True # Recording disabled for now due to stability issues with LXST # if self.config_manager and self.config_manager.call_recording_enabled.get(): @@ -139,9 +145,19 @@ class TelephoneManager: # Disabled for now pass - def announce(self, attached_interface=None): + def announce(self, attached_interface=None, display_name=None): if self.telephone: - self.telephone.announce(attached_interface=attached_interface) + if display_name: + import RNS.vendor.umsgpack as msgpack + + # Pack display name in LXMF-compatible app data format + app_data = msgpack.packb([display_name, None, None]) + self.telephone.destination.announce( + app_data=app_data, attached_interface=attached_interface + ) + self.telephone.last_announce = time.time() + else: + self.telephone.announce(attached_interface=attached_interface) def _update_initiation_status(self, status, target_hash=None): self.initiation_status = status @@ -171,15 +187,36 @@ class TelephoneManager: self._update_initiation_status("Resolving identity...", destination_hash_hex) try: - # Find destination identity - destination_identity = RNS.Identity.recall(destination_hash) - # If identity not found, check if it's a destination hash in our announces - if destination_identity is None and self.db: - announce = self.db.announces.get_announce_by_hash(destination_hash_hex) - if announce: - identity_hash = bytes.fromhex(announce["identity_hash"]) - destination_identity = RNS.Identity.recall(identity_hash) + def resolve_identity(target_hash_hex): + target_hash = bytes.fromhex(target_hash_hex) + # 1. Try RNS recall + ident = RNS.Identity.recall(target_hash) + if ident: + return ident + + # 2. Check DB announces + if self.db: + announce = self.db.announces.get_announce_by_hash(target_hash_hex) + if announce: + # Try recalling identity hash from announce + identity_hash = bytes.fromhex(announce["identity_hash"]) + ident = RNS.Identity.recall(identity_hash) + if ident: + return ident + + # Try reconstructing from public key if recall failed + if announce.get("identity_public_key"): + try: + return RNS.Identity.from_bytes( + base64.b64decode(announce["identity_public_key"]) + ) + except Exception: + pass + return None + + # Find destination identity + destination_identity = resolve_identity(destination_hash_hex) if destination_identity is None: self._update_initiation_status("Discovering path/identity...") @@ -189,20 +226,10 @@ class TelephoneManager: start_wait = time.time() while time.time() - start_wait < timeout_seconds: await asyncio.sleep(0.5) - destination_identity = RNS.Identity.recall(destination_hash) + destination_identity = resolve_identity(destination_hash_hex) if destination_identity: break - if self.db: - announce = self.db.announces.get_announce_by_hash( - destination_hash_hex - ) - if announce: - identity_hash = bytes.fromhex(announce["identity_hash"]) - destination_identity = RNS.Identity.recall(identity_hash) - if destination_identity: - break - if destination_identity is None: self._update_initiation_status(None, None) msg = "Destination identity not found" @@ -212,6 +239,13 @@ class TelephoneManager: self._update_initiation_status("Requesting path...") RNS.Transport.request_path(destination_hash) + # Wait up to 10s for path discovery + path_wait_start = time.time() + while time.time() - path_wait_start < min(timeout_seconds, 10): + if RNS.Transport.has_path(destination_hash): + break + await asyncio.sleep(0.5) + self._update_initiation_status("Dialing...") self.call_start_time = time.time() self.call_is_incoming = False diff --git a/meshchatx/src/backend/voicemail_manager.py b/meshchatx/src/backend/voicemail_manager.py index 47e4f44..591b9d1 100644 --- a/meshchatx/src/backend/voicemail_manager.py +++ b/meshchatx/src/backend/voicemail_manager.py @@ -402,9 +402,6 @@ class VoicemailManager: threading.Thread(target=session_job, daemon=True).start() def start_recording(self, caller_identity): - # Disabled for now - return - telephone = self.telephone_manager.telephone if not telephone or not telephone.active_call: return @@ -454,6 +451,9 @@ class VoicemailManager: # Save to database if long enough if duration >= 1: + filepath = os.path.join(self.recordings_dir, self.recording_filename) + self._fix_recording(filepath) + remote_name = self.get_name_for_identity_hash( self.recording_remote_identity.hash.hex(), ) @@ -491,10 +491,51 @@ class VoicemailManager: RNS.log(f"Error stopping recording: {e}", RNS.LOG_ERROR) self.is_recording = False - def start_greeting_recording(self): - # Disabled for now - return + def _fix_recording(self, filepath): + """Ensures the recording is a valid OGG/Opus file using ffmpeg.""" + if not self.has_ffmpeg or not os.path.exists(filepath): + return + temp_path = filepath + ".fix" + try: + # We assume it might be raw opus packets or a slightly broken ogg + # ffmpeg can often fix this by just re-wrapping it. + # We try to detect if it's already a valid format first. + cmd = [ + self.ffmpeg_path, + "-y", + "-i", + filepath, + "-c:a", + "libopus", + "-b:a", + "16k", + "-ar", + "48000", + "-ac", + "1", + temp_path, + ] + result = subprocess.run( + cmd, capture_output=True, text=True, check=False + ) # noqa: S603 + + if result.returncode == 0 and os.path.exists(temp_path): + os.remove(filepath) + os.rename(temp_path, filepath) + RNS.log(f"Voicemail: Fixed recording format for {filepath}", RNS.LOG_DEBUG) + else: + RNS.log( + f"Voicemail: ffmpeg failed to fix {filepath}: {result.stderr}", + RNS.LOG_WARNING, + ) + except Exception as e: + RNS.log(f"Voicemail: Error fixing recording {filepath}: {e}", RNS.LOG_ERROR) + finally: + if os.path.exists(temp_path): + os.remove(temp_path) + + def start_greeting_recording(self): telephone = self.telephone_manager.telephone if not telephone: return diff --git a/meshchatx/src/frontend/components/App.vue b/meshchatx/src/frontend/components/App.vue index 1eb77ed..b7c7149 100644 --- a/meshchatx/src/frontend/components/App.vue +++ b/meshchatx/src/frontend/components/App.vue @@ -50,7 +50,7 @@ {{ $t("app.custom_fork_by") }} Sudo-Ivan diff --git a/meshchatx/src/frontend/components/call/CallOverlay.vue b/meshchatx/src/frontend/components/call/CallOverlay.vue index 537ef2d..1e07e9b 100644 --- a/meshchatx/src/frontend/components/call/CallOverlay.vue +++ b/meshchatx/src/frontend/components/call/CallOverlay.vue @@ -112,7 +112,7 @@ ? 'text-red-600 dark:text-red-400 animate-pulse' : activeCall.is_voicemail ? 'text-red-600 dark:text-red-400 animate-pulse' - : activeCall.status === 6 + : activeCall && activeCall.status === 6 ? 'text-green-600 dark:text-green-400' : 'text-gray-600 dark:text-zinc-400', ]" @@ -123,17 +123,17 @@ {{ $t("call.recording_voicemail") }} - {{ + {{ $t("call.incoming_call") }} - {{ $t("call.busy") }} - {{ $t("call.rejected") }} - {{ $t("call.calling") }} - {{ $t("call.available") }} - {{ $t("call.ringing") }} - {{ $t("call.connecting") }} - {{ $t("call.connected") }} - {{ $t("call.status") }}: {{ activeCall.status }} + {{ $t("call.busy") }} + {{ $t("call.rejected") }} + {{ $t("call.calling") }} + {{ $t("call.available") }} + {{ $t("call.ringing") }} + {{ $t("call.connecting") }} + {{ $t("call.connected") }} + {{ $t("call.status") }}: {{ activeCall.status }}
    @@ -203,7 +203,7 @@ +
    +
    + Versions +
    +
    + +
    + No versions available +
    +
    +
    + +
    +
    +
    +
    +
    + + +
    @@ -1058,6 +1067,47 @@ generatedPaperMessageUri = null; " /> + + + +
    +
    +
    +

    Raw LXMF Message

    + +
    +
    +
    {{ JSON.stringify(rawMessageData, null, 2) }}
    +
    +
    + +
    +
    +
    +
    + + diff --git a/meshchatx/src/frontend/components/tools/ToolsPage.vue b/meshchatx/src/frontend/components/tools/ToolsPage.vue index e68e4d5..b54b6d7 100644 --- a/meshchatx/src/frontend/components/tools/ToolsPage.vue +++ b/meshchatx/src/frontend/components/tools/ToolsPage.vue @@ -3,7 +3,7 @@ class="flex flex-col flex-1 overflow-hidden min-w-0 bg-gradient-to-br from-slate-50 via-slate-100 to-white dark:from-zinc-950 dark:via-zinc-900 dark:to-zinc-900" >
    -
    +
    {{ $t("tools.utilities") }} @@ -16,184 +16,61 @@
    -
    - -
    - -
    -
    -
    {{ $t("tools.ping.title") }}
    -
    - {{ $t("tools.ping.description") }} -
    -
    - -
    +
    +
    + + +
    +
    - -
    - +
    + +
    + +
    -
    {{ $t("tools.rnprobe.title") }}
    +
    {{ tool.title }}
    - {{ $t("tools.rnprobe.description") }} + {{ tool.description }}
    - -
    - - -
    - -
    -
    -
    {{ $t("tools.rncp.title") }}
    -
    - {{ $t("tools.rncp.description") }} -
    -
    - -
    - - -
    - -
    -
    -
    {{ $t("tools.rnstatus.title") }}
    -
    - {{ $t("tools.rnstatus.description") }} -
    -
    - -
    - - -
    - -
    -
    -
    {{ $t("tools.rnpath.title") }}
    -
    - {{ $t("tools.rnpath.description") }} -
    -
    - -
    - - -
    - -
    -
    -
    {{ $t("tools.translator.title") }}
    -
    - {{ $t("tools.translator.description") }} -
    -
    - -
    - - -
    - -
    -
    -
    {{ $t("tools.forwarder.title") }}
    -
    - {{ $t("tools.forwarder.description") }} -
    -
    - -
    - - -
    - -
    -
    -
    {{ $t("docs.title") }}
    -
    - {{ $t("docs.subtitle") }} -
    -
    - -
    - - -
    - -
    -
    -
    {{ $t("tools.micron_editor.title") }}
    -
    - {{ $t("tools.micron_editor.description") }} -
    -
    - -
    - - -
    - -
    -
    -
    {{ $t("tools.paper_message.title") }}
    -
    - {{ $t("tools.paper_message.description") }} -
    -
    - -
    - - -
    - RNode -
    -
    -
    {{ $t("tools.rnode_flasher.title") }}
    -
    - {{ $t("tools.rnode_flasher.description") }} -
    -
    -
    + + +
    - -
    - -
    -
    -
    Debug Logs
    -
    - View and export internal system logs for troubleshooting. -
    -
    - -
    +
    + +
    {{ $t("common.no_results") }}
    @@ -210,8 +87,148 @@ export default { data() { return { rnodeLogoPath: "/rnode-flasher/reticulum_logo_512.png", + searchQuery: "", + tools: [ + { + name: "ping", + route: { name: "ping" }, + icon: "radar", + iconBg: "tool-card__icon bg-blue-50 text-blue-500 dark:bg-blue-900/30 dark:text-blue-200", + titleKey: "tools.ping.title", + descriptionKey: "tools.ping.description", + }, + { + name: "rnprobe", + route: { name: "rnprobe" }, + icon: "radar", + iconBg: "tool-card__icon bg-purple-50 text-purple-500 dark:bg-purple-900/30 dark:text-purple-200", + titleKey: "tools.rnprobe.title", + descriptionKey: "tools.rnprobe.description", + }, + { + name: "rncp", + route: { name: "rncp" }, + icon: "swap-horizontal", + iconBg: "tool-card__icon bg-green-50 text-green-500 dark:bg-green-900/30 dark:text-green-200", + titleKey: "tools.rncp.title", + descriptionKey: "tools.rncp.description", + }, + { + name: "rnstatus", + route: { name: "rnstatus" }, + icon: "chart-line", + iconBg: "tool-card__icon bg-orange-50 text-orange-500 dark:bg-orange-900/30 dark:text-orange-200", + titleKey: "tools.rnstatus.title", + descriptionKey: "tools.rnstatus.description", + }, + { + name: "rnpath", + route: { name: "rnpath" }, + icon: "route", + iconBg: "tool-card__icon bg-indigo-50 text-indigo-500 dark:bg-indigo-900/30 dark:text-indigo-200", + titleKey: "tools.rnpath.title", + descriptionKey: "tools.rnpath.description", + }, + { + name: "translator", + route: { name: "translator" }, + icon: "translate", + iconBg: "tool-card__icon bg-indigo-50 text-indigo-500 dark:bg-indigo-900/30 dark:text-indigo-200", + titleKey: "tools.translator.title", + descriptionKey: "tools.translator.description", + }, + { + name: "bots", + route: { name: "bots" }, + icon: "robot", + iconBg: "tool-card__icon bg-blue-50 text-blue-500 dark:bg-blue-900/30 dark:text-blue-200", + titleKey: "tools.bots.title", + descriptionKey: "tools.bots.description", + }, + { + name: "forwarder", + route: { name: "forwarder" }, + icon: "email-send-outline", + iconBg: "tool-card__icon bg-rose-50 text-rose-500 dark:bg-rose-900/30 dark:text-rose-200", + titleKey: "tools.forwarder.title", + descriptionKey: "tools.forwarder.description", + }, + { + name: "documentation", + route: { name: "documentation" }, + icon: "book-open-variant", + iconBg: "tool-card__icon bg-cyan-50 text-cyan-500 dark:bg-cyan-900/30 dark:text-cyan-200", + titleKey: "docs.title", + descriptionKey: "docs.subtitle", + }, + { + name: "micron-editor", + route: { name: "micron-editor" }, + icon: "code-tags", + iconBg: "tool-card__icon bg-teal-50 text-teal-500 dark:bg-teal-900/30 dark:text-teal-200", + titleKey: "tools.micron_editor.title", + descriptionKey: "tools.micron_editor.description", + }, + { + name: "paper-message", + route: { name: "paper-message" }, + icon: "qrcode", + iconBg: "tool-card__icon bg-blue-50 text-blue-500 dark:bg-blue-900/30 dark:text-blue-200", + titleKey: "tools.paper_message.title", + descriptionKey: "tools.paper_message.description", + }, + { + name: "rnode-flasher", + route: { name: "rnode-flasher" }, + icon: null, + image: "/rnode-flasher/reticulum_logo_512.png", + imageClass: "w-8 h-8 rounded-full", + imageAlt: "RNode", + iconBg: "tool-card__icon bg-purple-50 text-purple-500 dark:bg-purple-900/30 dark:text-purple-200", + titleKey: "tools.rnode_flasher.title", + descriptionKey: "tools.rnode_flasher.description", + extraAction: { + href: "/rnode-flasher/index.html", + target: "_blank", + icon: "open-in-new", + }, + }, + { + name: "debug-logs", + route: { name: "debug-logs" }, + icon: "console", + iconBg: "tool-card__icon bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400", + titleKey: null, + title: "Debug Logs", + descriptionKey: null, + description: "View and export internal system logs for troubleshooting.", + customClass: "border-dashed border-2", + }, + ], }; }, + computed: { + filteredTools() { + const toolsWithTranslations = this.tools.map((tool) => ({ + ...tool, + title: tool.title || (tool.titleKey ? this.$t(tool.titleKey) : ""), + description: tool.description || (tool.descriptionKey ? this.$t(tool.descriptionKey) : ""), + })); + + if (!this.searchQuery.trim()) { + return toolsWithTranslations; + } + + const query = this.searchQuery.toLowerCase().trim(); + return toolsWithTranslations.filter((tool) => { + return ( + tool.title.toLowerCase().includes(query) || + tool.description.toLowerCase().includes(query) || + tool.name.toLowerCase().includes(query) + ); + }); + }, + }, }; diff --git a/meshchatx/src/frontend/locales/de.json b/meshchatx/src/frontend/locales/de.json index 10eed8a..adee922 100644 --- a/meshchatx/src/frontend/locales/de.json +++ b/meshchatx/src/frontend/locales/de.json @@ -1,4 +1,31 @@ { + "bots": { + "title": "LXMFy-Bots", + "description": "Verwalten Sie automatisierte Bots für Echo, Notizen und Erinnerungen mit LXMFy.", + "bot_framework": "Bot-Framework", + "lxmfy_not_detected": "LXMFy nicht erkannt", + "lxmfy_not_detected_desc": "Um Bots zu verwenden, müssen Sie das LXMFy-Paket installieren:", + "install_via_pip": "Über pip installieren", + "create_new_bot": "Neuen Bot erstellen", + "running_bots": "Laufende Bots", + "no_bots_running": "Derzeit laufen keine Bots.", + "select": "Auswählen", + "start_bot": "Bot starten", + "stop_bot": "Bot stoppen", + "restart_bot": "Bot neu starten", + "saved_bots": "Gespeicherte Bots", + "bot_name": "Bot-Name", + "cancel": "Abbrechen", + "bot_started": "Bot erfolgreich gestartet", + "bot_stopped": "Bot gestoppt", + "failed_to_start": "Bot konnte nicht gestartet werden", + "failed_to_stop": "Bot konnte nicht gestoppt werden", + "delete_bot": "Bot löschen", + "export_identity": "Identität exportieren", + "bot_deleted": "Bot erfolgreich gelöscht", + "failed_to_delete": "Bot konnte nicht gelöscht werden", + "more_bots_coming": "Weitere Bots folgen in Kürze!" + }, "app": { "name": "Reticulum MeshChatX", "sync_messages": "Nachrichten synchronisieren", @@ -183,7 +210,9 @@ "shutdown": "Ausschalten", "acknowledge_reset": "Bestätigen & Zurücksetzen", "confirm": "Bestätigen", - "delete_confirm": "Sind Sie sicher, dass Sie dies löschen möchten? Dies kann nicht rückgängig gemacht werden." + "delete_confirm": "Sind Sie sicher, dass Sie dies löschen möchten? Dies kann nicht rückgängig gemacht werden.", + "search": "Werkzeuge suchen...", + "no_results": "Keine Werkzeuge gefunden" }, "identities": { "title": "Identitäten", @@ -665,6 +694,10 @@ "paper_message": { "title": "Papiernachricht", "description": "Erstellen und lesen Sie LXMF-signierte Papiernachrichten über QR-Codes." + }, + "bots": { + "title": "LXMFy-Bots", + "description": "Verwalten Sie automatisierte Bots für Echo, Notizen und Erinnerungen mit LXMFy." } }, "ping": { diff --git a/meshchatx/src/frontend/locales/en.json b/meshchatx/src/frontend/locales/en.json index 0cf0934..e663b41 100644 --- a/meshchatx/src/frontend/locales/en.json +++ b/meshchatx/src/frontend/locales/en.json @@ -1,4 +1,31 @@ { + "bots": { + "title": "LXMFy Bots", + "description": "Manage automated bots for echo, notes, and reminders using LXMFy.", + "bot_framework": "Bot Framework", + "lxmfy_not_detected": "LXMFy not detected", + "lxmfy_not_detected_desc": "To use bots, you must install the LXMFy package:", + "install_via_pip": "Install via pip", + "create_new_bot": "Create New Bot", + "running_bots": "Running Bots", + "no_bots_running": "No bots are currently running.", + "select": "Select", + "start_bot": "Start Bot", + "stop_bot": "Stop Bot", + "restart_bot": "Restart Bot", + "saved_bots": "Saved Bots", + "bot_name": "Bot Name", + "cancel": "Cancel", + "bot_started": "Bot started successfully", + "bot_stopped": "Bot stopped", + "failed_to_start": "Failed to start bot", + "failed_to_stop": "Failed to stop bot", + "delete_bot": "Delete Bot", + "export_identity": "Export Identity", + "bot_deleted": "Bot deleted successfully", + "failed_to_delete": "Failed to delete bot", + "more_bots_coming": "More bots coming soon!" + }, "app": { "name": "Reticulum MeshChatX", "sync_messages": "Sync Messages", @@ -183,7 +210,9 @@ "shutdown": "Shutdown", "acknowledge_reset": "Acknowledge & Reset", "confirm": "Confirm", - "delete_confirm": "Are you sure you want to delete this? This cannot be undone." + "delete_confirm": "Are you sure you want to delete this? This cannot be undone.", + "search": "Search tools...", + "no_results": "No tools found" }, "identities": { "title": "Identities", @@ -665,6 +694,10 @@ "paper_message": { "title": "Paper Message", "description": "Generate and read LXMF signed paper messages via QR codes." + }, + "bots": { + "title": "LXMFy Bots", + "description": "Manage automated bots for echo, notes, and reminders using LXMFy." } }, "ping": { diff --git a/meshchatx/src/frontend/locales/ru.json b/meshchatx/src/frontend/locales/ru.json index e1db5ae..e63e46b 100644 --- a/meshchatx/src/frontend/locales/ru.json +++ b/meshchatx/src/frontend/locales/ru.json @@ -1,4 +1,31 @@ { + "bots": { + "title": "Боты LXMFy", + "description": "Управление автоматическими ботами для эха, заметок и напоминаний с помощью LXMFy.", + "bot_framework": "Фреймворк ботов", + "lxmfy_not_detected": "LXMFy не обнаружен", + "lxmfy_not_detected_desc": "Для использования ботов необходимо установить пакет LXMFy:", + "install_via_pip": "Установить через pip", + "create_new_bot": "Создать нового бота", + "running_bots": "Запущенные боты", + "no_bots_running": "В данный момент нет запущенных ботов.", + "select": "Выбрать", + "start_bot": "Запустить бота", + "stop_bot": "Остановить бота", + "restart_bot": "Перезапустить бота", + "saved_bots": "Сохраненные боты", + "bot_name": "Имя бота", + "cancel": "Отмена", + "bot_started": "Бот успешно запущен", + "bot_stopped": "Бот остановлен", + "failed_to_start": "Не удалось запустить бота", + "failed_to_stop": "Не удалось остановить бота", + "delete_bot": "Удалить бота", + "export_identity": "Экспорт личности", + "bot_deleted": "Бот успешно удален", + "failed_to_delete": "Не удалось удалить бота", + "more_bots_coming": "Скоро появятся новые боты!" + }, "app": { "name": "Reticulum MeshChatX", "sync_messages": "Синхронизировать сообщения", @@ -183,7 +210,9 @@ "shutdown": "Выключить", "acknowledge_reset": "Подтвердить и сбросить", "confirm": "Подтвердить", - "delete_confirm": "Вы уверены, что хотите удалить это? Это действие нельзя отменить." + "delete_confirm": "Вы уверены, что хотите удалить это? Это действие нельзя отменить.", + "search": "Поиск инструментов...", + "no_results": "Инструменты не найдены" }, "identities": { "title": "Личности", @@ -665,6 +694,10 @@ "paper_message": { "title": "Бумажное сообщение", "description": "Создание и чтение подписанных бумажных сообщений LXMF через QR-коды." + }, + "bots": { + "title": "LXMFy Боты", + "description": "Управление автоматизированными ботами для эха, заметок и напоминаний с помощью LXMFy." } }, "ping": { diff --git a/meshchatx/src/frontend/main.js b/meshchatx/src/frontend/main.js index 37f866f..b4dcf8c 100644 --- a/meshchatx/src/frontend/main.js +++ b/meshchatx/src/frontend/main.js @@ -189,6 +189,11 @@ const router = createRouter({ path: "/translator", component: defineAsyncComponent(() => import("./components/translator/TranslatorPage.vue")), }, + { + name: "bots", + path: "/bots", + component: defineAsyncComponent(() => import("./components/tools/BotsPage.vue")), + }, { name: "forwarder", path: "/forwarder", diff --git a/scripts/generate_locale_template.py b/scripts/generate_locale_template.py index 99e628f..343e875 100644 --- a/scripts/generate_locale_template.py +++ b/scripts/generate_locale_template.py @@ -20,7 +20,7 @@ def main(): sys.exit(1) try: - with open(en_path, "r", encoding="utf-8") as f: + with open(en_path, encoding="utf-8") as f: en_data = json.load(f) template = clear_values(en_data) @@ -29,7 +29,7 @@ def main(): json.dump(template, f, indent=4, ensure_ascii=False) print( - f"Successfully generated {out_path} with all keys from {en_path} (empty values)." + f"Successfully generated {out_path} with all keys from {en_path} (empty values).", ) except Exception as e: print(f"Error generating locale template: {e}") diff --git a/tests/backend/benchmark_db_lite.py b/tests/backend/benchmark_db_lite.py index 6a29a56..2efe682 100644 --- a/tests/backend/benchmark_db_lite.py +++ b/tests/backend/benchmark_db_lite.py @@ -1,9 +1,10 @@ import os +import random +import secrets import shutil import tempfile import time -import random -import secrets + from meshchatx.src.backend.database import Database @@ -68,7 +69,7 @@ def test_db_performance(): convs = db.messages.get_conversations() end_time = time.time() print( - f"get_conversations() returned {len(convs)} conversations in {end_time - start_time:.4f} seconds" + f"get_conversations() returned {len(convs)} conversations in {end_time - start_time:.4f} seconds", ) # Test get_conversation_messages for a random peer @@ -78,7 +79,7 @@ def test_db_performance(): msgs = db.messages.get_conversation_messages(target_peer, limit=50) end_time = time.time() print( - f"get_conversation_messages() returned {len(msgs)} messages in {end_time - start_time:.4f} seconds" + f"get_conversation_messages() returned {len(msgs)} messages in {end_time - start_time:.4f} seconds", ) # Test unread states for all peers @@ -87,7 +88,7 @@ def test_db_performance(): _ = db.messages.get_conversations_unread_states(peer_hashes) end_time = time.time() print( - f"get_conversations_unread_states() for {len(peer_hashes)} peers took {end_time - start_time:.4f} seconds" + f"get_conversations_unread_states() for {len(peer_hashes)} peers took {end_time - start_time:.4f} seconds", ) # Test announces performance diff --git a/tests/backend/benchmarking_utils.py b/tests/backend/benchmarking_utils.py index a39088f..5296a79 100644 --- a/tests/backend/benchmarking_utils.py +++ b/tests/backend/benchmarking_utils.py @@ -1,9 +1,10 @@ -import os -import psutil import gc +import os import time from functools import wraps +import psutil + def get_memory_usage_mb(): """Returns the current process memory usage in MB.""" @@ -81,5 +82,5 @@ class MemoryTracker: self.duration_ms = (self.end_time - self.start_time) * 1000 self.mem_delta = self.end_mem - self.start_mem print( - f"TRACKER [{self.name}]: {self.duration_ms:.2f}ms, {self.mem_delta:.2f}MB" + f"TRACKER [{self.name}]: {self.duration_ms:.2f}ms, {self.mem_delta:.2f}MB", ) diff --git a/tests/backend/conftest.py b/tests/backend/conftest.py index bc52c9a..10c3c1f 100644 --- a/tests/backend/conftest.py +++ b/tests/backend/conftest.py @@ -1,6 +1,7 @@ -import pytest -from unittest.mock import patch import asyncio +from unittest.mock import patch + +import pytest @pytest.fixture(autouse=True) diff --git a/tests/backend/map_benchmarks.py b/tests/backend/map_benchmarks.py index 9947097..2d75c19 100644 --- a/tests/backend/map_benchmarks.py +++ b/tests/backend/map_benchmarks.py @@ -1,13 +1,15 @@ +import gc +import json import os +import random +import secrets import shutil import tempfile import time -import random -import secrets -import psutil -import gc -import json from unittest.mock import MagicMock + +import psutil + from meshchatx.src.backend.database import Database @@ -72,7 +74,9 @@ class MapBenchmarker: ) self.record_benchmark( - f"Telemetry Insertion ({count} entries)", run_telemetry, count + f"Telemetry Insertion ({count} entries)", + run_telemetry, + count, ) def benchmark_telemetry_retrieval(self, count=100): @@ -90,7 +94,9 @@ class MapBenchmarker: self.db.telemetry.get_telemetry_history(dest_hash, limit=100) self.record_benchmark( - f"Telemetry History Retrieval ({count} calls)", run_retrieval, count + f"Telemetry History Retrieval ({count} calls)", + run_retrieval, + count, ) def benchmark_drawing_storage(self, count=500): @@ -112,7 +118,7 @@ class MapBenchmarker: } for i in range(100) ], - } + }, ) def run_drawings(): @@ -125,7 +131,9 @@ class MapBenchmarker: ) self.record_benchmark( - f"Map Drawing Insertion ({count} layers)", run_drawings, count + f"Map Drawing Insertion ({count} layers)", + run_drawings, + count, ) def benchmark_drawing_listing(self, count=100): @@ -154,7 +162,9 @@ class MapBenchmarker: mm.list_mbtiles() self.record_benchmark( - f"MBTiles Listing ({count} calls, 5 files)", run_list, count + f"MBTiles Listing ({count} calls, 5 files)", + run_list, + count, ) @@ -173,7 +183,7 @@ def main(): print("-" * 80) for r in bench.results: print( - f"{r['name']:40} | {r['duration_ms']:8.2f} ms | {r['memory_growth_mb']:8.2f} MB" + f"{r['name']:40} | {r['duration_ms']:8.2f} ms | {r['memory_growth_mb']:8.2f} MB", ) print("=" * 80) diff --git a/tests/backend/memory_benchmarks.py b/tests/backend/memory_benchmarks.py index 1ab3e35..a6a4ee3 100644 --- a/tests/backend/memory_benchmarks.py +++ b/tests/backend/memory_benchmarks.py @@ -1,11 +1,13 @@ +import gc import os +import random +import secrets import shutil import tempfile import time -import random -import secrets + import psutil -import gc + from meshchatx.src.backend.database import Database from meshchatx.src.backend.recovery import CrashRecovery @@ -112,7 +114,9 @@ class PerformanceBenchmarker: recovery.run_diagnosis(file=open(os.devnull, "w")) self.record_benchmark( - "CrashRecovery Diagnosis Overhead (50 runs)", run_recovery_check, 50 + "CrashRecovery Diagnosis Overhead (50 runs)", + run_recovery_check, + 50, ) def benchmark_identity_generation(self, count=20): @@ -123,7 +127,9 @@ class PerformanceBenchmarker: RNS.Identity(create_keys=True) self.record_benchmark( - f"RNS Identity Generation ({count} identities)", run_gen, count + f"RNS Identity Generation ({count} identities)", + run_gen, + count, ) def benchmark_identity_listing(self, count=100): @@ -142,7 +148,9 @@ class PerformanceBenchmarker: manager.list_identities(current_identity_hash=hashes[0]) self.record_benchmark( - f"Identity Listing ({count} runs, 10 identities)", run_list, count + f"Identity Listing ({count} runs, 10 identities)", + run_list, + count, ) @@ -161,7 +169,7 @@ def main(): print("-" * 80) for r in bench.results: print( - f"{r['name']:40} | {r['duration_ms']:8.2f} ms | {r['memory_growth_mb']:8.2f} MB" + f"{r['name']:40} | {r['duration_ms']:8.2f} ms | {r['memory_growth_mb']:8.2f} MB", ) print("=" * 80) diff --git a/tests/backend/run_comprehensive_benchmarks.py b/tests/backend/run_comprehensive_benchmarks.py index 40ee07b..1003bff 100644 --- a/tests/backend/run_comprehensive_benchmarks.py +++ b/tests/backend/run_comprehensive_benchmarks.py @@ -1,18 +1,19 @@ import os -import sys -import time -import shutil -import tempfile import random import secrets +import shutil +import sys +import tempfile +import time # Ensure we can import meshchatx sys.path.append(os.getcwd()) import json + from meshchatx.src.backend.database import Database -from meshchatx.src.backend.identity_manager import IdentityManager from meshchatx.src.backend.database.telephone import TelephoneDAO +from meshchatx.src.backend.identity_manager import IdentityManager from tests.backend.benchmarking_utils import ( benchmark, get_memory_usage_mb, @@ -76,7 +77,7 @@ class BackendBenchmarker: "delivery_attempts": 1, "title": f"Extreme Msg {b + i}", "content": secrets.token_bytes( - 1024 + 1024, ).hex(), # 2KB hex string "fields": json.dumps({"test": "data" * 10}), "timestamp": time.time() - (total_messages - (b + i)), @@ -87,13 +88,15 @@ class BackendBenchmarker: } self.db.messages.upsert_lxmf_message(msg) print( - f" Progress: {b + batch_size}/{total_messages} messages inserted..." + f" Progress: {b + batch_size}/{total_messages} messages inserted...", ) @benchmark("EXTREME: Search 100k Messages (Wildcard)", iterations=5) def run_extreme_search(): return self.db.messages.get_conversation_messages( - peer_hashes[0], limit=100, offset=50000 + peer_hashes[0], + limit=100, + offset=50000, ) _, res_flood = run_extreme_flood() @@ -115,7 +118,7 @@ class BackendBenchmarker: data = { "destination_hash": secrets.token_hex(16), "aspect": random.choice( - ["lxmf.delivery", "lxst.telephony", "group.chat"] + ["lxmf.delivery", "lxst.telephony", "group.chat"], ), "identity_hash": secrets.token_hex(16), "identity_public_key": secrets.token_hex(32), @@ -130,7 +133,9 @@ class BackendBenchmarker: @benchmark("EXTREME: Filter 50k Announces (Complex)", iterations=10) def run_ann_filter(): return self.db.announces.get_filtered_announces( - aspect="lxmf.delivery", limit=100, offset=25000 + aspect="lxmf.delivery", + limit=100, + offset=25000, ) _, res_flood = run_ann_flood() @@ -164,7 +169,8 @@ class BackendBenchmarker: @benchmark("Database Initialization", iterations=5) def run(): tmp_db_path = os.path.join( - self.temp_dir, f"init_test_{random.randint(0, 1000)}.db" + self.temp_dir, + f"init_test_{random.randint(0, 1000)}.db", ) db = Database(tmp_db_path) db.initialize() @@ -210,7 +216,9 @@ class BackendBenchmarker: @benchmark("Get Messages for Conversation (offset 500)", iterations=20) def get_messages(): return self.db.messages.get_conversation_messages( - peer_hashes[0], limit=50, offset=500 + peer_hashes[0], + limit=50, + offset=500, ) _, res = upsert_batch() @@ -295,7 +303,7 @@ class BackendBenchmarker: print(f"{'-' * 40}-|-{'-' * 10}-|-{'-' * 10}") for r in self.results: print( - f"{r.name:40} | {r.duration_ms:8.2f} ms | {r.memory_delta_mb:8.2f} MB" + f"{r.name:40} | {r.duration_ms:8.2f} ms | {r.memory_delta_mb:8.2f} MB", ) print(f"{'=' * 59}") print(f"Final Memory Usage: {get_memory_usage_mb():.2f} MB") @@ -306,7 +314,9 @@ if __name__ == "__main__": parser = argparse.ArgumentParser(description="MeshChatX Backend Benchmarker") parser.add_argument( - "--extreme", action="store_true", help="Run extreme stress tests" + "--extreme", + action="store_true", + help="Run extreme stress tests", ) args = parser.parse_args() diff --git a/tests/backend/test_announce_dao_extended.py b/tests/backend/test_announce_dao_extended.py index 522fb8a..b3d9aff 100644 --- a/tests/backend/test_announce_dao_extended.py +++ b/tests/backend/test_announce_dao_extended.py @@ -1,9 +1,11 @@ import os import tempfile + import pytest + +from meshchatx.src.backend.database.announces import AnnounceDAO from meshchatx.src.backend.database.provider import DatabaseProvider from meshchatx.src.backend.database.schema import DatabaseSchema -from meshchatx.src.backend.database.announces import AnnounceDAO @pytest.fixture @@ -37,7 +39,7 @@ def test_get_filtered_announces_identity_hash(announce_dao): "rssi": -50, "snr": 10, "quality": 1.0, - } + }, ) announce_dao.upsert_announce( { @@ -49,7 +51,7 @@ def test_get_filtered_announces_identity_hash(announce_dao): "rssi": -50, "snr": 10, "quality": 1.0, - } + }, ) announce_dao.upsert_announce( { @@ -61,7 +63,7 @@ def test_get_filtered_announces_identity_hash(announce_dao): "rssi": -50, "snr": 10, "quality": 1.0, - } + }, ) # Test filtering by identity_hash @@ -71,7 +73,8 @@ def test_get_filtered_announces_identity_hash(announce_dao): # Test filtering by identity_hash and aspect results = announce_dao.get_filtered_announces( - identity_hash="ident1", aspect="lxmf.propagation" + identity_hash="ident1", + aspect="lxmf.propagation", ) assert len(results) == 1 assert results[0]["destination_hash"] == "dest1" @@ -89,6 +92,7 @@ def test_get_filtered_announces_robustness(announce_dao): # Test with multiple filters that yield no results results = announce_dao.get_filtered_announces( - identity_hash="ident1", aspect="non_existent_aspect" + identity_hash="ident1", + aspect="non_existent_aspect", ) assert len(results) == 0 diff --git a/tests/backend/test_app_endpoints.py b/tests/backend/test_app_endpoints.py index f2172cd..823d78e 100644 --- a/tests/backend/test_app_endpoints.py +++ b/tests/backend/test_app_endpoints.py @@ -1,11 +1,13 @@ +import asyncio +import json import shutil import tempfile -import pytest -import json from unittest.mock import MagicMock, patch -from meshchatx.meshchat import ReticulumMeshChat + +import pytest import RNS -import asyncio + +from meshchatx.meshchat import ReticulumMeshChat @pytest.fixture diff --git a/tests/backend/test_app_status_tracking.py b/tests/backend/test_app_status_tracking.py index 1d3b829..4235579 100644 --- a/tests/backend/test_app_status_tracking.py +++ b/tests/backend/test_app_status_tracking.py @@ -1,10 +1,12 @@ import shutil import tempfile -import pytest from unittest.mock import MagicMock, patch -from meshchatx.meshchat import ReticulumMeshChat + +import pytest import RNS +from meshchatx.meshchat import ReticulumMeshChat + @pytest.fixture def temp_dir(): @@ -36,43 +38,43 @@ async def test_app_status_endpoints(mock_rns_minimal, temp_dir): with ExitStack() as stack: # Patch all dependencies stack.enter_context( - patch("meshchatx.src.backend.identity_context.MessageHandler") + patch("meshchatx.src.backend.identity_context.MessageHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.AnnounceManager") + patch("meshchatx.src.backend.identity_context.AnnounceManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.ArchiverManager") + patch("meshchatx.src.backend.identity_context.ArchiverManager"), ) stack.enter_context(patch("meshchatx.src.backend.identity_context.MapManager")) stack.enter_context(patch("meshchatx.src.backend.identity_context.DocsManager")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.NomadNetworkManager") + patch("meshchatx.src.backend.identity_context.NomadNetworkManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.TelephoneManager") + patch("meshchatx.src.backend.identity_context.TelephoneManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.VoicemailManager") + patch("meshchatx.src.backend.identity_context.VoicemailManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RingtoneManager") + patch("meshchatx.src.backend.identity_context.RingtoneManager"), ) stack.enter_context(patch("meshchatx.src.backend.identity_context.RNCPHandler")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RNStatusHandler") + patch("meshchatx.src.backend.identity_context.RNStatusHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RNProbeHandler") + patch("meshchatx.src.backend.identity_context.RNProbeHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.TranslatorHandler") + patch("meshchatx.src.backend.identity_context.TranslatorHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.CommunityInterfacesManager") + patch("meshchatx.src.backend.identity_context.CommunityInterfacesManager"), ) stack.enter_context( - patch("meshchatx.src.backend.sideband_commands.SidebandCommands") + patch("meshchatx.src.backend.sideband_commands.SidebandCommands"), ) stack.enter_context(patch("meshchatx.meshchat.Telemeter")) stack.enter_context(patch("meshchatx.meshchat.CrashRecovery")) diff --git a/tests/backend/test_backend_integrity.py b/tests/backend/test_backend_integrity.py index 2b5ad63..4b7302b 100644 --- a/tests/backend/test_backend_integrity.py +++ b/tests/backend/test_backend_integrity.py @@ -1,9 +1,9 @@ -import unittest +import hashlib +import json import os import shutil import tempfile -import json -import hashlib +import unittest from pathlib import Path @@ -55,7 +55,7 @@ class TestBackendIntegrity(unittest.TestCase): def test_manifest_generation(self): """Test that the build script logic produces a valid manifest.""" manifest_path = self.generate_manifest() - with open(manifest_path, "r") as f: + with open(manifest_path) as f: manifest = json.load(f) self.assertEqual(len(manifest["files"]), 2) @@ -66,7 +66,7 @@ class TestBackendIntegrity(unittest.TestCase): def test_tampering_detection_logic(self): """Test that modifying a file changes its hash (logic check).""" manifest_path = self.generate_manifest() - with open(manifest_path, "r") as f: + with open(manifest_path) as f: manifest = json.load(f) old_hash = manifest["files"]["ReticulumMeshChatX"] diff --git a/tests/backend/test_blackhole_logic.py b/tests/backend/test_blackhole_logic.py index a9be6ca..569ac90 100644 --- a/tests/backend/test_blackhole_logic.py +++ b/tests/backend/test_blackhole_logic.py @@ -1,11 +1,13 @@ +import json import shutil import tempfile +from unittest.mock import AsyncMock, MagicMock, patch + import pytest -import json -from unittest.mock import MagicMock, patch, AsyncMock -from meshchatx.meshchat import ReticulumMeshChat import RNS +from meshchatx.meshchat import ReticulumMeshChat + @pytest.fixture def temp_dir(): @@ -74,7 +76,7 @@ async def test_banish_identity_with_blackhole(mock_rns_minimal, temp_dir): # Verify DB call app_instance.database.misc.add_blocked_destination.assert_called_with( - target_hash + target_hash, ) # Verify RNS blackhole call @@ -100,7 +102,7 @@ async def test_banish_identity_with_resolution(mock_rns_minimal, temp_dir): # Mock identity resolution app_instance.database.announces.get_announce_by_hash.return_value = { - "identity_hash": ident_hash + "identity_hash": ident_hash, } request = MagicMock() @@ -147,7 +149,7 @@ async def test_banish_identity_disabled_integration(mock_rns_minimal, temp_dir): # DB call should still happen app_instance.database.misc.add_blocked_destination.assert_called_with( - target_hash + target_hash, ) # RNS blackhole call should NOT happen @@ -189,7 +191,7 @@ async def test_lift_banishment(mock_rns_minimal, temp_dir): # Verify DB call app_instance.database.misc.delete_blocked_destination.assert_called_with( - target_hash + target_hash, ) # Verify RNS unblackhole call @@ -213,7 +215,7 @@ async def test_get_blackhole_list(mock_rns_minimal, temp_dir): "source": b"\x02" * 32, "until": 1234567890, "reason": "Spam", - } + }, } request = MagicMock() diff --git a/tests/backend/test_community_interfaces.py b/tests/backend/test_community_interfaces.py index 74eca08..94070d2 100644 --- a/tests/backend/test_community_interfaces.py +++ b/tests/backend/test_community_interfaces.py @@ -1,5 +1,7 @@ -import pytest from unittest.mock import MagicMock, patch + +import pytest + from meshchatx.src.backend.community_interfaces import CommunityInterfacesManager from meshchatx.src.backend.rnstatus_handler import RNStatusHandler @@ -42,7 +44,7 @@ async def test_rnstatus_integration_simulated(): "rxb": 0, "txb": 0, }, - ] + ], } handler = RNStatusHandler(mock_reticulum) diff --git a/tests/backend/test_contacts_custom_image.py b/tests/backend/test_contacts_custom_image.py index 374ad01..429f39f 100644 --- a/tests/backend/test_contacts_custom_image.py +++ b/tests/backend/test_contacts_custom_image.py @@ -1,8 +1,10 @@ import os + import pytest + +from meshchatx.src.backend.database.contacts import ContactsDAO from meshchatx.src.backend.database.provider import DatabaseProvider from meshchatx.src.backend.database.schema import DatabaseSchema -from meshchatx.src.backend.database.contacts import ContactsDAO @pytest.fixture @@ -39,7 +41,8 @@ def test_contacts_with_custom_image(db_provider): # Test updating contact image contacts_dao.update_contact( - contact["id"], custom_image="data:image/png;base64,updateddata" + contact["id"], + custom_image="data:image/png;base64,updateddata", ) contact = contacts_dao.get_contact(contact["id"]) diff --git a/tests/backend/test_crash_recovery.py b/tests/backend/test_crash_recovery.py index f17345d..cab6877 100644 --- a/tests/backend/test_crash_recovery.py +++ b/tests/backend/test_crash_recovery.py @@ -1,10 +1,11 @@ -import unittest +import io import os import shutil -import tempfile -import sys -import io import sqlite3 +import sys +import tempfile +import unittest + from meshchatx.src.backend.recovery.crash_recovery import CrashRecovery diff --git a/tests/backend/test_database_robustness.py b/tests/backend/test_database_robustness.py index 62663ff..dc2a996 100644 --- a/tests/backend/test_database_robustness.py +++ b/tests/backend/test_database_robustness.py @@ -1,7 +1,8 @@ -import unittest import os -import tempfile import shutil +import tempfile +import unittest + from meshchatx.src.backend.database.provider import DatabaseProvider from meshchatx.src.backend.database.schema import DatabaseSchema @@ -42,7 +43,8 @@ class TestDatabaseRobustness(unittest.TestCase): ) """) self.provider.execute( - "INSERT INTO config (key, value) VALUES (?, ?)", ("database_version", "1") + "INSERT INTO config (key, value) VALUES (?, ?)", + ("database_version", "1"), ) # 3. Attempt initialization. @@ -77,7 +79,7 @@ class TestDatabaseRobustness(unittest.TestCase): # 3. Version should now be set to LATEST row = self.provider.fetchone( - "SELECT value FROM config WHERE key = 'database_version'" + "SELECT value FROM config WHERE key = 'database_version'", ) self.assertEqual(int(row["value"]), self.schema.LATEST_VERSION) diff --git a/tests/backend/test_database_snapshots.py b/tests/backend/test_database_snapshots.py index 1f09c69..49f29ca 100644 --- a/tests/backend/test_database_snapshots.py +++ b/tests/backend/test_database_snapshots.py @@ -3,6 +3,7 @@ import shutil import tempfile import pytest + from meshchatx.src.backend.database import Database @@ -20,7 +21,8 @@ def test_database_snapshot_creation(temp_dir): # Add some data db.execute_sql( - "INSERT INTO config (key, value) VALUES (?, ?)", ("test_key", "test_value") + "INSERT INTO config (key, value) VALUES (?, ?)", + ("test_key", "test_value"), ) # Create snapshot diff --git a/tests/backend/test_debug_logs.py b/tests/backend/test_debug_logs.py index 370ab29..ef7a260 100644 --- a/tests/backend/test_debug_logs.py +++ b/tests/backend/test_debug_logs.py @@ -1,8 +1,10 @@ -import time -import pytest import logging -from meshchatx.src.backend.persistent_log_handler import PersistentLogHandler +import time + +import pytest + from meshchatx.src.backend.database import Database +from meshchatx.src.backend.persistent_log_handler import PersistentLogHandler @pytest.fixture diff --git a/tests/backend/test_docs_manager.py b/tests/backend/test_docs_manager.py index a1fc228..c896ea9 100644 --- a/tests/backend/test_docs_manager.py +++ b/tests/backend/test_docs_manager.py @@ -141,7 +141,7 @@ def create_mock_zip(zip_path, file_list): ) @given( root_folder_name=st.text(min_size=1, max_size=50).filter( - lambda x: "/" not in x and x not in [".", ".."] + lambda x: "/" not in x and x not in [".", ".."], ), docs_file=st.text(min_size=1, max_size=50).filter(lambda x: "/" not in x), ) diff --git a/tests/backend/test_emergency_mode.py b/tests/backend/test_emergency_mode.py index 2258d74..d98538d 100644 --- a/tests/backend/test_emergency_mode.py +++ b/tests/backend/test_emergency_mode.py @@ -5,6 +5,7 @@ from unittest.mock import MagicMock, patch import pytest import RNS + from meshchatx.meshchat import ReticulumMeshChat @@ -39,7 +40,9 @@ def mock_rns(): patch.object(MockIdentityClass, "from_file", return_value=mock_id_instance), patch.object(MockIdentityClass, "recall", return_value=mock_id_instance), patch.object( - MockIdentityClass, "from_bytes", return_value=mock_id_instance + MockIdentityClass, + "from_bytes", + return_value=mock_id_instance, ), ): mock_transport.interfaces = [] @@ -73,7 +76,7 @@ def test_emergency_mode_startup_logic(mock_rns, temp_dir): patch("meshchatx.src.backend.identity_context.DocsManager"), patch("meshchatx.src.backend.identity_context.NomadNetworkManager"), patch( - "meshchatx.src.backend.identity_context.TelephoneManager" + "meshchatx.src.backend.identity_context.TelephoneManager", ) as mock_tel_class, patch("meshchatx.src.backend.identity_context.VoicemailManager"), patch("meshchatx.src.backend.identity_context.RingtoneManager"), @@ -83,10 +86,10 @@ def test_emergency_mode_startup_logic(mock_rns, temp_dir): patch("meshchatx.src.backend.identity_context.TranslatorHandler"), patch("meshchatx.src.backend.identity_context.CommunityInterfacesManager"), patch( - "meshchatx.src.backend.identity_context.IntegrityManager" + "meshchatx.src.backend.identity_context.IntegrityManager", ) as mock_integrity_class, patch( - "meshchatx.src.backend.identity_context.IdentityContext.start_background_threads" + "meshchatx.src.backend.identity_context.IdentityContext.start_background_threads", ), ): # Initialize app in emergency mode @@ -139,7 +142,7 @@ def test_emergency_mode_env_var(mock_rns, temp_dir): patch("meshchatx.src.backend.identity_context.TranslatorHandler"), patch("meshchatx.src.backend.identity_context.CommunityInterfacesManager"), patch( - "meshchatx.src.backend.identity_context.IdentityContext.start_background_threads" + "meshchatx.src.backend.identity_context.IdentityContext.start_background_threads", ), ): # We need to simulate the argparse processing that happens in main() @@ -170,7 +173,7 @@ def test_normal_mode_startup_logic(mock_rns, temp_dir): patch("meshchatx.src.backend.identity_context.DocsManager"), patch("meshchatx.src.backend.identity_context.NomadNetworkManager"), patch( - "meshchatx.src.backend.identity_context.TelephoneManager" + "meshchatx.src.backend.identity_context.TelephoneManager", ) as mock_tel_class, patch("meshchatx.src.backend.identity_context.VoicemailManager"), patch("meshchatx.src.backend.identity_context.RingtoneManager"), @@ -180,10 +183,10 @@ def test_normal_mode_startup_logic(mock_rns, temp_dir): patch("meshchatx.src.backend.identity_context.TranslatorHandler"), patch("meshchatx.src.backend.identity_context.CommunityInterfacesManager"), patch( - "meshchatx.src.backend.identity_context.IntegrityManager" + "meshchatx.src.backend.identity_context.IntegrityManager", ) as mock_integrity_class, patch( - "meshchatx.src.backend.identity_context.IdentityContext.start_background_threads" + "meshchatx.src.backend.identity_context.IdentityContext.start_background_threads", ), ): # Configure mocks BEFORE instantiating app diff --git a/tests/backend/test_fuzzing.py b/tests/backend/test_fuzzing.py index 24950ec..708d803 100644 --- a/tests/backend/test_fuzzing.py +++ b/tests/backend/test_fuzzing.py @@ -12,6 +12,11 @@ from hypothesis import strategies as st from meshchatx.meshchat import ReticulumMeshChat from meshchatx.src.backend.interface_config_parser import InterfaceConfigParser +from meshchatx.src.backend.lxmf_message_fields import ( + LxmfAudioField, + LxmfFileAttachment, + LxmfImageField, +) from meshchatx.src.backend.meshchat_utils import ( parse_lxmf_display_name, parse_nomadnetwork_node_display_name, @@ -20,11 +25,6 @@ from meshchatx.src.backend.nomadnet_utils import ( convert_nomadnet_field_data_to_map, convert_nomadnet_string_data_to_map, ) -from meshchatx.src.backend.lxmf_message_fields import ( - LxmfAudioField, - LxmfFileAttachment, - LxmfImageField, -) from meshchatx.src.backend.telemetry_utils import Telemeter @@ -122,39 +122,39 @@ def mock_app(temp_dir): # Mock database and other managers to avoid heavy initialization stack.enter_context(patch("meshchatx.src.backend.identity_context.Database")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.ConfigManager") + patch("meshchatx.src.backend.identity_context.ConfigManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.MessageHandler") + patch("meshchatx.src.backend.identity_context.MessageHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.AnnounceManager") + patch("meshchatx.src.backend.identity_context.AnnounceManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.ArchiverManager") + patch("meshchatx.src.backend.identity_context.ArchiverManager"), ) stack.enter_context(patch("meshchatx.src.backend.identity_context.MapManager")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.TelephoneManager") + patch("meshchatx.src.backend.identity_context.TelephoneManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.VoicemailManager") + patch("meshchatx.src.backend.identity_context.VoicemailManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RingtoneManager") + patch("meshchatx.src.backend.identity_context.RingtoneManager"), ) stack.enter_context(patch("meshchatx.src.backend.identity_context.RNCPHandler")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RNStatusHandler") + patch("meshchatx.src.backend.identity_context.RNStatusHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RNProbeHandler") + patch("meshchatx.src.backend.identity_context.RNProbeHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.TranslatorHandler") + patch("meshchatx.src.backend.identity_context.TranslatorHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.CommunityInterfacesManager") + patch("meshchatx.src.backend.identity_context.CommunityInterfacesManager"), ) mock_async_utils = stack.enter_context(patch("meshchatx.meshchat.AsyncUtils")) stack.enter_context(patch("LXMF.LXMRouter")) @@ -171,7 +171,9 @@ def mock_app(temp_dir): stack.enter_context(patch("threading.Thread")) stack.enter_context( patch.object( - ReticulumMeshChat, "announce_loop", new=MagicMock(return_value=None) + ReticulumMeshChat, + "announce_loop", + new=MagicMock(return_value=None), ), ) stack.enter_context( @@ -183,12 +185,16 @@ def mock_app(temp_dir): ) stack.enter_context( patch.object( - ReticulumMeshChat, "crawler_loop", new=MagicMock(return_value=None) + ReticulumMeshChat, + "crawler_loop", + new=MagicMock(return_value=None), ), ) stack.enter_context( patch.object( - ReticulumMeshChat, "auto_backup_loop", new=MagicMock(return_value=None) + ReticulumMeshChat, + "auto_backup_loop", + new=MagicMock(return_value=None), ), ) @@ -196,13 +202,13 @@ def mock_app(temp_dir): mock_id.get_private_key = MagicMock(return_value=b"test_private_key") stack.enter_context( - patch.object(MockIdentityClass, "from_file", return_value=mock_id) + patch.object(MockIdentityClass, "from_file", return_value=mock_id), ) stack.enter_context( - patch.object(MockIdentityClass, "recall", return_value=mock_id) + patch.object(MockIdentityClass, "recall", return_value=mock_id), ) stack.enter_context( - patch.object(MockIdentityClass, "from_bytes", return_value=mock_id) + patch.object(MockIdentityClass, "from_bytes", return_value=mock_id), ) # Make run_async a no-op that doesn't trigger coroutine warnings diff --git a/tests/backend/test_fuzzing_extended.py b/tests/backend/test_fuzzing_extended.py index 22748d2..1d8850b 100644 --- a/tests/backend/test_fuzzing_extended.py +++ b/tests/backend/test_fuzzing_extended.py @@ -29,39 +29,39 @@ def mock_app(temp_dir): with ExitStack() as stack: stack.enter_context(patch("meshchatx.src.backend.identity_context.Database")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.ConfigManager") + patch("meshchatx.src.backend.identity_context.ConfigManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.MessageHandler") + patch("meshchatx.src.backend.identity_context.MessageHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.AnnounceManager") + patch("meshchatx.src.backend.identity_context.AnnounceManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.ArchiverManager") + patch("meshchatx.src.backend.identity_context.ArchiverManager"), ) stack.enter_context(patch("meshchatx.src.backend.identity_context.MapManager")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.TelephoneManager") + patch("meshchatx.src.backend.identity_context.TelephoneManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.VoicemailManager") + patch("meshchatx.src.backend.identity_context.VoicemailManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RingtoneManager") + patch("meshchatx.src.backend.identity_context.RingtoneManager"), ) stack.enter_context(patch("meshchatx.src.backend.identity_context.RNCPHandler")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RNStatusHandler") + patch("meshchatx.src.backend.identity_context.RNStatusHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RNProbeHandler") + patch("meshchatx.src.backend.identity_context.RNProbeHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.TranslatorHandler") + patch("meshchatx.src.backend.identity_context.TranslatorHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.CommunityInterfacesManager") + patch("meshchatx.src.backend.identity_context.CommunityInterfacesManager"), ) stack.enter_context(patch("meshchatx.meshchat.AsyncUtils")) stack.enter_context(patch("LXMF.LXMRouter")) @@ -76,31 +76,37 @@ def mock_app(temp_dir): stack.enter_context(patch("threading.Thread")) stack.enter_context( patch.object( - ReticulumMeshChat, "announce_loop", new=MagicMock(return_value=None) - ) + ReticulumMeshChat, + "announce_loop", + new=MagicMock(return_value=None), + ), ) stack.enter_context( patch.object( ReticulumMeshChat, "announce_sync_propagation_nodes", new=MagicMock(return_value=None), - ) + ), ) stack.enter_context( patch.object( - ReticulumMeshChat, "crawler_loop", new=MagicMock(return_value=None) - ) + ReticulumMeshChat, + "crawler_loop", + new=MagicMock(return_value=None), + ), ) stack.enter_context( patch.object( - ReticulumMeshChat, "auto_backup_loop", new=MagicMock(return_value=None) - ) + ReticulumMeshChat, + "auto_backup_loop", + new=MagicMock(return_value=None), + ), ) mock_id = MockIdentityClass() mock_id.get_private_key = MagicMock(return_value=b"test_private_key") stack.enter_context( - patch.object(MockIdentityClass, "from_file", return_value=mock_id) + patch.object(MockIdentityClass, "from_file", return_value=mock_id), ) app = ReticulumMeshChat( @@ -136,9 +142,10 @@ def mock_app(temp_dir): data=st.recursive( st.one_of(st.none(), st.booleans(), st.floats(), st.text(), st.integers()), lambda children: st.one_of( - st.lists(children), st.dictionaries(st.text(), children) + st.lists(children), + st.dictionaries(st.text(), children), ), - ) + ), ) @pytest.mark.asyncio async def test_websocket_api_recursive_fuzzing(mock_app, data): @@ -190,7 +197,8 @@ async def test_lxm_uri_parsing_fuzzing(mock_app, uri): # Also test it through the websocket interface if it exists there mock_client = MagicMock() await mock_app.on_websocket_data_received( - mock_client, {"type": "lxm.ingest_uri", "uri": uri} + mock_client, + {"type": "lxm.ingest_uri", "uri": uri}, ) except (KeyError, TypeError, ValueError, AttributeError): pass @@ -232,7 +240,8 @@ def test_lxmf_message_construction_fuzzing(mock_app, content, title, fields): @given( table_name=st.sampled_from(["messages", "announces", "identities", "config"]), data=st.dictionaries( - st.text(), st.one_of(st.text(), st.integers(), st.binary(), st.none()) + st.text(), + st.one_of(st.text(), st.integers(), st.binary(), st.none()), ), ) def test_database_record_fuzzing(mock_app, table_name, data): @@ -266,10 +275,10 @@ def test_database_record_fuzzing(mock_app, table_name, data): "map_default_lat", "map_default_lon", "lxmf_inbound_stamp_cost", - ] + ], ), st.one_of(st.text(), st.integers(), st.booleans(), st.none()), - ) + ), ) @pytest.mark.asyncio async def test_config_update_fuzzing(mock_app, config_updates): @@ -288,7 +297,10 @@ async def test_config_update_fuzzing(mock_app, config_updates): @given(destination_hash=st.text(), content=st.text(), title=st.text()) @pytest.mark.asyncio async def test_lxm_generate_paper_uri_fuzzing( - mock_app, destination_hash, content, title + mock_app, + destination_hash, + content, + title, ): """Fuzz lxm.generate_paper_uri WebSocket handler.""" mock_client = MagicMock() @@ -410,7 +422,10 @@ def test_on_lxmf_delivery_fuzzing(mock_app, content, title): app_data=st.binary(min_size=0, max_size=1000), ) def test_on_lxmf_announce_received_fuzzing( - mock_app, aspect, destination_hash, app_data + mock_app, + aspect, + destination_hash, + app_data, ): """Fuzz the announce received handler.""" try: @@ -457,7 +472,10 @@ def test_telemeter_roundtrip_fuzzing(battery, uptime, load, temperature): try: t = Telemeter( - battery=battery, uptime=uptime, load=load, temperature=temperature + battery=battery, + uptime=uptime, + load=load, + temperature=temperature, ) packed = t.pack() unpacked = Telemeter.from_packed(packed) diff --git a/tests/backend/test_identity_switch.py b/tests/backend/test_identity_switch.py index c5ad7d1..32552f3 100644 --- a/tests/backend/test_identity_switch.py +++ b/tests/backend/test_identity_switch.py @@ -1,8 +1,9 @@ import os import shutil import tempfile -from unittest.mock import AsyncMock, MagicMock, patch from contextlib import ExitStack +from unittest.mock import AsyncMock, MagicMock, patch + import pytest import RNS @@ -64,17 +65,19 @@ def mock_rns(): # Mock class methods on MockIdentityClass mock_id_instance = MockIdentityClass() mock_id_instance.get_private_key = MagicMock( - return_value=b"initial_private_key" + return_value=b"initial_private_key", ) stack.enter_context( - patch.object(MockIdentityClass, "from_file", return_value=mock_id_instance) + patch.object(MockIdentityClass, "from_file", return_value=mock_id_instance), ) stack.enter_context( - patch.object(MockIdentityClass, "recall", return_value=mock_id_instance) + patch.object(MockIdentityClass, "recall", return_value=mock_id_instance), ) stack.enter_context( - patch.object(MockIdentityClass, "from_bytes", return_value=mock_id_instance) + patch.object( + MockIdentityClass, "from_bytes", return_value=mock_id_instance + ), ) # Access specifically the ones we need to configure @@ -118,7 +121,7 @@ async def test_hotswap_identity_success(mock_rns, temp_dir): # Mock methods app.teardown_identity = MagicMock() app.setup_identity = MagicMock( - side_effect=lambda id: setattr(app, "current_context", mock_context) + side_effect=lambda id: setattr(app, "current_context", mock_context), ) app.websocket_broadcast = AsyncMock() @@ -164,7 +167,7 @@ async def test_hotswap_identity_keep_alive(mock_rns, temp_dir): # Mock methods app.teardown_identity = MagicMock() app.setup_identity = MagicMock( - side_effect=lambda id: setattr(app, "current_context", mock_context) + side_effect=lambda id: setattr(app, "current_context", mock_context), ) app.websocket_broadcast = AsyncMock() diff --git a/tests/backend/test_integrity.py b/tests/backend/test_integrity.py index 39eef39..ed53738 100644 --- a/tests/backend/test_integrity.py +++ b/tests/backend/test_integrity.py @@ -1,7 +1,8 @@ -import unittest import shutil import tempfile +import unittest from pathlib import Path + from meshchatx.src.backend.integrity_manager import IntegrityManager diff --git a/tests/backend/test_interface_discovery.py b/tests/backend/test_interface_discovery.py new file mode 100644 index 0000000..ab919a7 --- /dev/null +++ b/tests/backend/test_interface_discovery.py @@ -0,0 +1,201 @@ +import json +import shutil +import tempfile +from unittest.mock import MagicMock, patch + +import pytest +import RNS + +from meshchatx.meshchat import ReticulumMeshChat + + +class ConfigDict(dict): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.write_called = False + + def write(self): + self.write_called = True + return True + + +@pytest.fixture +def temp_dir(): + path = tempfile.mkdtemp() + try: + yield path + finally: + shutil.rmtree(path) + + +def build_identity(): + identity = MagicMock(spec=RNS.Identity) + identity.hash = b"test_hash_32_bytes_long_01234567" + identity.hexhash = identity.hash.hex() + identity.get_private_key.return_value = b"test_private_key" + return identity + + +async def find_route_handler(app_instance, path, method): + for route in app_instance.get_routes(): + if route.path == path and route.method == method: + return route.handler + return None + + +@pytest.mark.asyncio +async def test_reticulum_discovery_get_and_patch(temp_dir): + config = ConfigDict( + { + "reticulum": { + "discover_interfaces": "true", + "interface_discovery_sources": "abc,def", + "required_discovery_value": "16", + "autoconnect_discovered_interfaces": "2", + "network_identity": "/tmp/net_id", + }, + "interfaces": {}, + }, + ) + + with ( + patch("meshchatx.meshchat.generate_ssl_certificate"), + patch("RNS.Reticulum") as mock_rns, + patch("RNS.Transport"), + patch("LXMF.LXMRouter"), + ): + mock_reticulum = mock_rns.return_value + mock_reticulum.config = config + mock_reticulum.configpath = "/tmp/mock_config" + mock_reticulum.is_connected_to_shared_instance = False + mock_reticulum.transport_enabled.return_value = True + + app_instance = ReticulumMeshChat( + identity=build_identity(), + storage_dir=temp_dir, + reticulum_config_dir=temp_dir, + ) + + get_handler = await find_route_handler( + app_instance, + "/api/v1/reticulum/discovery", + "GET", + ) + patch_handler = await find_route_handler( + app_instance, + "/api/v1/reticulum/discovery", + "PATCH", + ) + assert get_handler and patch_handler + + # GET returns current reticulum discovery config + get_response = await get_handler(MagicMock()) + get_data = json.loads(get_response.body) + assert get_data["discovery"]["discover_interfaces"] == "true" + assert get_data["discovery"]["interface_discovery_sources"] == "abc,def" + assert get_data["discovery"]["required_discovery_value"] == "16" + assert get_data["discovery"]["autoconnect_discovered_interfaces"] == "2" + assert get_data["discovery"]["network_identity"] == "/tmp/net_id" + + # PATCH updates and persists + new_config = { + "discover_interfaces": False, + "interface_discovery_sources": "", + "required_discovery_value": 18, + "autoconnect_discovered_interfaces": 5, + "network_identity": "/tmp/other_id", + } + + class PatchRequest: + @staticmethod + async def json(): + return new_config + + patch_response = await patch_handler(PatchRequest()) + patch_data = json.loads(patch_response.body) + assert patch_data["discovery"]["discover_interfaces"] is False + assert patch_data["discovery"]["interface_discovery_sources"] is None + assert patch_data["discovery"]["required_discovery_value"] == 18 + assert patch_data["discovery"]["autoconnect_discovered_interfaces"] == 5 + assert patch_data["discovery"]["network_identity"] == "/tmp/other_id" + assert config["reticulum"]["discover_interfaces"] is False + assert "interface_discovery_sources" not in config["reticulum"] + assert config["reticulum"]["required_discovery_value"] == 18 + assert config["reticulum"]["autoconnect_discovered_interfaces"] == 5 + assert config["reticulum"]["network_identity"] == "/tmp/other_id" + assert config.write_called + + +@pytest.mark.asyncio +async def test_interface_add_includes_discovery_fields(temp_dir): + config = ConfigDict({"reticulum": {}, "interfaces": {}}) + + with ( + patch("meshchatx.meshchat.generate_ssl_certificate"), + patch("RNS.Reticulum") as mock_rns, + patch("RNS.Transport"), + patch("LXMF.LXMRouter"), + ): + mock_reticulum = mock_rns.return_value + mock_reticulum.config = config + mock_reticulum.configpath = "/tmp/mock_config" + mock_reticulum.is_connected_to_shared_instance = False + mock_reticulum.transport_enabled.return_value = True + + app_instance = ReticulumMeshChat( + identity=build_identity(), + storage_dir=temp_dir, + reticulum_config_dir=temp_dir, + ) + + add_handler = await find_route_handler( + app_instance, + "/api/v1/reticulum/interfaces/add", + "POST", + ) + assert add_handler + + payload = { + "allow_overwriting_interface": False, + "name": "TestIface", + "type": "TCPClientInterface", + "target_host": "example.com", + "target_port": "4242", + "discoverable": "yes", + "discovery_name": "Region A", + "announce_interval": 720, + "reachable_on": "/usr/bin/get_ip.sh", + "discovery_stamp_value": 22, + "discovery_encrypt": True, + "publish_ifac": True, + "latitude": 10.1, + "longitude": 20.2, + "height": 30, + "discovery_frequency": 915000000, + "discovery_bandwidth": 125000, + "discovery_modulation": "LoRa", + } + + class AddRequest: + @staticmethod + async def json(): + return payload + + response = await add_handler(AddRequest()) + data = json.loads(response.body) + assert "Interface has been added" in data["message"] + saved = config["interfaces"]["TestIface"] + assert saved["discoverable"] == "yes" + assert saved["discovery_name"] == "Region A" + assert saved["announce_interval"] == 720 + assert saved["reachable_on"] == "/usr/bin/get_ip.sh" + assert saved["discovery_stamp_value"] == 22 + assert saved["discovery_encrypt"] is True + assert saved["publish_ifac"] is True + assert saved["latitude"] == 10.1 + assert saved["longitude"] == 20.2 + assert saved["height"] == 30 + assert saved["discovery_frequency"] == 915000000 + assert saved["discovery_bandwidth"] == 125000 + assert saved["discovery_modulation"] == "LoRa" + assert config.write_called diff --git a/tests/backend/test_lxmf_attachments.py b/tests/backend/test_lxmf_attachments.py index 872a0e8..847eaa6 100644 --- a/tests/backend/test_lxmf_attachments.py +++ b/tests/backend/test_lxmf_attachments.py @@ -1,4 +1,5 @@ import json + from meshchatx.src.backend.meshchat_utils import message_fields_have_attachments @@ -22,7 +23,7 @@ def test_message_fields_have_attachments(): # File attachments - with files assert ( message_fields_have_attachments( - json.dumps({"file_attachments": [{"file_name": "test.txt"}]}) + json.dumps({"file_attachments": [{"file_name": "test.txt"}]}), ) is True ) @@ -36,8 +37,8 @@ def test_message_fields_have_attachments_mixed(): assert ( message_fields_have_attachments( json.dumps( - {"image": "img", "file_attachments": [{"file_name": "test.txt"}]} - ) + {"image": "img", "file_attachments": [{"file_name": "test.txt"}]}, + ), ) is True ) @@ -45,7 +46,7 @@ def test_message_fields_have_attachments_mixed(): # Unrelated fields assert ( message_fields_have_attachments( - json.dumps({"title": "hello", "content": "world"}) + json.dumps({"title": "hello", "content": "world"}), ) is False ) diff --git a/tests/backend/test_lxmf_icons.py b/tests/backend/test_lxmf_icons.py index 4067a69..a783691 100644 --- a/tests/backend/test_lxmf_icons.py +++ b/tests/backend/test_lxmf_icons.py @@ -1,10 +1,11 @@ import shutil import tempfile -from unittest.mock import AsyncMock, MagicMock, patch from contextlib import ExitStack +from unittest.mock import AsyncMock, MagicMock, patch + +import LXMF import pytest import RNS -import LXMF from meshchatx.meshchat import ReticulumMeshChat @@ -80,17 +81,19 @@ def mock_rns(): # Mock class methods on MockIdentityClass mock_id_instance = MockIdentityClass() mock_id_instance.get_private_key = MagicMock( - return_value=b"initial_private_key" + return_value=b"initial_private_key", ) stack.enter_context( - patch.object(MockIdentityClass, "from_file", return_value=mock_id_instance) + patch.object(MockIdentityClass, "from_file", return_value=mock_id_instance), ) stack.enter_context( - patch.object(MockIdentityClass, "recall", return_value=mock_id_instance) + patch.object(MockIdentityClass, "recall", return_value=mock_id_instance), ) stack.enter_context( - patch.object(MockIdentityClass, "from_bytes", return_value=mock_id_instance) + patch.object( + MockIdentityClass, "from_bytes", return_value=mock_id_instance + ), ) # Setup mock LXMessage @@ -249,7 +252,7 @@ async def test_receive_message_updates_icon(mock_rns, temp_dir): "new_icon", b"\xff\xff\xff", # #ffffff b"\x00\x00\x00", # #000000 - ] + ], } # Mock methods diff --git a/tests/backend/test_lxmf_propagation_full.py b/tests/backend/test_lxmf_propagation_full.py index feae74c..4766c25 100644 --- a/tests/backend/test_lxmf_propagation_full.py +++ b/tests/backend/test_lxmf_propagation_full.py @@ -1,11 +1,13 @@ +import json import shutil import tempfile -import pytest -import json from unittest.mock import MagicMock, patch -from meshchatx.meshchat import ReticulumMeshChat -import RNS + import LXMF +import pytest +import RNS + +from meshchatx.meshchat import ReticulumMeshChat # Store original constants PR_IDLE = LXMF.LXMRouter.PR_IDLE @@ -58,7 +60,7 @@ def mock_app(temp_dir): mock_rns_inst.transport_enabled.return_value = False with patch( - "meshchatx.src.backend.meshchat_utils.LXMRouter" + "meshchatx.src.backend.meshchat_utils.LXMRouter", ) as mock_utils_router: mock_utils_router.PR_IDLE = PR_IDLE mock_utils_router.PR_PATH_REQUESTED = PR_PATH_REQUESTED @@ -76,7 +78,9 @@ def mock_app(temp_dir): app.current_context.message_router = mock_router with patch.object( - app, "send_config_to_websocket_clients", return_value=None + app, + "send_config_to_websocket_clients", + return_value=None, ): yield app @@ -87,11 +91,11 @@ async def test_lxmf_propagation_config(mock_app): node_hash_bytes = bytes.fromhex(node_hash_hex) await mock_app.update_config( - {"lxmf_preferred_propagation_node_destination_hash": node_hash_hex} + {"lxmf_preferred_propagation_node_destination_hash": node_hash_hex}, ) mock_app.current_context.message_router.set_outbound_propagation_node.assert_called_with( - node_hash_bytes + node_hash_bytes, ) assert ( mock_app.config.lxmf_preferred_propagation_node_destination_hash.get() @@ -159,7 +163,7 @@ async def test_send_failed_via_prop_node(mock_app): @pytest.mark.asyncio async def test_auto_sync_interval_config(mock_app): await mock_app.update_config( - {"lxmf_preferred_propagation_node_auto_sync_interval_seconds": 3600} + {"lxmf_preferred_propagation_node_auto_sync_interval_seconds": 3600}, ) assert ( mock_app.config.lxmf_preferred_propagation_node_auto_sync_interval_seconds.get() @@ -198,17 +202,17 @@ async def test_user_provided_node_hash(mock_app): # Set this node as preferred await mock_app.update_config( - {"lxmf_preferred_propagation_node_destination_hash": node_hash_hex} + {"lxmf_preferred_propagation_node_destination_hash": node_hash_hex}, ) # Check if the router was updated with the correct bytes mock_app.current_context.message_router.set_outbound_propagation_node.assert_called_with( - bytes.fromhex(node_hash_hex) + bytes.fromhex(node_hash_hex), ) # Trigger a sync request mock_app.current_context.message_router.get_outbound_propagation_node.return_value = bytes.fromhex( - node_hash_hex + node_hash_hex, ) sync_handler = next( r.handler @@ -219,5 +223,5 @@ async def test_user_provided_node_hash(mock_app): # Verify the router was told to sync for our identity mock_app.current_context.message_router.request_messages_from_propagation_node.assert_called_with( - mock_app.current_context.identity + mock_app.current_context.identity, ) diff --git a/tests/backend/test_lxmf_sync.py b/tests/backend/test_lxmf_sync.py index 8fa09eb..d449475 100644 --- a/tests/backend/test_lxmf_sync.py +++ b/tests/backend/test_lxmf_sync.py @@ -1,11 +1,13 @@ +import json import shutil import tempfile -import pytest -import json from unittest.mock import MagicMock, patch -from meshchatx.meshchat import ReticulumMeshChat -import RNS + import LXMF +import pytest +import RNS + +from meshchatx.meshchat import ReticulumMeshChat # Store original constants PR_IDLE = LXMF.LXMRouter.PR_IDLE @@ -48,7 +50,7 @@ def mock_app(temp_dir): mock_rns_inst.transport_enabled.return_value = False with patch( - "meshchatx.src.backend.meshchat_utils.LXMRouter" + "meshchatx.src.backend.meshchat_utils.LXMRouter", ) as mock_utils_router: mock_utils_router.PR_IDLE = PR_IDLE mock_utils_router.PR_COMPLETE = PR_COMPLETE @@ -62,7 +64,9 @@ def mock_app(temp_dir): app.current_context.message_router = mock_router with patch.object( - app, "send_config_to_websocket_clients", return_value=None + app, + "send_config_to_websocket_clients", + return_value=None, ): yield app @@ -117,13 +121,13 @@ async def test_specific_node_hash_validation(mock_app): with patch.object(mock_app, "send_config_to_websocket_clients", return_value=None): # Set the preferred propagation node await mock_app.update_config( - {"lxmf_preferred_propagation_node_destination_hash": node_hash_hex} + {"lxmf_preferred_propagation_node_destination_hash": node_hash_hex}, ) # Verify it was set on the router correctly as 16 bytes expected_bytes = bytes.fromhex(node_hash_hex) mock_app.current_context.message_router.set_outbound_propagation_node.assert_called_with( - expected_bytes + expected_bytes, ) # Trigger sync diff --git a/tests/backend/test_lxmf_utils_extended.py b/tests/backend/test_lxmf_utils_extended.py index 3341eb7..b3e371a 100644 --- a/tests/backend/test_lxmf_utils_extended.py +++ b/tests/backend/test_lxmf_utils_extended.py @@ -3,10 +3,11 @@ import json from unittest.mock import MagicMock import LXMF + from meshchatx.src.backend.lxmf_utils import ( + convert_db_lxmf_message_to_dict, convert_lxmf_message_to_dict, convert_lxmf_state_to_string, - convert_db_lxmf_message_to_dict, ) @@ -129,9 +130,9 @@ def test_convert_db_lxmf_message_to_dict(): { "file_name": "f.txt", "file_bytes": base64.b64encode(b"file").decode(), - } + }, ], - } + }, ), "timestamp": 1234567890, "rssi": -60, diff --git a/tests/backend/test_map_manager_extended.py b/tests/backend/test_map_manager_extended.py index d0ac446..52dbb94 100644 --- a/tests/backend/test_map_manager_extended.py +++ b/tests/backend/test_map_manager_extended.py @@ -1,10 +1,11 @@ import os import shutil -import tempfile import sqlite3 +import tempfile from unittest.mock import MagicMock, patch import pytest + from meshchatx.src.backend.map_manager import MapManager @@ -83,11 +84,12 @@ def test_get_tile(mock_config, temp_dir): conn = sqlite3.connect(db_path) conn.execute( - "CREATE TABLE tiles (zoom_level integer, tile_column integer, tile_row integer, tile_data blob)" + "CREATE TABLE tiles (zoom_level integer, tile_column integer, tile_row integer, tile_data blob)", ) # Zoom 0, Tile 0,0. TMS y for 0/0/0 is (1<<0)-1-0 = 0 conn.execute( - "INSERT INTO tiles VALUES (0, 0, 0, ?)", (sqlite3.Binary(b"tile_data"),) + "INSERT INTO tiles VALUES (0, 0, 0, ?)", + (sqlite3.Binary(b"tile_data"),), ) conn.commit() conn.close() diff --git a/tests/backend/test_markdown_renderer.py b/tests/backend/test_markdown_renderer.py index abf89d9..4f69aae 100644 --- a/tests/backend/test_markdown_renderer.py +++ b/tests/backend/test_markdown_renderer.py @@ -1,4 +1,5 @@ import unittest + from meshchatx.src.backend.markdown_renderer import MarkdownRenderer @@ -24,7 +25,7 @@ class TestMarkdownRenderer(unittest.TestCase): # Check for escaped characters self.assertTrue( "print('hello')" in rendered - or "print('hello')" in rendered + or "print('hello')" in rendered, ) def test_lists(self): diff --git a/tests/backend/test_memory_profiling.py b/tests/backend/test_memory_profiling.py index 3093090..649a0c7 100644 --- a/tests/backend/test_memory_profiling.py +++ b/tests/backend/test_memory_profiling.py @@ -1,8 +1,9 @@ -import unittest import os +import secrets import shutil import tempfile -import secrets +import unittest + from meshchatx.src.backend.database import Database from meshchatx.src.backend.identity_manager import IdentityManager from tests.backend.benchmarking_utils import MemoryTracker @@ -54,7 +55,9 @@ class TestMemoryProfiling(unittest.TestCase): # 10k messages * 512 bytes is ~5MB of raw content. # SQLite should handle this efficiently. self.assertLess( - tracker.mem_delta, 20.0, "Excessive memory growth during DB insertion" + tracker.mem_delta, + 20.0, + "Excessive memory growth during DB insertion", ) def test_identity_manager_memory(self): @@ -70,7 +73,9 @@ class TestMemoryProfiling(unittest.TestCase): self.assertEqual(len(identities), 50) self.assertLess( - tracker.mem_delta, 10.0, "Identity management consumed too much memory" + tracker.mem_delta, + 10.0, + "Identity management consumed too much memory", ) def test_large_message_processing(self): @@ -124,7 +129,9 @@ class TestMemoryProfiling(unittest.TestCase): self.db.announces.upsert_announce(data) self.assertLess( - tracker.mem_delta, 15.0, "Announce updates causing memory bloat" + tracker.mem_delta, + 15.0, + "Announce updates causing memory bloat", ) diff --git a/tests/backend/test_meshchat_utils.py b/tests/backend/test_meshchat_utils.py index c68bc40..11884bc 100644 --- a/tests/backend/test_meshchat_utils.py +++ b/tests/backend/test_meshchat_utils.py @@ -1,8 +1,8 @@ import os import shutil import tempfile -from unittest.mock import MagicMock, patch from contextlib import ExitStack +from unittest.mock import MagicMock, patch import pytest import RNS @@ -31,36 +31,36 @@ def mock_app(temp_dir): with ExitStack() as stack: stack.enter_context(patch("meshchatx.src.backend.identity_context.Database")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.ConfigManager") + patch("meshchatx.src.backend.identity_context.ConfigManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.MessageHandler") + patch("meshchatx.src.backend.identity_context.MessageHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.AnnounceManager") + patch("meshchatx.src.backend.identity_context.AnnounceManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.ArchiverManager") + patch("meshchatx.src.backend.identity_context.ArchiverManager"), ) stack.enter_context(patch("meshchatx.src.backend.identity_context.MapManager")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.TelephoneManager") + patch("meshchatx.src.backend.identity_context.TelephoneManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.VoicemailManager") + patch("meshchatx.src.backend.identity_context.VoicemailManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RingtoneManager") + patch("meshchatx.src.backend.identity_context.RingtoneManager"), ) stack.enter_context(patch("meshchatx.src.backend.identity_context.RNCPHandler")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RNStatusHandler") + patch("meshchatx.src.backend.identity_context.RNStatusHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RNProbeHandler") + patch("meshchatx.src.backend.identity_context.RNProbeHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.TranslatorHandler") + patch("meshchatx.src.backend.identity_context.TranslatorHandler"), ) stack.enter_context(patch("LXMF.LXMRouter")) stack.enter_context(patch("RNS.Identity", MockIdentityClass)) @@ -72,34 +72,34 @@ def mock_app(temp_dir): ReticulumMeshChat, "announce_loop", new=MagicMock(return_value=None), - ) + ), ) stack.enter_context( patch.object( ReticulumMeshChat, "announce_sync_propagation_nodes", new=MagicMock(return_value=None), - ) + ), ) stack.enter_context( patch.object( ReticulumMeshChat, "crawler_loop", new=MagicMock(return_value=None), - ) + ), ) mock_id = MockIdentityClass() mock_id.get_private_key = MagicMock(return_value=b"test_private_key") stack.enter_context( - patch.object(MockIdentityClass, "from_file", return_value=mock_id) + patch.object(MockIdentityClass, "from_file", return_value=mock_id), ) stack.enter_context( - patch.object(MockIdentityClass, "recall", return_value=mock_id) + patch.object(MockIdentityClass, "recall", return_value=mock_id), ) stack.enter_context( - patch.object(MockIdentityClass, "from_bytes", return_value=mock_id) + patch.object(MockIdentityClass, "from_bytes", return_value=mock_id), ) app = ReticulumMeshChat( diff --git a/tests/backend/test_message_handler.py b/tests/backend/test_message_handler.py index 17a0a0f..7b8c538 100644 --- a/tests/backend/test_message_handler.py +++ b/tests/backend/test_message_handler.py @@ -1,5 +1,6 @@ import unittest from unittest.mock import MagicMock + from meshchatx.src.backend.message_handler import MessageHandler diff --git a/tests/backend/test_nomadnet_downloader.py b/tests/backend/test_nomadnet_downloader.py index 5871661..1e58918 100644 --- a/tests/backend/test_nomadnet_downloader.py +++ b/tests/backend/test_nomadnet_downloader.py @@ -1,5 +1,6 @@ import unittest from unittest.mock import MagicMock + from meshchatx.src.backend.nomadnet_downloader import NomadnetDownloader diff --git a/tests/backend/test_notifications.py b/tests/backend/test_notifications.py index e31012f..3b1ba6d 100644 --- a/tests/backend/test_notifications.py +++ b/tests/backend/test_notifications.py @@ -1,7 +1,7 @@ import os import time -from unittest.mock import MagicMock, patch from contextlib import ExitStack +from unittest.mock import MagicMock, patch import pytest import RNS @@ -49,33 +49,33 @@ def mock_app(db, tmp_path): stack.enter_context(patch("RNS.Transport")) stack.enter_context(patch("LXMF.LXMRouter")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.TelephoneManager") + patch("meshchatx.src.backend.identity_context.TelephoneManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.VoicemailManager") + patch("meshchatx.src.backend.identity_context.VoicemailManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RingtoneManager") + patch("meshchatx.src.backend.identity_context.RingtoneManager"), ) stack.enter_context(patch("meshchatx.src.backend.identity_context.RNCPHandler")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RNStatusHandler") + patch("meshchatx.src.backend.identity_context.RNStatusHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RNProbeHandler") + patch("meshchatx.src.backend.identity_context.RNProbeHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.TranslatorHandler") + patch("meshchatx.src.backend.identity_context.TranslatorHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.ArchiverManager") + patch("meshchatx.src.backend.identity_context.ArchiverManager"), ) stack.enter_context(patch("meshchatx.src.backend.identity_context.MapManager")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.MessageHandler") + patch("meshchatx.src.backend.identity_context.MessageHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.AnnounceManager") + patch("meshchatx.src.backend.identity_context.AnnounceManager"), ) stack.enter_context(patch("threading.Thread")) @@ -83,44 +83,52 @@ def mock_app(db, tmp_path): mock_id.get_private_key = MagicMock(return_value=b"test_private_key") stack.enter_context( - patch.object(MockIdentityClass, "from_file", return_value=mock_id) + patch.object(MockIdentityClass, "from_file", return_value=mock_id), ) stack.enter_context( - patch.object(MockIdentityClass, "recall", return_value=mock_id) + patch.object(MockIdentityClass, "recall", return_value=mock_id), ) stack.enter_context( - patch.object(MockIdentityClass, "from_bytes", return_value=mock_id) + patch.object(MockIdentityClass, "from_bytes", return_value=mock_id), ) # Patch background threads and other heavy init stack.enter_context( patch.object( - ReticulumMeshChat, "announce_loop", new=MagicMock(return_value=None) - ) + ReticulumMeshChat, + "announce_loop", + new=MagicMock(return_value=None), + ), ) stack.enter_context( patch.object( ReticulumMeshChat, "announce_sync_propagation_nodes", new=MagicMock(return_value=None), - ) + ), ) stack.enter_context( patch.object( - ReticulumMeshChat, "crawler_loop", new=MagicMock(return_value=None) - ) + ReticulumMeshChat, + "crawler_loop", + new=MagicMock(return_value=None), + ), ) stack.enter_context( patch.object( - ReticulumMeshChat, "auto_backup_loop", new=MagicMock(return_value=None) - ) + ReticulumMeshChat, + "auto_backup_loop", + new=MagicMock(return_value=None), + ), ) # Prevent JSON serialization issues with MagicMocks stack.enter_context( patch.object( - ReticulumMeshChat, "send_config_to_websocket_clients", return_value=None - ) + ReticulumMeshChat, + "send_config_to_websocket_clients", + return_value=None, + ), ) app = ReticulumMeshChat( @@ -262,7 +270,10 @@ async def test_notifications_api(mock_app): # Let's test a spike of notifications for i in range(100): mock_app.database.misc.add_notification( - f"type{i}", f"hash{i}", f"title{i}", f"content{i}" + f"type{i}", + f"hash{i}", + f"title{i}", + f"content{i}", ) notifications = mock_app.database.misc.get_notifications(limit=50) @@ -295,7 +306,10 @@ def test_voicemail_notification_fuzzing(mock_app, remote_hash, remote_name, dura call_was_established=st.booleans(), ) def test_missed_call_notification_fuzzing( - mock_app, remote_hash, status_code, call_was_established + mock_app, + remote_hash, + status_code, + call_was_established, ): """Fuzz missed call notification triggering.""" mock_app.database.misc.provider.execute("DELETE FROM notifications") diff --git a/tests/backend/test_performance_bottlenecks.py b/tests/backend/test_performance_bottlenecks.py index 9655484..89f1081 100644 --- a/tests/backend/test_performance_bottlenecks.py +++ b/tests/backend/test_performance_bottlenecks.py @@ -1,12 +1,13 @@ -import unittest import os +import secrets import shutil import tempfile import time -import secrets +import unittest from unittest.mock import MagicMock -from meshchatx.src.backend.database import Database + from meshchatx.src.backend.announce_manager import AnnounceManager +from meshchatx.src.backend.database import Database class TestPerformanceBottlenecks(unittest.TestCase): @@ -60,7 +61,9 @@ class TestPerformanceBottlenecks(unittest.TestCase): for offset in offsets: start = time.time() msgs = self.db.messages.get_conversation_messages( - peer_hash, limit=limit, offset=offset + peer_hash, + limit=limit, + offset=offset, ) duration = (time.time() - start) * 1000 print(f"Fetch {limit} messages at offset {offset}: {duration:.2f}ms") @@ -103,7 +106,7 @@ class TestPerformanceBottlenecks(unittest.TestCase): duration_total = time.time() - start_total avg_duration = (duration_total / num_announces) * 1000 print( - f"Processed {num_announces} announces in {duration_total:.2f}s (Avg: {avg_duration:.2f}ms/announce)" + f"Processed {num_announces} announces in {duration_total:.2f}s (Avg: {avg_duration:.2f}ms/announce)", ) self.assertLess(avg_duration, 20, "Announce processing is too slow!") @@ -129,7 +132,9 @@ class TestPerformanceBottlenecks(unittest.TestCase): # Benchmark filtered search with pagination start = time.time() results = self.announce_manager.get_filtered_announces( - aspect="lxmf.delivery", limit=50, offset=1000 + aspect="lxmf.delivery", + limit=50, + offset=1000, ) duration = (time.time() - start) * 1000 print(f"Filtered announce pagination (offset 1000): {duration:.2f}ms") @@ -164,7 +169,7 @@ class TestPerformanceBottlenecks(unittest.TestCase): ] print( - f"\nRunning {num_threads} threads inserting {announces_per_thread} announces each..." + f"\nRunning {num_threads} threads inserting {announces_per_thread} announces each...", ) start = time.time() for t in threads: @@ -174,7 +179,7 @@ class TestPerformanceBottlenecks(unittest.TestCase): duration = time.time() - start print( - f"Concurrent insertion took {duration:.2f}s for {num_threads * announces_per_thread} announces" + f"Concurrent insertion took {duration:.2f}s for {num_threads * announces_per_thread} announces", ) self.assertLess(duration, 10.0, "Concurrent announce insertion is too slow!") diff --git a/tests/backend/test_propagation_nodes_robustness.py b/tests/backend/test_propagation_nodes_robustness.py index b34803e..ab0a56c 100644 --- a/tests/backend/test_propagation_nodes_robustness.py +++ b/tests/backend/test_propagation_nodes_robustness.py @@ -1,11 +1,13 @@ +import json import shutil import tempfile -import pytest -import json from unittest.mock import MagicMock, patch -from meshchatx.meshchat import ReticulumMeshChat + +import pytest import RNS +from meshchatx.meshchat import ReticulumMeshChat + @pytest.fixture def temp_dir(): diff --git a/tests/backend/test_rncp_handler_extended.py b/tests/backend/test_rncp_handler_extended.py index 2fb1afe..6405150 100644 --- a/tests/backend/test_rncp_handler_extended.py +++ b/tests/backend/test_rncp_handler_extended.py @@ -5,6 +5,7 @@ from unittest.mock import MagicMock, patch import pytest import RNS + from meshchatx.src.backend.rncp_handler import RNCPHandler @@ -40,7 +41,9 @@ def mock_rns(): patch.object(MockIdentityClass, "from_file", return_value=mock_id_instance), patch.object(MockIdentityClass, "recall", return_value=mock_id_instance), patch.object( - MockIdentityClass, "from_bytes", return_value=mock_id_instance + MockIdentityClass, + "from_bytes", + return_value=mock_id_instance, ), ): mock_dest_instance = MagicMock() @@ -85,7 +88,9 @@ def test_setup_receive_destination(mock_rns, temp_dir): mock_rns["Reticulum"].identitypath = temp_dir _ = handler.setup_receive_destination( - allowed_hashes=["abc123def456"], fetch_allowed=True, fetch_jail=temp_dir + allowed_hashes=["abc123def456"], + fetch_allowed=True, + fetch_jail=temp_dir, ) assert handler.receive_destination is not None diff --git a/tests/backend/test_rnpath_logic.py b/tests/backend/test_rnpath_logic.py index 33e6175..c3ba289 100644 --- a/tests/backend/test_rnpath_logic.py +++ b/tests/backend/test_rnpath_logic.py @@ -1,9 +1,11 @@ -import pytest import json -from unittest.mock import MagicMock, patch, AsyncMock -from meshchatx.meshchat import ReticulumMeshChat +from unittest.mock import AsyncMock, MagicMock, patch + +import pytest import RNS +from meshchatx.meshchat import ReticulumMeshChat + @pytest.fixture def temp_dir(tmp_path): diff --git a/tests/backend/test_rns_lifecycle.py b/tests/backend/test_rns_lifecycle.py index 5232c54..4b9e3c6 100644 --- a/tests/backend/test_rns_lifecycle.py +++ b/tests/backend/test_rns_lifecycle.py @@ -45,7 +45,9 @@ def mock_rns(): new=MagicMock(return_value=None), ), patch.object( - ReticulumMeshChat, "send_config_to_websocket_clients", return_value=None + ReticulumMeshChat, + "send_config_to_websocket_clients", + return_value=None, ), ): # Setup mock instance @@ -57,10 +59,14 @@ def mock_rns(): patch.object(MockIdentityClass, "from_file", return_value=mock_id_instance), patch.object(MockIdentityClass, "recall", return_value=mock_id_instance), patch.object( - MockIdentityClass, "from_bytes", return_value=mock_id_instance + MockIdentityClass, + "from_bytes", + return_value=mock_id_instance, ), patch.object( - MockIdentityClass, "full_hash", return_value=b"full_hash_bytes" + MockIdentityClass, + "full_hash", + return_value=b"full_hash_bytes", ), ): # Setup mock transport @@ -263,7 +269,7 @@ async def test_hotswap_identity(mock_rns, temp_dir): with ( patch("meshchatx.src.backend.identity_context.Database"), patch( - "meshchatx.src.backend.identity_context.ConfigManager" + "meshchatx.src.backend.identity_context.ConfigManager", ) as mock_config_class, patch("meshchatx.src.backend.identity_context.MessageHandler"), patch("meshchatx.src.backend.identity_context.AnnounceManager"), diff --git a/tests/backend/test_rnstatus_blackhole.py b/tests/backend/test_rnstatus_blackhole.py index 2911616..48a6efc 100644 --- a/tests/backend/test_rnstatus_blackhole.py +++ b/tests/backend/test_rnstatus_blackhole.py @@ -1,8 +1,10 @@ -import pytest from unittest.mock import MagicMock, patch -from meshchatx.src.backend.rnstatus_handler import RNStatusHandler + +import pytest import RNS +from meshchatx.src.backend.rnstatus_handler import RNStatusHandler + @pytest.fixture def mock_reticulum_instance(): @@ -50,7 +52,7 @@ def test_blackhole_status_missing_api(mock_reticulum_instance): # But we can patch the RNS object inside rnstatus_handler module. with patch( - "meshchatx.src.backend.rnstatus_handler.RNS.Reticulum" + "meshchatx.src.backend.rnstatus_handler.RNS.Reticulum", ) as mock_rns_class: del mock_rns_class.publish_blackhole_enabled diff --git a/tests/backend/test_security_fuzzing.py b/tests/backend/test_security_fuzzing.py index 9125dc0..b3d4630 100644 --- a/tests/backend/test_security_fuzzing.py +++ b/tests/backend/test_security_fuzzing.py @@ -1,6 +1,6 @@ +import base64 import os import time -import base64 from contextlib import ExitStack from unittest.mock import MagicMock, patch @@ -27,39 +27,39 @@ def mock_app(): # Mock core dependencies that interact with the system/network stack.enter_context(patch("meshchatx.src.backend.identity_context.Database")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.ConfigManager") + patch("meshchatx.src.backend.identity_context.ConfigManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.MessageHandler") + patch("meshchatx.src.backend.identity_context.MessageHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.AnnounceManager") + patch("meshchatx.src.backend.identity_context.AnnounceManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.ArchiverManager") + patch("meshchatx.src.backend.identity_context.ArchiverManager"), ) stack.enter_context(patch("meshchatx.src.backend.identity_context.MapManager")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.TelephoneManager") + patch("meshchatx.src.backend.identity_context.TelephoneManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.VoicemailManager") + patch("meshchatx.src.backend.identity_context.VoicemailManager"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RingtoneManager") + patch("meshchatx.src.backend.identity_context.RingtoneManager"), ) stack.enter_context(patch("meshchatx.src.backend.identity_context.RNCPHandler")) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RNStatusHandler") + patch("meshchatx.src.backend.identity_context.RNStatusHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.RNProbeHandler") + patch("meshchatx.src.backend.identity_context.RNProbeHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.TranslatorHandler") + patch("meshchatx.src.backend.identity_context.TranslatorHandler"), ) stack.enter_context( - patch("meshchatx.src.backend.identity_context.CommunityInterfacesManager") + patch("meshchatx.src.backend.identity_context.CommunityInterfacesManager"), ) mock_async_utils = stack.enter_context(patch("meshchatx.meshchat.AsyncUtils")) @@ -72,36 +72,40 @@ def mock_app(): # Stop background loops stack.enter_context( - patch.object(ReticulumMeshChat, "announce_loop", return_value=None) + patch.object(ReticulumMeshChat, "announce_loop", return_value=None), ) stack.enter_context( patch.object( - ReticulumMeshChat, "announce_sync_propagation_nodes", return_value=None - ) + ReticulumMeshChat, + "announce_sync_propagation_nodes", + return_value=None, + ), ) stack.enter_context( - patch.object(ReticulumMeshChat, "crawler_loop", return_value=None) + patch.object(ReticulumMeshChat, "crawler_loop", return_value=None), ) stack.enter_context( - patch.object(ReticulumMeshChat, "auto_backup_loop", return_value=None) + patch.object(ReticulumMeshChat, "auto_backup_loop", return_value=None), ) stack.enter_context( patch.object( - ReticulumMeshChat, "send_config_to_websocket_clients", return_value=None - ) + ReticulumMeshChat, + "send_config_to_websocket_clients", + return_value=None, + ), ) mock_id = MockIdentityClass() mock_id.get_private_key = MagicMock(return_value=b"test_private_key") stack.enter_context( - patch.object(MockIdentityClass, "from_file", return_value=mock_id) + patch.object(MockIdentityClass, "from_file", return_value=mock_id), ) stack.enter_context( - patch.object(MockIdentityClass, "recall", return_value=mock_id) + patch.object(MockIdentityClass, "recall", return_value=mock_id), ) stack.enter_context( - patch.object(MockIdentityClass, "from_bytes", return_value=mock_id) + patch.object(MockIdentityClass, "from_bytes", return_value=mock_id), ) def mock_run_async(coro): @@ -117,10 +121,10 @@ def mock_app(): return MagicMock() mock_telephone_manager = stack.enter_context( - patch("meshchatx.src.backend.identity_context.TelephoneManager") + patch("meshchatx.src.backend.identity_context.TelephoneManager"), ) mock_telephone_manager.return_value.initiate = MagicMock( - side_effect=mock_initiate + side_effect=mock_initiate, ) app = ReticulumMeshChat( @@ -1015,7 +1019,11 @@ def test_telemetry_unpack_location_fuzzing(mock_app, packed_location): bearing=st.one_of(st.floats(allow_nan=True, allow_infinity=True), st.integers()), accuracy=st.one_of(st.floats(allow_nan=True, allow_infinity=True), st.integers()), last_update=st.one_of( - st.integers(), st.floats(), st.text(), st.binary(), st.none() + st.integers(), + st.floats(), + st.text(), + st.binary(), + st.none(), ), ) def test_telemetry_pack_location_fuzzing( @@ -1052,12 +1060,15 @@ def test_telemetry_pack_location_fuzzing( st.none(), ), data=st.one_of( - st.text(), st.binary(), st.dictionaries(keys=st.text(), values=st.text()) + st.text(), + st.binary(), + st.dictionaries(keys=st.text(), values=st.text()), ), received_from=st.one_of(st.text(), st.binary(), st.none()), physical_link=st.one_of( st.dictionaries( - keys=st.text(), values=st.one_of(st.integers(), st.floats(), st.text()) + keys=st.text(), + values=st.one_of(st.integers(), st.floats(), st.text()), ), st.text(), st.binary(), @@ -1456,7 +1467,9 @@ def test_lxst_audio_frame_handling_fuzzing(mock_app, audio_frame): caller_identity_hash=st.binary(min_size=0, max_size=100), ) def test_lxst_call_state_transitions_fuzzing( - mock_app, call_status, caller_identity_hash + mock_app, + call_status, + caller_identity_hash, ): """Fuzz LXST call state transitions with invalid states.""" try: @@ -1490,7 +1503,7 @@ def test_lxst_call_state_transitions_fuzzing( "2400", "3200", "invalid", - ] + ], ), ) def test_codec2_decode_fuzzing(mock_app, codec2_data, codec_mode): @@ -1577,7 +1590,8 @@ def test_lxst_profile_switching_fuzzing(mock_app, profile_id): @settings(suppress_health_check=[HealthCheck.function_scoped_fixture], deadline=None) @given( destination_hash=st.one_of( - st.binary(min_size=0, max_size=100), st.text(min_size=0, max_size=100) + st.binary(min_size=0, max_size=100), + st.text(min_size=0, max_size=100), ), timeout=st.one_of( st.integers(min_value=-100, max_value=1000), @@ -1612,7 +1626,8 @@ def test_lxst_call_initiation_fuzzing(mock_app, destination_hash, timeout): loop.run_until_complete( mock_app.telephone_manager.initiate( - dest_hash_bytes, timeout_seconds=timeout_int + dest_hash_bytes, + timeout_seconds=timeout_int, ), ) finally: @@ -1716,16 +1731,21 @@ def test_lxmf_message_unpacking_fuzzing(mock_app, lxmf_message_data): pipeline_config=st.dictionaries( keys=st.text(), values=st.one_of( - st.text(), st.binary(), st.integers(), st.floats(), st.booleans(), st.none() + st.text(), + st.binary(), + st.integers(), + st.floats(), + st.booleans(), + st.none(), ), ), ) def test_lxst_pipeline_config_fuzzing(mock_app, pipeline_config): """Fuzz LXST Pipeline configuration.""" - from LXST.Pipeline import Pipeline from LXST.Codecs import Null - from LXST.Sources import Source + from LXST.Pipeline import Pipeline from LXST.Sinks import Sink + from LXST.Sources import Source class DummySource(Source): pass @@ -1748,7 +1768,8 @@ def test_lxst_pipeline_config_fuzzing(mock_app, pipeline_config): @settings(suppress_health_check=[HealthCheck.function_scoped_fixture], deadline=None) @given( sink_data=st.one_of( - st.binary(min_size=0, max_size=10000), st.text(min_size=0, max_size=1000) + st.binary(min_size=0, max_size=10000), + st.text(min_size=0, max_size=1000), ), ) def test_lxst_sink_handling_fuzzing(mock_app, sink_data): @@ -1784,7 +1805,8 @@ def test_telemetry_packing_invariants_regression(): } packed = Telemeter.pack( - time_utc=original_data["time"]["utc"], location=original_data["location"] + time_utc=original_data["time"]["utc"], + location=original_data["location"], ) unpacked = Telemeter.from_packed(packed) diff --git a/tests/backend/test_startup.py b/tests/backend/test_startup.py index e460f1c..a99c625 100644 --- a/tests/backend/test_startup.py +++ b/tests/backend/test_startup.py @@ -34,12 +34,16 @@ def mock_rns(): patch("meshchatx.meshchat.get_file_path", return_value="/tmp/mock_path"), patch.object(ReticulumMeshChat, "announce_loop", return_value=None), patch.object( - ReticulumMeshChat, "announce_sync_propagation_nodes", return_value=None + ReticulumMeshChat, + "announce_sync_propagation_nodes", + return_value=None, ), patch.object(ReticulumMeshChat, "crawler_loop", return_value=None), patch.object(ReticulumMeshChat, "auto_backup_loop", return_value=None), patch.object( - ReticulumMeshChat, "send_config_to_websocket_clients", return_value=None + ReticulumMeshChat, + "send_config_to_websocket_clients", + return_value=None, ), ): # Setup mock instance @@ -51,7 +55,9 @@ def mock_rns(): patch.object(MockIdentityClass, "from_file", return_value=mock_id_instance), patch.object(MockIdentityClass, "recall", return_value=mock_id_instance), patch.object( - MockIdentityClass, "from_bytes", return_value=mock_id_instance + MockIdentityClass, + "from_bytes", + return_value=mock_id_instance, ), ): # Setup mock transport @@ -83,7 +89,7 @@ def test_reticulum_meshchat_init(mock_rns, temp_dir): with ( patch("meshchatx.src.backend.identity_context.Database") as mock_db_class, patch( - "meshchatx.src.backend.identity_context.ConfigManager" + "meshchatx.src.backend.identity_context.ConfigManager", ) as mock_config_class, patch("meshchatx.src.backend.identity_context.MessageHandler"), patch("meshchatx.src.backend.identity_context.AnnounceManager"), @@ -152,7 +158,7 @@ def test_reticulum_meshchat_init_with_auth(mock_rns, temp_dir): with ( patch("meshchatx.src.backend.identity_context.Database"), patch( - "meshchatx.src.backend.identity_context.ConfigManager" + "meshchatx.src.backend.identity_context.ConfigManager", ) as mock_config_class, patch("meshchatx.src.backend.identity_context.MessageHandler"), patch("meshchatx.src.backend.identity_context.AnnounceManager"), diff --git a/tests/backend/test_startup_advanced.py b/tests/backend/test_startup_advanced.py index 9facb93..0e692a2 100644 --- a/tests/backend/test_startup_advanced.py +++ b/tests/backend/test_startup_advanced.py @@ -1,11 +1,12 @@ -import shutil -import tempfile import base64 import secrets -from unittest.mock import MagicMock, patch, mock_open +import shutil +import tempfile +from unittest.mock import MagicMock, mock_open, patch import pytest import RNS + from meshchatx.meshchat import ReticulumMeshChat, main @@ -43,12 +44,16 @@ def mock_rns(): patch("LXMF.LXMRouter"), patch.object(ReticulumMeshChat, "announce_loop", return_value=None), patch.object( - ReticulumMeshChat, "announce_sync_propagation_nodes", return_value=None + ReticulumMeshChat, + "announce_sync_propagation_nodes", + return_value=None, ), patch.object(ReticulumMeshChat, "crawler_loop", return_value=None), patch.object(ReticulumMeshChat, "auto_backup_loop", return_value=None), patch.object( - ReticulumMeshChat, "send_config_to_websocket_clients", return_value=None + ReticulumMeshChat, + "send_config_to_websocket_clients", + return_value=None, ), ): mock_id_instance = MockIdentityClass() @@ -57,7 +62,9 @@ def mock_rns(): patch.object(MockIdentityClass, "from_file", return_value=mock_id_instance), patch.object(MockIdentityClass, "recall", return_value=mock_id_instance), patch.object( - MockIdentityClass, "from_bytes", return_value=mock_id_instance + MockIdentityClass, + "from_bytes", + return_value=mock_id_instance, ), ): yield { @@ -73,7 +80,7 @@ def test_run_https_logic(mock_rns, temp_dir): with ( patch("meshchatx.src.backend.identity_context.Database"), patch( - "meshchatx.src.backend.identity_context.ConfigManager" + "meshchatx.src.backend.identity_context.ConfigManager", ) as mock_config_class, patch("meshchatx.meshchat.generate_ssl_certificate") as mock_gen_cert, patch("ssl.SSLContext") as mock_ssl_context, @@ -97,7 +104,7 @@ def test_run_https_logic(mock_rns, temp_dir): mock_config = mock_config_class.return_value # provide a real-looking secret key mock_config.auth_session_secret.get.return_value = base64.urlsafe_b64encode( - secrets.token_bytes(32) + secrets.token_bytes(32), ).decode() mock_config.display_name.get.return_value = "Test" mock_config.lxmf_propagation_node_stamp_cost.get.return_value = 0 @@ -137,7 +144,7 @@ def test_database_integrity_recovery(mock_rns, temp_dir): with ( patch("meshchatx.src.backend.identity_context.Database") as mock_db_class, patch( - "meshchatx.src.backend.identity_context.ConfigManager" + "meshchatx.src.backend.identity_context.ConfigManager", ) as mock_config_class, patch("meshchatx.src.backend.identity_context.MessageHandler"), patch("meshchatx.src.backend.identity_context.AnnounceManager"), @@ -190,7 +197,7 @@ def test_identity_loading_fallback(mock_rns, temp_dir): with ( patch("meshchatx.src.backend.identity_context.Database"), patch( - "meshchatx.src.backend.identity_context.ConfigManager" + "meshchatx.src.backend.identity_context.ConfigManager", ) as mock_config_class, patch("RNS.Identity") as mock_id_class, patch("os.path.exists", return_value=False), # Pretend files don't exist @@ -210,7 +217,7 @@ def test_identity_loading_fallback(mock_rns, temp_dir): # Mock sys.argv to use default behavior (random generation) with patch("sys.argv", ["meshchat.py", "--storage-dir", temp_dir]): with patch( - "meshchatx.meshchat.ReticulumMeshChat" + "meshchatx.meshchat.ReticulumMeshChat", ): # Mock ReticulumMeshChat to avoid full init with patch("aiohttp.web.run_app"): main() @@ -235,25 +242,25 @@ def test_cli_flags_and_envs(mock_rns, temp_dir): "MESHCHAT_AUTH": "1", "MESHCHAT_STORAGE_DIR": temp_dir, } - with patch.dict("os.environ", env): - with patch("sys.argv", ["meshchat.py"]): - main() + with patch.dict("os.environ", env), patch("sys.argv", ["meshchat.py"]): + main() - # Verify ReticulumMeshChat was called with values from ENV - args, kwargs = mock_app_class.call_args - assert kwargs["auto_recover"] is True - assert kwargs["auth_enabled"] is True + # Verify ReticulumMeshChat was called with values from ENV + args, kwargs = mock_app_class.call_args + assert kwargs["auto_recover"] is True + assert kwargs["auth_enabled"] is True - # Verify run was called with host/port from ENV - mock_app_instance = mock_app_class.return_value - run_args, run_kwargs = mock_app_instance.run.call_args - assert run_args[0] == "1.2.3.4" - assert run_args[1] == 9000 + # Verify run was called with host/port from ENV + mock_app_instance = mock_app_class.return_value + run_args, run_kwargs = mock_app_instance.run.call_args + assert run_args[0] == "1.2.3.4" + assert run_args[1] == 9000 # Test CLI Flags (override Envs) mock_app_class.reset_mock() - with patch.dict("os.environ", env): - with patch( + with ( + patch.dict("os.environ", env), + patch( "sys.argv", [ "meshchat.py", @@ -265,11 +272,12 @@ def test_cli_flags_and_envs(mock_rns, temp_dir): "--storage-dir", temp_dir, ], - ): - main() + ), + ): + main() - mock_app_instance = mock_app_class.return_value - run_args, run_kwargs = mock_app_instance.run.call_args - assert run_args[0] == "5.6.7.8" - assert run_args[1] == 7000 - assert run_kwargs["enable_https"] is False + mock_app_instance = mock_app_class.return_value + run_args, run_kwargs = mock_app_instance.run.call_args + assert run_args[0] == "5.6.7.8" + assert run_args[1] == 7000 + assert run_kwargs["enable_https"] is False diff --git a/tests/backend/test_telephone_recorder.py b/tests/backend/test_telephone_recorder.py index 756a7d8..cfb1b72 100644 --- a/tests/backend/test_telephone_recorder.py +++ b/tests/backend/test_telephone_recorder.py @@ -38,7 +38,9 @@ def temp_storage(tmp_path): def test_telephone_manager_init(mock_identity, mock_config, temp_storage): tm = TelephoneManager( - mock_identity, config_manager=mock_config, storage_dir=temp_storage + mock_identity, + config_manager=mock_config, + storage_dir=temp_storage, ) assert tm.identity == mock_identity assert tm.config_manager == mock_config @@ -48,7 +50,11 @@ def test_telephone_manager_init(mock_identity, mock_config, temp_storage): @patch("meshchatx.src.backend.telephone_manager.Telephone") def test_call_recording_lifecycle( - mock_telephone_class, mock_identity, mock_config, mock_db, temp_storage + mock_telephone_class, + mock_identity, + mock_config, + mock_db, + temp_storage, ): # Setup mocks mock_telephone = mock_telephone_class.return_value @@ -63,7 +69,10 @@ def test_call_recording_lifecycle( mock_telephone.transmit_mixer = MagicMock() tm = TelephoneManager( - mock_identity, config_manager=mock_config, storage_dir=temp_storage, db=mock_db + mock_identity, + config_manager=mock_config, + storage_dir=temp_storage, + db=mock_db, ) tm.get_name_for_identity_hash = MagicMock(return_value="Remote User") tm.init_telephone() @@ -90,7 +99,10 @@ def test_call_recording_lifecycle( def test_call_recording_disabled(mock_identity, mock_config, mock_db, temp_storage): mock_config.call_recording_enabled.get.return_value = False tm = TelephoneManager( - mock_identity, config_manager=mock_config, storage_dir=temp_storage, db=mock_db + mock_identity, + config_manager=mock_config, + storage_dir=temp_storage, + db=mock_db, ) # Mock telephone and active call @@ -105,13 +117,15 @@ def test_call_recording_disabled(mock_identity, mock_config, mock_db, temp_stora def test_audio_profile_persistence(mock_identity, mock_config, temp_storage): with patch( - "meshchatx.src.backend.telephone_manager.Telephone" + "meshchatx.src.backend.telephone_manager.Telephone", ) as mock_telephone_class: mock_telephone = mock_telephone_class.return_value mock_config.telephone_audio_profile_id.get.return_value = 4 tm = TelephoneManager( - mock_identity, config_manager=mock_config, storage_dir=temp_storage + mock_identity, + config_manager=mock_config, + storage_dir=temp_storage, ) tm.init_telephone() @@ -121,7 +135,11 @@ def test_audio_profile_persistence(mock_identity, mock_config, temp_storage): @patch("meshchatx.src.backend.telephone_manager.Telephone") def test_call_recording_saves_after_disconnect( - mock_telephone_class, mock_identity, mock_config, mock_db, temp_storage + mock_telephone_class, + mock_identity, + mock_config, + mock_db, + temp_storage, ): # Setup mocks mock_telephone = mock_telephone_class.return_value @@ -136,7 +154,10 @@ def test_call_recording_saves_after_disconnect( mock_telephone.transmit_mixer = MagicMock() tm = TelephoneManager( - mock_identity, config_manager=mock_config, storage_dir=temp_storage, db=mock_db + mock_identity, + config_manager=mock_config, + storage_dir=temp_storage, + db=mock_db, ) tm.init_telephone() @@ -162,11 +183,16 @@ def test_call_recording_saves_after_disconnect( @patch("meshchatx.src.backend.telephone_manager.Telephone") def test_manual_mute_overrides( - mock_telephone_class, mock_identity, mock_config, temp_storage + mock_telephone_class, + mock_identity, + mock_config, + temp_storage, ): mock_telephone = mock_telephone_class.return_value tm = TelephoneManager( - mock_identity, config_manager=mock_config, storage_dir=temp_storage + mock_identity, + config_manager=mock_config, + storage_dir=temp_storage, ) tm.init_telephone() diff --git a/tests/backend/test_translator_handler.py b/tests/backend/test_translator_handler.py index 57875de..66ba659 100644 --- a/tests/backend/test_translator_handler.py +++ b/tests/backend/test_translator_handler.py @@ -1,5 +1,6 @@ import unittest from unittest.mock import MagicMock, patch + from meshchatx.src.backend.translator_handler import TranslatorHandler diff --git a/tests/backend/test_voicemail_manager_extended.py b/tests/backend/test_voicemail_manager_extended.py index bb2f038..5d0ce62 100644 --- a/tests/backend/test_voicemail_manager_extended.py +++ b/tests/backend/test_voicemail_manager_extended.py @@ -4,6 +4,7 @@ import tempfile from unittest.mock import MagicMock, patch import pytest + from meshchatx.src.backend.voicemail_manager import VoicemailManager diff --git a/tests/backend/test_websocket_interfaces.py b/tests/backend/test_websocket_interfaces.py index cba84ba..2448ace 100644 --- a/tests/backend/test_websocket_interfaces.py +++ b/tests/backend/test_websocket_interfaces.py @@ -1,12 +1,13 @@ +import socket import unittest from unittest.mock import MagicMock, patch -import socket -from meshchatx.src.backend.interfaces.WebsocketServerInterface import ( - WebsocketServerInterface, -) + from meshchatx.src.backend.interfaces.WebsocketClientInterface import ( WebsocketClientInterface, ) +from meshchatx.src.backend.interfaces.WebsocketServerInterface import ( + WebsocketServerInterface, +) class TestWebsocketInterfaces(unittest.TestCase): @@ -43,7 +44,7 @@ class TestWebsocketInterfaces(unittest.TestCase): # We don't want it to actually try connecting in this basic test with patch( - "meshchatx.src.backend.interfaces.WebsocketClientInterface.threading.Thread" + "meshchatx.src.backend.interfaces.WebsocketClientInterface.threading.Thread", ): client = WebsocketClientInterface(self.owner, config) self.assertEqual(client.name, "test_ws_client") diff --git a/tests/frontend/AboutPage.test.js b/tests/frontend/AboutPage.test.js index 96315ab..d444b8d 100644 --- a/tests/frontend/AboutPage.test.js +++ b/tests/frontend/AboutPage.test.js @@ -182,13 +182,13 @@ describe("AboutPage.vue", () => { }); mountAboutPage(); - expect(axiosMock.get).toHaveBeenCalledTimes(4); // info, config, health, snapshots + expect(axiosMock.get).toHaveBeenCalledTimes(5); // info, config, health, snapshots, backups vi.advanceTimersByTime(5000); - expect(axiosMock.get).toHaveBeenCalledTimes(5); + expect(axiosMock.get).toHaveBeenCalledTimes(6); // +1 from updateInterval vi.advanceTimersByTime(5000); - expect(axiosMock.get).toHaveBeenCalledTimes(6); + expect(axiosMock.get).toHaveBeenCalledTimes(7); // +2 from updateInterval }); it("handles vacuum database action", async () => { diff --git a/tests/frontend/AddInterfaceDiscovery.test.js b/tests/frontend/AddInterfaceDiscovery.test.js new file mode 100644 index 0000000..87b26ef --- /dev/null +++ b/tests/frontend/AddInterfaceDiscovery.test.js @@ -0,0 +1,86 @@ +import { mount } from "@vue/test-utils"; +import { describe, it, expect, vi, beforeEach } from "vitest"; +import AddInterfacePage from "../../meshchatx/src/frontend/components/interfaces/AddInterfacePage.vue"; + +// mocks +const mockAxios = { + get: vi.fn(), + post: vi.fn(), +}; +window.axios = mockAxios; + +vi.mock("../../meshchatx/src/frontend/js/DialogUtils", () => ({ + default: { + alert: vi.fn(), + }, +})); + +vi.mock("../../meshchatx/src/frontend/js/ToastUtils", () => ({ + default: { + success: vi.fn(), + error: vi.fn(), + }, +})); + +describe("AddInterfacePage.vue discovery", () => { + beforeEach(() => { + vi.clearAllMocks(); + mockAxios.get.mockResolvedValue({ data: {} }); + mockAxios.post.mockResolvedValue({ data: { message: "ok" } }); + }); + + it("adds discovery fields when interface is discoverable", async () => { + const wrapper = mount(AddInterfacePage, { + global: { + mocks: { + $route: { query: {} }, + $router: { push: vi.fn() }, + $t: (msg) => msg, + }, + stubs: ["RouterLink", "MaterialDesignIcon", "Toggle", "ExpandingSection", "FormLabel", "FormSubLabel"], + }, + }); + + // required interface fields + wrapper.vm.newInterfaceName = "TestIface"; + wrapper.vm.newInterfaceType = "TCPClientInterface"; + wrapper.vm.newInterfaceTargetHost = "example.com"; + wrapper.vm.newInterfaceTargetPort = "4242"; + + // discovery fields + wrapper.vm.discovery.discoverable = true; + wrapper.vm.discovery.discovery_name = "Region A"; + wrapper.vm.discovery.announce_interval = 720; + wrapper.vm.discovery.reachable_on = "/usr/local/bin/ip.sh"; + wrapper.vm.discovery.discovery_stamp_value = 22; + wrapper.vm.discovery.discovery_encrypt = true; + wrapper.vm.discovery.publish_ifac = true; + wrapper.vm.discovery.latitude = 1.23; + wrapper.vm.discovery.longitude = 4.56; + wrapper.vm.discovery.height = 7; + wrapper.vm.discovery.discovery_frequency = 915000000; + wrapper.vm.discovery.discovery_bandwidth = 125000; + wrapper.vm.discovery.discovery_modulation = "LoRa"; + + await wrapper.vm.addInterface(); + + expect(mockAxios.post).toHaveBeenCalledWith( + "/api/v1/reticulum/interfaces/add", + expect.objectContaining({ + discoverable: "yes", + discovery_name: "Region A", + announce_interval: 720, + reachable_on: "/usr/local/bin/ip.sh", + discovery_stamp_value: 22, + discovery_encrypt: true, + publish_ifac: true, + latitude: 1.23, + longitude: 4.56, + height: 7, + discovery_frequency: 915000000, + discovery_bandwidth: 125000, + discovery_modulation: "LoRa", + }) + ); + }); +}); diff --git a/tests/frontend/InterfacesPage.test.js b/tests/frontend/InterfacesPage.test.js index 4a50fdc..b78390b 100644 --- a/tests/frontend/InterfacesPage.test.js +++ b/tests/frontend/InterfacesPage.test.js @@ -7,6 +7,7 @@ import GlobalState from "../../meshchatx/src/frontend/js/GlobalState"; const mockAxios = { get: vi.fn(), post: vi.fn(), + patch: vi.fn(), }; window.axios = mockAxios; @@ -110,4 +111,85 @@ describe("InterfacesPage.vue", () => { expect(wrapper.vm.modifiedInterfaceNames.size).toBe(0); expect(mockAxios.post).toHaveBeenCalledWith("/api/v1/reticulum/reload"); }); + + it("loads and saves discovery config", async () => { + mockAxios.get.mockImplementation((url) => { + if (url === "/api/v1/reticulum/interfaces") { + return Promise.resolve({ data: { interfaces: [] } }); + } + if (url === "/api/v1/app/info") { + return Promise.resolve({ data: { app_info: { is_reticulum_running: true } } }); + } + if (url === "/api/v1/reticulum/discovery") { + return Promise.resolve({ + data: { + discovery: { + discover_interfaces: "true", + interface_discovery_sources: "abc", + required_discovery_value: "16", + autoconnect_discovered_interfaces: "3", + network_identity: "/tmp/netid", + }, + }, + }); + } + return Promise.reject(); + }); + + mockAxios.patch.mockResolvedValue({ + data: { + discovery: { + discover_interfaces: false, + interface_discovery_sources: null, + required_discovery_value: 18, + autoconnect_discovered_interfaces: 5, + network_identity: "/tmp/new", + }, + }, + }); + + const wrapper = mount(InterfacesPage, { + global: { + mocks: { + $route: mockRoute, + $router: mockRouter, + $t: (msg) => msg, + }, + stubs: [ + "RouterLink", + "MaterialDesignIcon", + "IconButton", + "Interface", + "ImportInterfacesModal", + "Toggle", + ], + }, + }); + + await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick(); + + expect(wrapper.vm.discoveryConfig.discover_interfaces).toBe(true); + expect(wrapper.vm.discoveryConfig.interface_discovery_sources).toBe("abc"); + expect(wrapper.vm.discoveryConfig.required_discovery_value).toBe(16); + expect(wrapper.vm.discoveryConfig.autoconnect_discovered_interfaces).toBe(3); + expect(wrapper.vm.discoveryConfig.network_identity).toBe("/tmp/netid"); + + wrapper.vm.discoveryConfig.discover_interfaces = false; + wrapper.vm.discoveryConfig.interface_discovery_sources = ""; + wrapper.vm.discoveryConfig.required_discovery_value = 18; + wrapper.vm.discoveryConfig.autoconnect_discovered_interfaces = 5; + wrapper.vm.discoveryConfig.network_identity = "/tmp/new"; + + await wrapper.vm.saveDiscoveryConfig(); + + expect(mockAxios.patch).toHaveBeenCalledWith("/api/v1/reticulum/discovery", { + discover_interfaces: false, + interface_discovery_sources: null, + required_discovery_value: 18, + autoconnect_discovered_interfaces: 5, + network_identity: "/tmp/new", + }); + expect(wrapper.vm.savingDiscovery).toBe(false); + }); }); diff --git a/tests/frontend/MapDrawing.test.js b/tests/frontend/MapDrawing.test.js index aebdd6b..34f93d6 100644 --- a/tests/frontend/MapDrawing.test.js +++ b/tests/frontend/MapDrawing.test.js @@ -45,6 +45,10 @@ vi.mock("ol/Map", () => ({ forEachFeatureAtPixel: vi.fn(), setTarget: vi.fn(), updateSize: vi.fn(), + getViewport: vi.fn().mockReturnValue({ + addEventListener: vi.fn(), + removeEventListener: vi.fn(), + }), })), })); @@ -63,6 +67,7 @@ vi.mock("ol/source/Vector", () => ({ addFeature: vi.fn(), addFeatures: vi.fn(), getFeatures: vi.fn().mockReturnValue([]), + on: vi.fn(), })), })); vi.mock("ol/proj", () => ({ @@ -75,11 +80,30 @@ vi.mock("ol/control", () => ({ vi.mock("ol/interaction/Draw", () => ({ default: vi.fn().mockImplementation(() => ({ on: vi.fn(), + setActive: vi.fn(), })), })); vi.mock("ol/interaction/Modify", () => ({ default: vi.fn().mockImplementation(() => ({ on: vi.fn(), + setActive: vi.fn(), + })), +})); +vi.mock("ol/interaction/Select", () => ({ + default: vi.fn().mockImplementation(() => ({ + on: vi.fn(), + setActive: vi.fn(), + getFeatures: vi.fn().mockReturnValue({ + getArray: vi.fn().mockReturnValue([]), + clear: vi.fn(), + push: vi.fn(), + }), + })), +})); +vi.mock("ol/interaction/Translate", () => ({ + default: vi.fn().mockImplementation(() => ({ + on: vi.fn(), + setActive: vi.fn(), })), })); vi.mock("ol/interaction/Snap", () => ({ @@ -106,6 +130,29 @@ vi.mock("ol/format/GeoJSON", () => ({ readFeatures: vi.fn().mockReturnValue([]), })), })); +vi.mock("ol/style", () => ({ + Style: vi.fn().mockImplementation(() => ({})), + Text: vi.fn().mockImplementation(() => ({})), + Fill: vi.fn().mockImplementation(() => ({})), + Stroke: vi.fn().mockImplementation(() => ({})), + Circle: vi.fn().mockImplementation(() => ({})), + Icon: vi.fn().mockImplementation(() => ({})), +})); +vi.mock("ol/sphere", () => ({ + getArea: vi.fn(), + getLength: vi.fn(), +})); +vi.mock("ol/geom", () => ({ + LineString: vi.fn(), + Polygon: vi.fn(), + Circle: vi.fn(), +})); +vi.mock("ol/geom/Polygon", () => ({ + fromCircle: vi.fn(), +})); +vi.mock("ol/Observable", () => ({ + unByKey: vi.fn(), +})); describe("MapPage.vue - Drawing and Measurement Tools", () => { let axiosMock; @@ -196,13 +243,18 @@ describe("MapPage.vue - Drawing and Measurement Tools", () => { const wrapper = mountMapPage(); await wrapper.vm.$nextTick(); await new Promise((resolve) => setTimeout(resolve, 50)); // wait for initMap + await wrapper.vm.$nextTick(); + + expect(wrapper.vm.map).toBeDefined(); const pointTool = wrapper.find('button[title="map.tool_point"]'); await pointTool.trigger("click"); + await wrapper.vm.$nextTick(); expect(wrapper.vm.drawType).toBe("Point"); expect(wrapper.vm.draw).not.toBeNull(); await pointTool.trigger("click"); + await wrapper.vm.$nextTick(); expect(wrapper.vm.drawType).toBeNull(); expect(wrapper.vm.draw).toBeNull(); }); @@ -211,13 +263,18 @@ describe("MapPage.vue - Drawing and Measurement Tools", () => { const wrapper = mountMapPage(); await wrapper.vm.$nextTick(); await new Promise((resolve) => setTimeout(resolve, 50)); // wait for initMap + await wrapper.vm.$nextTick(); + + expect(wrapper.vm.map).toBeDefined(); const measureTool = wrapper.find('button[title="map.tool_measure"]'); await measureTool.trigger("click"); + await wrapper.vm.$nextTick(); expect(wrapper.vm.isMeasuring).toBe(true); expect(wrapper.vm.drawType).toBe("LineString"); await measureTool.trigger("click"); + await wrapper.vm.$nextTick(); expect(wrapper.vm.isMeasuring).toBe(false); expect(wrapper.vm.drawType).toBeNull(); }); diff --git a/tests/frontend/MapPage.test.js b/tests/frontend/MapPage.test.js index bcf6ac4..ec4347d 100644 --- a/tests/frontend/MapPage.test.js +++ b/tests/frontend/MapPage.test.js @@ -45,6 +45,10 @@ vi.mock("ol/Map", () => ({ forEachFeatureAtPixel: vi.fn(), setTarget: vi.fn(), updateSize: vi.fn(), + getViewport: vi.fn().mockReturnValue({ + addEventListener: vi.fn(), + removeEventListener: vi.fn(), + }), })), })); @@ -63,6 +67,7 @@ vi.mock("ol/source/Vector", () => ({ addFeature: vi.fn(), addFeatures: vi.fn(), getFeatures: vi.fn().mockReturnValue([]), + on: vi.fn(), })), })); vi.mock("ol/proj", () => ({ @@ -75,11 +80,30 @@ vi.mock("ol/control", () => ({ vi.mock("ol/interaction/Draw", () => ({ default: vi.fn().mockImplementation(() => ({ on: vi.fn(), + setActive: vi.fn(), })), })); vi.mock("ol/interaction/Modify", () => ({ default: vi.fn().mockImplementation(() => ({ on: vi.fn(), + setActive: vi.fn(), + })), +})); +vi.mock("ol/interaction/Select", () => ({ + default: vi.fn().mockImplementation(() => ({ + on: vi.fn(), + setActive: vi.fn(), + getFeatures: vi.fn().mockReturnValue({ + getArray: vi.fn().mockReturnValue([]), + clear: vi.fn(), + push: vi.fn(), + }), + })), +})); +vi.mock("ol/interaction/Translate", () => ({ + default: vi.fn().mockImplementation(() => ({ + on: vi.fn(), + setActive: vi.fn(), })), })); vi.mock("ol/interaction/Snap", () => ({ @@ -106,6 +130,29 @@ vi.mock("ol/format/GeoJSON", () => ({ readFeatures: vi.fn().mockReturnValue([]), })), })); +vi.mock("ol/style", () => ({ + Style: vi.fn().mockImplementation(() => ({})), + Text: vi.fn().mockImplementation(() => ({})), + Fill: vi.fn().mockImplementation(() => ({})), + Stroke: vi.fn().mockImplementation(() => ({})), + Circle: vi.fn().mockImplementation(() => ({})), + Icon: vi.fn().mockImplementation(() => ({})), +})); +vi.mock("ol/sphere", () => ({ + getArea: vi.fn(), + getLength: vi.fn(), +})); +vi.mock("ol/geom", () => ({ + LineString: vi.fn(), + Polygon: vi.fn(), + Circle: vi.fn(), +})); +vi.mock("ol/geom/Polygon", () => ({ + fromCircle: vi.fn(), +})); +vi.mock("ol/Observable", () => ({ + unByKey: vi.fn(), +})); import MapPage from "@/components/map/MapPage.vue"; From e7728696c8d41c454ca3db0193af1736c6c32540 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Mon, 5 Jan 2026 11:47:46 -0600 Subject: [PATCH 171/234] chore(vite): add asset cleanup before build to prevent accumulation of old files --- vite.config.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/vite.config.js b/vite.config.js index 1bde217..4747441 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,7 +1,14 @@ import path from "path"; +import fs from "fs"; import vue from "@vitejs/plugin-vue"; import vuetify from "vite-plugin-vuetify"; +// Purge old assets before build to prevent accumulation +const assetsDir = path.join(__dirname, "meshchatx", "public", "assets"); +if (fs.existsSync(assetsDir)) { + fs.rmSync(assetsDir, { recursive: true, force: true }); +} + export default { plugins: [vue(), vuetify()], From 5b25e3b4c0d24e0d00e15bfcd885c8b7535dc62f Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Mon, 5 Jan 2026 11:47:52 -0600 Subject: [PATCH 172/234] feat(changelog): add new features including Web Audio Bridge, LXMFy for bots, and RNS Discoverable Interfaces --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81197da..5da338b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,9 @@ Season 1 Episode 1 - A MASSIVE REFACTOR * **Protocol Handling:** Register as default handler for `lxmf://` and `rns://` links for seamless cross-app navigation. * **Hardware Acceleration Toggle:** Power-user setting to disable GPU acceleration if flickering or glitches occur. * **Power Management:** Automatically prevents system sleep during active audio calls to maintain RNS path stability. +- **Added Web Audio Bridge** which allows web/electron to hook into LXST backend for passing microphone and audio streams to active telephone calls. +- **Added LXMFy** for running bots. +- **Added RNS Discoverable Interfaces** https://markqvist.github.io/Reticulum/manual/interfaces.html#discoverable-interfaces ### Improvements From a9e881a095a84001139429a0338b0f832f1fc018 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Mon, 5 Jan 2026 11:48:00 -0600 Subject: [PATCH 173/234] chore(dependencies): update hypothesis to version 6.149.0 and add lxmfy package from git repository --- poetry.lock | 28 ++++++++++++++++++++++++---- pyproject.toml | 2 ++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index a85187a..2cc4f6d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1076,14 +1076,14 @@ files = [ [[package]] name = "hypothesis" -version = "6.148.11" +version = "6.149.0" description = "The property-based testing library for Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "hypothesis-6.148.11-py3-none-any.whl", hash = "sha256:397b3fd13d0906cf5ece76f5da340a0fbb07bd18ab61ac41a7982ceb080312f0"}, - {file = "hypothesis-6.148.11.tar.gz", hash = "sha256:4f3c38030d0f0b38c8b7153d6907892e6fcac9ecb0410e627d6af2cea677f92c"}, + {file = "hypothesis-6.149.0-py3-none-any.whl", hash = "sha256:96420e306421741be4eea4f32bfc7a13360d73400b2e886a5d5e3668a2337a05"}, + {file = "hypothesis-6.149.0.tar.gz", hash = "sha256:27afa07824fbb7785369dfae8e2574ec2ae0b1bdce50f3a327dfc069b79b0a44"}, ] [package.dependencies] @@ -1233,6 +1233,26 @@ files = [ [package.dependencies] rns = ">=1.0.1" +[[package]] +name = "lxmfy" +version = "1.3.0" +description = "LXMF bot framework for creating bots for the Reticulum Network" +optional = false +python-versions = ">=3.11" +groups = ["main"] +files = [] +develop = false + +[package.dependencies] +lxmf = ">=0.9.3" +rns = ">=1.1.0" + +[package.source] +type = "git" +url = "https://git.quad4.io/LXMFy/LXMFy.git" +reference = "HEAD" +resolved_reference = "bf5986d1a145420af4beec9b726c8bbc12dce691" + [[package]] name = "lxst" version = "0.4.5" @@ -2254,4 +2274,4 @@ propcache = ">=0.2.1" [metadata] lock-version = "2.1" python-versions = ">=3.11" -content-hash = "4dda950e0586a558174bb05ed43a8d3feaaf2cf6acb056bafcb27e4b80e975f3" +content-hash = "a4edf771858212d7b4a90871b57ef55623e73929c5f1ead40cab10949dc1eadc" diff --git a/pyproject.toml b/pyproject.toml index a95e882..7e36391 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,6 +22,7 @@ classifiers = [ dependencies = [ "aiohttp>=3.13.2", "lxmf>=0.9.3", + "lxmfy @ git+https://git.quad4.io/LXMFy/LXMFy.git", "psutil>=7.1.3", "rns>=1.1.0", "websockets>=15.0.1", @@ -45,6 +46,7 @@ packages = [{include = "meshchatx"}] [tool.poetry.dependencies] python = ">=3.11" +lxmfy = {git = "https://git.quad4.io/LXMFy/LXMFy.git"} [tool.poetry.group.dev.dependencies] cx-freeze = ">=7.0.0" From 144cc53cd902d26ef66705c797a81d12ed40256e Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Mon, 5 Jan 2026 11:48:12 -0600 Subject: [PATCH 174/234] chore(security): lint --- SECURITY.md | 1 - 1 file changed, 1 deletion(-) diff --git a/SECURITY.md b/SECURITY.md index f554392..0221831 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -32,4 +32,3 @@ The project employs continuous security monitoring and testing: - **Pinned Actions**: All CI/CD workflows use pinned actions with full URLs to forked, vetted actions hosted on our Gitea instance (`git.quad4.io`) to prevent supply chain attacks. - **Extensive Testing & Fuzzing**: Comprehensive backend benchmarking suite with high-precision timing, memory delta tracking, and extreme stress modes to ensure stability and prevent resource exhaustion. - **Linting & Code Quality**: Strict linting rules and static analysis are enforced on every push. - From 30cab64101e22962af46ffb328f409cf42203302 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Mon, 5 Jan 2026 12:01:59 -0600 Subject: [PATCH 175/234] chore(docker): add git to build dependencies in Dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 275e1e4..f9645aa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ RUN corepack enable && corepack prepare pnpm@latest --activate && \ FROM ${PYTHON_IMAGE}@${PYTHON_HASH} AS builder WORKDIR /build # Install build dependencies for C-extensions -RUN apk add --no-cache gcc musl-dev linux-headers python3-dev libffi-dev openssl-dev +RUN apk add --no-cache gcc musl-dev linux-headers python3-dev libffi-dev openssl-dev git # Setup venv and install dependencies RUN python -m venv /opt/venv ENV PATH="/opt/venv/bin:$PATH" From 666c90875aa810547703b5d00d304e8dd1917a4f Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Mon, 5 Jan 2026 17:38:52 -0600 Subject: [PATCH 176/234] interface discovery, folders for messages, map nodes from discovery, maintenance tools. --- meshchatx/meshchat.py | 372 ++++++++++- meshchatx/src/backend/bot_handler.py | 4 +- meshchatx/src/backend/config_manager.py | 1 + meshchatx/src/backend/database/__init__.py | 54 +- meshchatx/src/backend/database/announces.py | 18 + meshchatx/src/backend/database/messages.py | 85 +++ meshchatx/src/backend/database/schema.py | 46 +- meshchatx/src/backend/docs_manager.py | 9 +- meshchatx/src/backend/message_handler.py | 18 + .../src/frontend/components/TutorialModal.vue | 567 ++++++++++++++-- .../frontend/components/about/AboutPage.vue | 308 +++++++-- .../components/interfaces/InterfacesPage.vue | 612 ++++++++++++++---- .../src/frontend/components/map/MapPage.vue | 158 ++++- .../components/messages/MessagesPage.vue | 141 ++++ .../components/messages/MessagesSidebar.vue | 451 ++++++++++++- .../components/settings/SettingsPage.vue | 310 ++++++++- .../frontend/components/tools/ToolsPage.vue | 70 +- meshchatx/src/frontend/locales/de.json | 44 +- meshchatx/src/frontend/locales/en.json | 44 +- meshchatx/src/frontend/locales/ru.json | 44 +- meshchatx/src/frontend/style.css | 27 + tests/backend/test_identity_restore.py | 85 +++ tests/backend/test_maintenance.py | 64 ++ tests/backend/test_message_handler.py | 12 +- tests/frontend/MessagesSidebar.test.js | 20 +- tests/frontend/Performance.test.js | 2 +- 26 files changed, 3272 insertions(+), 294 deletions(-) create mode 100644 tests/backend/test_identity_restore.py create mode 100644 tests/backend/test_maintenance.py diff --git a/meshchatx/meshchat.py b/meshchatx/meshchat.py index d5a2c26..ed27040 100644 --- a/meshchatx/meshchat.py +++ b/meshchatx/meshchat.py @@ -42,6 +42,7 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.x509.oid import NameOID +from RNS.Discovery import InterfaceDiscovery from serial.tools import list_ports from meshchatx.src.backend.async_utils import AsyncUtils @@ -2152,8 +2153,37 @@ class ReticulumMeshChat: @routes.get("/api/v1/database/snapshots") async def list_db_snapshots(request): try: + limit = int(request.query.get("limit", 100)) + offset = int(request.query.get("offset", 0)) snapshots = self.database.list_snapshots(self.storage_dir) - return web.json_response(snapshots) + total = len(snapshots) + paginated_snapshots = snapshots[offset : offset + limit] + return web.json_response( + { + "snapshots": paginated_snapshots, + "total": total, + "limit": limit, + "offset": offset, + }, + ) + except Exception as e: + return web.json_response( + {"status": "error", "message": str(e)}, + status=500, + ) + + @routes.delete("/api/v1/database/snapshots/{filename}") + async def delete_db_snapshot(request): + try: + filename = request.match_info.get("filename") + if not filename.endswith(".zip"): + filename += ".zip" + self.database.delete_snapshot_or_backup( + self.storage_dir, + filename, + is_backup=False, + ) + return web.json_response({"status": "success"}) except Exception as e: return web.json_response( {"status": "error", "message": str(e)}, @@ -2199,9 +2229,13 @@ class ReticulumMeshChat: @routes.get("/api/v1/database/backups") async def list_db_backups(request): try: + limit = int(request.query.get("limit", 100)) + offset = int(request.query.get("offset", 0)) backup_dir = os.path.join(self.storage_dir, "database-backups") if not os.path.exists(backup_dir): - return web.json_response([]) + return web.json_response( + {"backups": [], "total": 0, "limit": limit, "offset": offset}, + ) backups = [] for file in os.listdir(backup_dir): @@ -2219,9 +2253,39 @@ class ReticulumMeshChat: ).isoformat(), }, ) - return web.json_response( - sorted(backups, key=lambda x: x["created_at"], reverse=True), + sorted_backups = sorted( + backups, + key=lambda x: x["created_at"], + reverse=True, ) + total = len(sorted_backups) + paginated_backups = sorted_backups[offset : offset + limit] + return web.json_response( + { + "backups": paginated_backups, + "total": total, + "limit": limit, + "offset": offset, + }, + ) + except Exception as e: + return web.json_response( + {"status": "error", "message": str(e)}, + status=500, + ) + + @routes.delete("/api/v1/database/backups/{filename}") + async def delete_db_backup(request): + try: + filename = request.match_info.get("filename") + if not filename.endswith(".zip"): + filename += ".zip" + self.database.delete_snapshot_or_backup( + self.storage_dir, + filename, + is_backup=True, + ) + return web.json_response({"status": "success"}) except Exception as e: return web.json_response( {"status": "error", "message": str(e)}, @@ -3360,6 +3424,7 @@ class ReticulumMeshChat: ), "ply": self.get_package_version("ply"), "bcrypt": self.get_package_version("bcrypt"), + "lxmfy": self.get_package_version("lxmfy"), }, "storage_path": self.storage_path, "database_path": self.database_path, @@ -3939,6 +4004,62 @@ class ReticulumMeshChat: status=500, ) + # maintenance - clear messages + @routes.delete("/api/v1/maintenance/messages") + async def maintenance_clear_messages(request): + self.database.messages.delete_all_lxmf_messages() + return web.json_response({"message": "All messages cleared"}) + + # maintenance - clear announces + @routes.delete("/api/v1/maintenance/announces") + async def maintenance_clear_announces(request): + aspect = request.query.get("aspect") + self.database.announces.delete_all_announces(aspect=aspect) + return web.json_response( + { + "message": f"Announces cleared{' for aspect ' + aspect if aspect else ''}", + }, + ) + + # maintenance - clear favorites + @routes.delete("/api/v1/maintenance/favourites") + async def maintenance_clear_favourites(request): + aspect = request.query.get("aspect") + self.database.announces.delete_all_favourites(aspect=aspect) + return web.json_response( + { + "message": f"Favourites cleared{' for aspect ' + aspect if aspect else ''}", + }, + ) + + # maintenance - clear archives + @routes.delete("/api/v1/maintenance/archives") + async def maintenance_clear_archives(request): + self.database.misc.delete_archived_pages() + return web.json_response({"message": "All archived pages cleared"}) + + # maintenance - export messages + @routes.get("/api/v1/maintenance/messages/export") + async def maintenance_export_messages(request): + messages = self.database.messages.get_all_lxmf_messages() + # Convert sqlite3.Row to dict if necessary + messages_list = [dict(m) for m in messages] + return web.json_response({"messages": messages_list}) + + # maintenance - import messages + @routes.post("/api/v1/maintenance/messages/import") + async def maintenance_import_messages(request): + try: + data = await request.json() + messages = data.get("messages", []) + for msg in messages: + self.database.messages.upsert_lxmf_message(msg) + return web.json_response( + {"message": f"Successfully imported {len(messages)} messages"}, + ) + except Exception as e: + return web.json_response({"error": str(e)}, status=400) + # get config @routes.get("/api/v1/config") async def config_get(request): @@ -4043,6 +4164,91 @@ class ReticulumMeshChat: return web.json_response({"discovery": discovery_config}) + @routes.get("/api/v1/reticulum/discovered-interfaces") + async def reticulum_discovered_interfaces(request): + try: + discovery = InterfaceDiscovery(discover_interfaces=False) + interfaces = discovery.list_discovered_interfaces() + active = [] + try: + if hasattr(self, "reticulum") and self.reticulum: + stats = self.reticulum.get_interface_stats().get( + "interfaces", + [], + ) + active = [] + for s in stats: + name = s.get("name") or "" + parsed_host = None + parsed_port = None + if "/" in name: + try: + host_port = name.split("/")[-1].strip("[]") + if ":" in host_port: + parsed_host, parsed_port = host_port.rsplit( + ":", + 1, + ) + try: + parsed_port = int(parsed_port) + except Exception: + parsed_port = None + else: + parsed_host = host_port + except Exception: + parsed_host = None + parsed_port = None + + host = ( + s.get("target_host") or s.get("remote") or parsed_host + ) + port = ( + s.get("target_port") + or s.get("listen_port") + or parsed_port + ) + transport_id = s.get("transport_id") + if isinstance(transport_id, (bytes, bytearray)): + transport_id = transport_id.hex() + + active.append( + { + "name": name, + "short_name": s.get("short_name"), + "type": s.get("type"), + "target_host": host, + "target_port": port, + "listen_ip": s.get("listen_ip"), + "connected": s.get("connected"), + "online": s.get("online"), + "transport_id": transport_id, + "network_id": s.get("network_id"), + }, + ) + except Exception as e: + logger.debug(f"Failed to get interface stats: {e}") + + def to_jsonable(obj): + if isinstance(obj, bytes): + return obj.hex() + if isinstance(obj, dict): + return {k: to_jsonable(v) for k, v in obj.items()} + if isinstance(obj, list): + return [to_jsonable(v) for v in obj] + return obj + + return web.json_response( + { + "interfaces": to_jsonable(interfaces), + "active": to_jsonable(active), + }, + ) + except Exception as e: + return web.json_response( + {"message": f"Failed to load discovered interfaces: {e!s}"}, + status=500, + ) + # enable transport mode @routes.post("/api/v1/reticulum/enable-transport") async def reticulum_enable_transport(request): @@ -6920,6 +7126,12 @@ class ReticulumMeshChat: request.query.get("filter_has_attachments", "false"), ), ) + folder_id = request.query.get("folder_id") + if folder_id is not None: + try: + folder_id = int(folder_id) + except ValueError: + folder_id = None # get pagination params try: @@ -6943,6 +7155,7 @@ class ReticulumMeshChat: filter_unread=filter_unread, filter_failed=filter_failed, filter_has_attachments=filter_has_attachments, + folder_id=folder_id, limit=limit, offset=offset, ) @@ -7021,6 +7234,123 @@ class ReticulumMeshChat: }, ) + @routes.get("/api/v1/lxmf/folders") + async def lxmf_folders_get(request): + folders = self.database.messages.get_all_folders() + return web.json_response([dict(f) for f in folders]) + + @routes.post("/api/v1/lxmf/folders") + async def lxmf_folders_post(request): + data = await request.json() + name = data.get("name") + if not name: + return web.json_response({"message": "Name is required"}, status=400) + try: + self.database.messages.create_folder(name) + return web.json_response({"message": "Folder created"}) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + + @routes.patch("/api/v1/lxmf/folders/{id}") + async def lxmf_folders_patch(request): + folder_id = int(request.match_info["id"]) + data = await request.json() + name = data.get("name") + if not name: + return web.json_response({"message": "Name is required"}, status=400) + self.database.messages.rename_folder(folder_id, name) + return web.json_response({"message": "Folder renamed"}) + + @routes.delete("/api/v1/lxmf/folders/{id}") + async def lxmf_folders_delete(request): + folder_id = int(request.match_info["id"]) + self.database.messages.delete_folder(folder_id) + return web.json_response({"message": "Folder deleted"}) + + @routes.post("/api/v1/lxmf/conversations/move-to-folder") + async def lxmf_conversations_move_to_folder(request): + data = await request.json() + peer_hashes = data.get("peer_hashes", []) + folder_id = data.get("folder_id") # Can be None to remove from folder + if not peer_hashes: + return web.json_response( + {"message": "peer_hashes is required"}, + status=400, + ) + self.database.messages.move_conversations_to_folder(peer_hashes, folder_id) + return web.json_response({"message": "Conversations moved"}) + + @routes.post("/api/v1/lxmf/conversations/bulk-mark-as-read") + async def lxmf_conversations_bulk_mark_read(request): + data = await request.json() + destination_hashes = data.get("destination_hashes", []) + if not destination_hashes: + return web.json_response( + {"message": "destination_hashes is required"}, + status=400, + ) + self.database.messages.mark_conversations_as_read(destination_hashes) + return web.json_response({"message": "Conversations marked as read"}) + + @routes.post("/api/v1/lxmf/conversations/bulk-delete") + async def lxmf_conversations_bulk_delete(request): + data = await request.json() + destination_hashes = data.get("destination_hashes", []) + if not destination_hashes: + return web.json_response( + {"message": "destination_hashes is required"}, + status=400, + ) + local_hash = self.local_lxmf_destination.hexhash + for dest_hash in destination_hashes: + self.message_handler.delete_conversation(local_hash, dest_hash) + return web.json_response({"message": "Conversations deleted"}) + + @routes.get("/api/v1/lxmf/folders/export") + async def lxmf_folders_export(request): + folders = [dict(f) for f in self.database.messages.get_all_folders()] + mappings = [ + dict(m) for m in self.database.messages.get_all_conversation_folders() + ] + return web.json_response({"folders": folders, "mappings": mappings}) + + @routes.post("/api/v1/lxmf/folders/import") + async def lxmf_folders_import(request): + data = await request.json() + folders = data.get("folders", []) + mappings = data.get("mappings", []) + + # We'll try to recreate folders by name to avoid ID conflicts + folder_name_to_new_id = {} + for f in folders: + try: + self.database.messages.create_folder(f["name"]) + except Exception as e: + logger.debug(f"Folder '{f['name']}' likely already exists: {e}") + + # Refresh folder list to get new IDs + all_folders = self.database.messages.get_all_folders() + for f in all_folders: + folder_name_to_new_id[f["name"]] = f["id"] + + # Map old IDs to new IDs if possible, or just use names if we had them + # Since IDs might change, we should have exported names too + # Let's assume the export had folder names in mappings or we match by old folder info + old_id_to_name = {f["id"]: f["name"] for f in folders} + + for m in mappings: + peer_hash = m["peer_hash"] + old_folder_id = m["folder_id"] + folder_name = old_id_to_name.get(old_folder_id) + if folder_name and folder_name in folder_name_to_new_id: + new_folder_id = folder_name_to_new_id[folder_name] + self.database.messages.move_conversation_to_folder( + peer_hash, + new_folder_id, + ) + + return web.json_response({"message": "Folders and mappings imported"}) + # mark lxmf conversation as read @routes.get("/api/v1/lxmf/conversations/{destination_hash}/mark-as-read") async def lxmf_conversations_mark_read(request): @@ -7806,7 +8136,7 @@ class ReticulumMeshChat: f"connect-src {' '.join(connect_sources)}; " "media-src 'self' blob:; " "worker-src 'self' blob:; " - "frame-src 'self'; " + "frame-src 'self' https://reticulum.network; " "object-src 'none'; " "base-uri 'self';" ) @@ -7922,17 +8252,24 @@ class ReticulumMeshChat: # (e.g. when running from a read-only AppImage) if self.current_context and hasattr(self.current_context, "docs_manager"): dm = self.current_context.docs_manager - if ( - dm.docs_dir - and os.path.exists(dm.docs_dir) - and not dm.docs_dir.startswith(public_dir) - ): - app.router.add_static( - "/reticulum-docs/", - dm.docs_dir, - name="reticulum_docs_storage", - follow_symlinks=True, - ) + + # Custom handler for reticulum docs to allow fallback to official website + async def reticulum_docs_handler(request): + path = request.match_info.get("filename", "index.html") + if not path: + path = "index.html" + if path.endswith("/"): + path += "index.html" + + local_path = os.path.join(dm.docs_dir, path) + if os.path.exists(local_path) and os.path.isfile(local_path): + return web.FileResponse(local_path) + + # Fallback to official website + return web.HTTPFound(f"https://reticulum.network/manual/{path}") + + app.router.add_get("/reticulum-docs/{filename:.*}", reticulum_docs_handler) + if ( dm.meshchatx_docs_dir and os.path.exists(dm.meshchatx_docs_dir) @@ -7978,7 +8315,8 @@ class ReticulumMeshChat: print( f"Performing scheduled auto-backup for {ctx.identity_hash}...", ) - ctx.database.backup_database(self.storage_dir) + max_count = ctx.config.backup_max_count.get() + ctx.database.backup_database(self.storage_dir, max_count=max_count) except Exception as e: print(f"Auto-backup failed: {e}") diff --git a/meshchatx/src/backend/bot_handler.py b/meshchatx/src/backend/bot_handler.py index 576fef9..e5b99a1 100644 --- a/meshchatx/src/backend/bot_handler.py +++ b/meshchatx/src/backend/bot_handler.py @@ -240,7 +240,9 @@ class BotHandler: shutil.rmtree(storage_dir) except Exception as exc: logger.warning( - "Failed to delete storage dir for bot %s: %s", bot_id, exc + "Failed to delete storage dir for bot %s: %s", + bot_id, + exc, ) self._save_state() diff --git a/meshchatx/src/backend/config_manager.py b/meshchatx/src/backend/config_manager.py index e8ab093..cb4593f 100644 --- a/meshchatx/src/backend/config_manager.py +++ b/meshchatx/src/backend/config_manager.py @@ -103,6 +103,7 @@ class ConfigManager: "archives_max_storage_gb", 1, ) + self.backup_max_count = self.IntConfig(self, "backup_max_count", 5) self.crawler_enabled = self.BoolConfig(self, "crawler_enabled", False) self.crawler_max_retries = self.IntConfig(self, "crawler_max_retries", 3) self.crawler_retry_delay_seconds = self.IntConfig( diff --git a/meshchatx/src/backend/database/__init__.py b/meshchatx/src/backend/database/__init__.py index 29d2ffc..6ec139a 100644 --- a/meshchatx/src/backend/database/__init__.py +++ b/meshchatx/src/backend/database/__init__.py @@ -211,14 +211,41 @@ class Database: "size": os.path.getsize(backup_path), } - def backup_database(self, storage_path, backup_path: str | None = None): + def backup_database( + self, + storage_path, + backup_path: str | None = None, + max_count: int | None = None, + ): default_dir = os.path.join(storage_path, "database-backups") os.makedirs(default_dir, exist_ok=True) if backup_path is None: timestamp = datetime.now(UTC).strftime("%Y%m%d-%H%M%S") backup_path = os.path.join(default_dir, f"backup-{timestamp}.zip") - return self._backup_to_zip(backup_path) + result = self._backup_to_zip(backup_path) + + # Cleanup old backups if a limit is set + if max_count is not None and max_count > 0: + try: + backups = [] + for file in os.listdir(default_dir): + if file.endswith(".zip"): + full_path = os.path.join(default_dir, file) + stats = os.stat(full_path) + backups.append((full_path, stats.st_mtime)) + + if len(backups) > max_count: + # Sort by modification time (oldest first) + backups.sort(key=lambda x: x[1]) + to_delete = backups[: len(backups) - max_count] + for path, _ in to_delete: + if os.path.exists(path): + os.remove(path) + except Exception as e: + print(f"Failed to cleanup old backups: {e}") + + return result def create_snapshot(self, storage_path, name: str): """Creates a named snapshot of the database.""" @@ -258,6 +285,29 @@ class Database: ) return sorted(snapshots, key=lambda x: x["created_at"], reverse=True) + def delete_snapshot_or_backup( + self, + storage_path, + filename: str, + is_backup: bool = False, + ): + """Deletes a database snapshot or auto-backup.""" + base_dir = "database-backups" if is_backup else "snapshots" + file_path = os.path.join(storage_path, base_dir, filename) + + # Basic security check to ensure we stay within the intended directory + abs_path = os.path.abspath(file_path) + abs_base = os.path.abspath(os.path.join(storage_path, base_dir)) + + if not abs_path.startswith(abs_base): + msg = "Invalid path" + raise ValueError(msg) + + if os.path.exists(abs_path): + os.remove(abs_path) + return True + return False + def restore_database(self, backup_path: str): if not os.path.exists(backup_path): msg = f"Backup not found at {backup_path}" diff --git a/meshchatx/src/backend/database/announces.py b/meshchatx/src/backend/database/announces.py index 080a1bc..a1b626e 100644 --- a/meshchatx/src/backend/database/announces.py +++ b/meshchatx/src/backend/database/announces.py @@ -54,6 +54,15 @@ class AnnounceDAO: (destination_hash,), ) + def delete_all_announces(self, aspect=None): + if aspect: + self.provider.execute( + "DELETE FROM announces WHERE aspect = ?", + (aspect,), + ) + else: + self.provider.execute("DELETE FROM announces") + def get_filtered_announces( self, aspect=None, @@ -137,3 +146,12 @@ class AnnounceDAO: "DELETE FROM favourite_destinations WHERE destination_hash = ?", (destination_hash,), ) + + def delete_all_favourites(self, aspect=None): + if aspect: + self.provider.execute( + "DELETE FROM favourite_destinations WHERE aspect = ?", + (aspect,), + ) + else: + self.provider.execute("DELETE FROM favourite_destinations") diff --git a/meshchatx/src/backend/database/messages.py b/meshchatx/src/backend/database/messages.py index 442be84..618d532 100644 --- a/meshchatx/src/backend/database/messages.py +++ b/meshchatx/src/backend/database/messages.py @@ -63,12 +63,28 @@ class MessageDAO: (message_hash,), ) + def delete_lxmf_messages_by_hashes(self, message_hashes): + if not message_hashes: + return + placeholders = ", ".join(["?"] * len(message_hashes)) + self.provider.execute( + f"DELETE FROM lxmf_messages WHERE hash IN ({placeholders})", + tuple(message_hashes), + ) + def delete_lxmf_message_by_hash(self, message_hash): self.provider.execute( "DELETE FROM lxmf_messages WHERE hash = ?", (message_hash,), ) + def delete_all_lxmf_messages(self): + self.provider.execute("DELETE FROM lxmf_messages") + self.provider.execute("DELETE FROM lxmf_conversation_read_state") + + def get_all_lxmf_messages(self): + return self.provider.fetchall("SELECT * FROM lxmf_messages") + def get_conversation_messages(self, destination_hash, limit=100, offset=0): return self.provider.fetchall( "SELECT * FROM lxmf_messages WHERE peer_hash = ? ORDER BY timestamp DESC LIMIT ? OFFSET ?", @@ -103,6 +119,22 @@ class MessageDAO: (destination_hash, now, now, now), ) + def mark_conversations_as_read(self, destination_hashes): + if not destination_hashes: + return + now = datetime.now(UTC).isoformat() + for destination_hash in destination_hashes: + self.provider.execute( + """ + INSERT INTO lxmf_conversation_read_state (destination_hash, last_read_at, created_at, updated_at) + VALUES (?, ?, ?, ?) + ON CONFLICT(destination_hash) DO UPDATE SET + last_read_at = EXCLUDED.last_read_at, + updated_at = EXCLUDED.updated_at + """, + (destination_hash, now, now, now), + ) + def is_conversation_unread(self, destination_hash): row = self.provider.fetchone( """ @@ -290,3 +322,56 @@ class MessageDAO: last_viewed_at = last_viewed_at.replace(tzinfo=UTC) return message_timestamp <= last_viewed_at.timestamp() + + # Folders + def get_all_folders(self): + return self.provider.fetchall("SELECT * FROM lxmf_folders ORDER BY name ASC") + + def create_folder(self, name): + now = datetime.now(UTC).isoformat() + return self.provider.execute( + "INSERT INTO lxmf_folders (name, created_at, updated_at) VALUES (?, ?, ?)", + (name, now, now), + ) + + def rename_folder(self, folder_id, new_name): + now = datetime.now(UTC).isoformat() + self.provider.execute( + "UPDATE lxmf_folders SET name = ?, updated_at = ? WHERE id = ?", + (new_name, now, folder_id), + ) + + def delete_folder(self, folder_id): + self.provider.execute("DELETE FROM lxmf_folders WHERE id = ?", (folder_id,)) + + def get_conversation_folder(self, peer_hash): + return self.provider.fetchone( + "SELECT * FROM lxmf_conversation_folders WHERE peer_hash = ?", + (peer_hash,), + ) + + def move_conversation_to_folder(self, peer_hash, folder_id): + now = datetime.now(UTC).isoformat() + if folder_id is None: + self.provider.execute( + "DELETE FROM lxmf_conversation_folders WHERE peer_hash = ?", + (peer_hash,), + ) + else: + self.provider.execute( + """ + INSERT INTO lxmf_conversation_folders (peer_hash, folder_id, created_at, updated_at) + VALUES (?, ?, ?, ?) + ON CONFLICT(peer_hash) DO UPDATE SET + folder_id = EXCLUDED.folder_id, + updated_at = EXCLUDED.updated_at + """, + (peer_hash, folder_id, now, now), + ) + + def move_conversations_to_folder(self, peer_hashes, folder_id): + for peer_hash in peer_hashes: + self.move_conversation_to_folder(peer_hash, folder_id) + + def get_all_conversation_folders(self): + return self.provider.fetchall("SELECT * FROM lxmf_conversation_folders") diff --git a/meshchatx/src/backend/database/schema.py b/meshchatx/src/backend/database/schema.py index 49f8b86..4a551cd 100644 --- a/meshchatx/src/backend/database/schema.py +++ b/meshchatx/src/backend/database/schema.py @@ -2,7 +2,7 @@ from .provider import DatabaseProvider class DatabaseSchema: - LATEST_VERSION = 35 + LATEST_VERSION = 36 def __init__(self, provider: DatabaseProvider): self.provider = provider @@ -423,6 +423,24 @@ class DatabaseSchema: created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) """, + "lxmf_folders": """ + CREATE TABLE IF NOT EXISTS lxmf_folders ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT UNIQUE, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP + ) + """, + "lxmf_conversation_folders": """ + CREATE TABLE IF NOT EXISTS lxmf_conversation_folders ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + peer_hash TEXT UNIQUE, + folder_id INTEGER, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (folder_id) REFERENCES lxmf_folders(id) ON DELETE CASCADE + ) + """, } for table_name, create_sql in tables.items(): @@ -933,6 +951,32 @@ class DatabaseSchema: "ALTER TABLE contacts ADD COLUMN lxst_address TEXT DEFAULT NULL", ) + if current_version < 36: + self._safe_execute(""" + CREATE TABLE IF NOT EXISTS lxmf_folders ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT UNIQUE, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP + ) + """) + self._safe_execute(""" + CREATE TABLE IF NOT EXISTS lxmf_conversation_folders ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + peer_hash TEXT UNIQUE, + folder_id INTEGER, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (folder_id) REFERENCES lxmf_folders(id) ON DELETE CASCADE + ) + """) + self._safe_execute( + "CREATE INDEX IF NOT EXISTS idx_lxmf_conversation_folders_peer_hash ON lxmf_conversation_folders(peer_hash)", + ) + self._safe_execute( + "CREATE INDEX IF NOT EXISTS idx_lxmf_conversation_folders_folder_id ON lxmf_conversation_folders(folder_id)", + ) + # Update version in config self._safe_execute( """ diff --git a/meshchatx/src/backend/docs_manager.py b/meshchatx/src/backend/docs_manager.py index 64c4335..d78d031 100644 --- a/meshchatx/src/backend/docs_manager.py +++ b/meshchatx/src/backend/docs_manager.py @@ -38,7 +38,12 @@ class DocsManager: # Ensure docs directories exist try: - for d in [self.docs_base_dir, self.versions_dir, self.meshchatx_docs_dir]: + for d in [ + self.docs_base_dir, + self.versions_dir, + self.docs_dir, + self.meshchatx_docs_dir, + ]: if not os.path.exists(d): os.makedirs(d) @@ -423,8 +428,6 @@ class DocsManager: def has_docs(self): # Check if index.html exists in the docs folder or if we have any versions - if self.config.docs_downloaded.get(): - return True return ( os.path.exists(os.path.join(self.docs_dir, "index.html")) or len(self.get_available_versions()) > 0 diff --git a/meshchatx/src/backend/message_handler.py b/meshchatx/src/backend/message_handler.py index 4fb1c8a..5a3deeb 100644 --- a/meshchatx/src/backend/message_handler.py +++ b/meshchatx/src/backend/message_handler.py @@ -35,6 +35,11 @@ class MessageHandler: def delete_conversation(self, local_hash, destination_hash): query = "DELETE FROM lxmf_messages WHERE peer_hash = ?" self.db.provider.execute(query, [destination_hash]) + # Also clean up folder mapping + self.db.provider.execute( + "DELETE FROM lxmf_conversation_folders WHERE peer_hash = ?", + [destination_hash], + ) def search_messages(self, local_hash, search_term): like_term = f"%{search_term}%" @@ -54,6 +59,7 @@ class MessageHandler: filter_unread=False, filter_failed=False, filter_has_attachments=False, + folder_id=None, limit=None, offset=0, ): @@ -66,6 +72,8 @@ class MessageHandler: con.custom_image as contact_image, i.icon_name, i.foreground_colour, i.background_colour, r.last_read_at, + f.id as folder_id, + fn.name as folder_name, (SELECT COUNT(*) FROM lxmf_messages m_failed WHERE m_failed.peer_hash = m1.peer_hash AND m_failed.state = 'failed') as failed_count FROM lxmf_messages m1 @@ -84,10 +92,20 @@ class MessageHandler: ) LEFT JOIN lxmf_user_icons i ON i.destination_hash = m1.peer_hash LEFT JOIN lxmf_conversation_read_state r ON r.destination_hash = m1.peer_hash + LEFT JOIN lxmf_conversation_folders f ON f.peer_hash = m1.peer_hash + LEFT JOIN lxmf_folders fn ON fn.id = f.folder_id """ params = [] where_clauses = [] + if folder_id is not None: + if folder_id == 0 or folder_id == "0": + # Special case: no folder (Uncategorized) + where_clauses.append("f.folder_id IS NULL") + else: + where_clauses.append("f.folder_id = ?") + params.append(folder_id) + if filter_unread: where_clauses.append( "(r.last_read_at IS NULL OR m1.timestamp > strftime('%s', r.last_read_at))", diff --git a/meshchatx/src/frontend/components/TutorialModal.vue b/meshchatx/src/frontend/components/TutorialModal.vue index 6023cfe..f3db212 100644 --- a/meshchatx/src/frontend/components/TutorialModal.vue +++ b/meshchatx/src/frontend/components/TutorialModal.vue @@ -180,7 +180,161 @@

    -
    +
    +
    + +
    + {{ + $t("tutorial.discovery_question") || + "Do you want to use community interface discovering and auto-connect?" + }} +
    +

    + {{ + $t("tutorial.discovery_desc") || + "This allows MeshChatX to automatically find and connect to public community nodes near you or on the internet." + }} +

    +
    + + +
    +
    +
    + +
    + +
    +
    + + Discovered Interfaces +
    +
    +
    +
    +
    + +
    + +
    +
    +
    + {{ iface.name }} +
    + {{ + iface.type + }} +
    + +
    + + Stamps: {{ iface.value }} + +
    + +
    + Hops: {{ iface.hops }} + {{ iface.status }} + + {{ formatLastHeard(iface.last_heard) }} + +
    + +
    +
    + + Address: {{ iface.reachable_on }}:{{ iface.port }} +
    +
    + + Transport ID: {{ iface.transport_id }} +
    +
    + + Network ID: {{ iface.network_id }} +
    +
    +
    + +
    + Heard +
    +
    +
    +
    +
    +
    -
    +

    {{ $t("tutorial.custom_interfaces_desc") }}

    @@ -479,7 +636,7 @@
    -
    +
    -
    - +
    -
    - - {{ - $t("tutorial.suggested_relays") - }} + +
    + {{ + $t("tutorial.discovery_question") || + "Do you want to use community interface discovering and auto-connect?" + }}
    -
    -
    + {{ + $t("tutorial.discovery_desc") || + "This allows MeshChatX to automatically find and connect to public community nodes near you or on the internet." + }} +

    +
    + + +
    +
    +
    + +
    + +
    +
    + +
    +
    +
    + + Discovered +
    +
    +
    +
    +
    + +
    + +
    +
    +
    + {{ iface.name }} +
    + {{ iface.type }} +
    + +
    + + Stamps: {{ iface.value }} + +
    + +
    + Hops: {{ iface.hops }} + {{ + iface.status + }} + + {{ formatLastHeard(iface.last_heard) }} + +
    + +
    +
    + + Address: {{ iface.reachable_on }}:{{ + iface.port + }} +
    + +
    + + Transport ID: {{ iface.transport_id }} +
    + +
    + + Network ID: {{ iface.network_id }} +
    + +
    + + Loc: {{ iface.latitude }}, + {{ iface.longitude }} +
    +
    +
    + +
    + Heard +
    +
    +
    +
    -
    - + + +
    +
    + + {{ + $t("tutorial.suggested_relays") + }} +
    +
    +
    +
    + + {{ iface.name }} + + {{ iface.target_host }}:{{ iface.target_port }} +
    +
    + + + {{ $t("tutorial.online") }} + + +
    +
    +
    + +
    +
    +
    -
    -

    +

    + +

    {{ $t("tutorial.custom_interfaces") }}

    -

    +

    {{ $t("tutorial.custom_interfaces_desc_page") }}

    +
    +
    Reticulum Network Stack
    -
    - v{{ appInfo.rns_version }} +
    +
    + v{{ appInfo.rns_version }} +
    +
    + {{ + appInfo.is_connected_to_shared_instance + ? "Shared Instance" + : "Main Instance" + }} +
    @@ -530,34 +566,75 @@
    -
    -
    -
    - {{ snapshot.name }} - {{ formatBytes(snapshot.size) }} • {{ snapshot.created_at }} -
    - +
    + {{ snapshot.name }} + {{ formatBytes(snapshot.size) }} • + {{ Utils.formatTimeAgo(snapshot.created_at) }} +
    +
    + + +
    +
    +
    + + +
    +
    + Page {{ Math.floor(snapshotsOffset / snapshotsLimit) + 1 }} of + {{ Math.ceil(snapshotsTotal / snapshotsLimit) }} +
    +
    + + +
    -
    +
    -
    -
    -
    - {{ backup.name }} - {{ formatBytes(backup.size) }} • {{ backup.created_at }} -
    - +
    + {{ backup.name }} + {{ formatBytes(backup.size) }} • + {{ Utils.formatTimeAgo(backup.created_at) }} +
    +
    + + +
    +
    +
    + + +
    +
    + Page {{ Math.floor(autoBackupsOffset / autoBackupsLimit) + 1 }} of + {{ Math.ceil(autoBackupsTotal / autoBackupsLimit) }} +
    +
    + + +
    @@ -704,6 +822,7 @@ export default { components: {}, data() { return { + Utils, appInfo: null, config: null, updateInterval: null, @@ -725,10 +844,16 @@ export default { restoreFile: null, snapshotName: "", snapshots: [], + snapshotsTotal: 0, + snapshotsOffset: 0, + snapshotsLimit: 3, snapshotInProgress: false, snapshotMessage: "", snapshotError: "", autoBackups: [], + autoBackupsTotal: 0, + autoBackupsOffset: 0, + autoBackupsLimit: 3, identityBackupMessage: "", identityBackupError: "", identityBase32: "", @@ -776,18 +901,74 @@ export default { methods: { async listSnapshots() { try { - const response = await window.axios.get("/api/v1/database/snapshots"); - this.snapshots = response.data; + const response = await window.axios.get("/api/v1/database/snapshots", { + params: { + limit: this.snapshotsLimit, + offset: this.snapshotsOffset, + }, + }); + this.snapshots = response.data.snapshots; + this.snapshotsTotal = response.data.total; } catch (e) { console.log("Failed to list snapshots", e); } }, async listAutoBackups() { try { - const response = await window.axios.get("/api/v1/database/backups"); - this.autoBackups = response.data; - } catch (e) { - console.log("Failed to list auto-backups", e); + const response = await window.axios.get("/api/v1/database/backups", { + params: { + limit: this.autoBackupsLimit, + offset: this.autoBackupsOffset, + }, + }); + this.autoBackups = response.data.backups; + this.autoBackupsTotal = response.data.total; + } catch { + console.log("Failed to list auto-backups"); + } + }, + async deleteSnapshot(filename) { + if (!(await DialogUtils.confirm("Are you sure you want to delete this snapshot?"))) return; + try { + await window.axios.delete(`/api/v1/database/snapshots/${filename}`); + ToastUtils.success("Snapshot deleted"); + await this.listSnapshots(); + } catch { + ToastUtils.error("Failed to delete snapshot"); + } + }, + async deleteBackup(filename) { + if (!(await DialogUtils.confirm("Are you sure you want to delete this backup?"))) return; + try { + await window.axios.delete(`/api/v1/database/backups/${filename}`); + ToastUtils.success("Backup deleted"); + await this.listAutoBackups(); + } catch { + ToastUtils.error("Failed to delete backup"); + } + }, + async nextSnapshots() { + if (this.snapshotsOffset + this.snapshotsLimit < this.snapshotsTotal) { + this.snapshotsOffset += this.snapshotsLimit; + await this.listSnapshots(); + } + }, + async prevSnapshots() { + if (this.snapshotsOffset > 0) { + this.snapshotsOffset = Math.max(0, this.snapshotsOffset - this.snapshotsLimit); + await this.listSnapshots(); + } + }, + async nextBackups() { + if (this.autoBackupsOffset + this.autoBackupsLimit < this.autoBackupsTotal) { + this.autoBackupsOffset += this.autoBackupsLimit; + await this.listAutoBackups(); + } + }, + async prevBackups() { + if (this.autoBackupsOffset > 0) { + this.autoBackupsOffset = Math.max(0, this.autoBackupsOffset - this.autoBackupsLimit); + await this.listAutoBackups(); } }, async createSnapshot() { @@ -802,9 +983,8 @@ export default { this.snapshotMessage = "Snapshot created successfully"; this.snapshotName = ""; await this.listSnapshots(); - } catch (e) { + } catch { this.snapshotError = "Failed to create snapshot"; - console.log(e); } finally { this.snapshotInProgress = false; } @@ -825,9 +1005,8 @@ export default { setTimeout(() => ElectronUtils.relaunch(), 2000); } } - } catch (e) { + } catch { ToastUtils.error("Failed to restore snapshot"); - console.log(e); } }, async getAppInfo() { @@ -856,9 +1035,8 @@ export default { await window.axios.post("/api/v1/app/integrity/acknowledge"); ToastUtils.success("Integrity issues acknowledged"); await this.getAppInfo(); - } catch (e) { + } catch { ToastUtils.error("Failed to acknowledge integrity issues"); - console.log(e); } } }, @@ -1075,9 +1253,9 @@ export default { link.remove(); window.URL.revokeObjectURL(url); this.identityBackupMessage = "Identity downloaded. Keep it secret."; - } catch (e) { + ToastUtils.success("Identity key file exported"); + } catch { this.identityBackupError = "Failed to download identity"; - console.log(e); } }, async copyIdentityBase32() { @@ -1092,9 +1270,9 @@ export default { } await navigator.clipboard.writeText(this.identityBase32); this.identityBase32Message = "Identity copied. Clear your clipboard after use."; - } catch (e) { + ToastUtils.success("Identity Base32 key copied to clipboard"); + } catch { this.identityBase32Error = "Failed to copy identity"; - console.log(e); } }, onIdentityRestoreFileChange(event) { @@ -1124,9 +1302,8 @@ export default { headers: { "Content-Type": "multipart/form-data" }, }); this.identityRestoreMessage = response.data.message || "Identity imported."; - } catch (e) { + } catch { this.identityRestoreError = "Identity restore failed"; - console.log(e); } finally { this.identityRestoreInProgress = false; } @@ -1147,9 +1324,8 @@ export default { base32: this.identityRestoreBase32.trim(), }); this.identityRestoreMessage = response.data.message || "Identity imported."; - } catch (e) { + } catch { this.identityRestoreError = "Identity restore failed"; - console.log(e); } finally { this.identityRestoreInProgress = false; } diff --git a/meshchatx/src/frontend/components/interfaces/InterfacesPage.vue b/meshchatx/src/frontend/components/interfaces/InterfacesPage.vue index f2e67b3..068a4e5 100644 --- a/meshchatx/src/frontend/components/interfaces/InterfacesPage.vue +++ b/meshchatx/src/frontend/components/interfaces/InterfacesPage.vue @@ -3,7 +3,7 @@ class="flex flex-col flex-1 overflow-hidden min-w-0 bg-gradient-to-br from-slate-50 via-slate-100 to-white dark:from-zinc-950 dark:via-zinc-900 dark:to-zinc-900" >
    -
    +
    -
    +
    {{ $t("interfaces.manage") }}
    -
    +
    {{ $t("interfaces.title") }}
    @@ -111,136 +111,370 @@
    -
    - -
    {{ $t("interfaces.no_interfaces_found") }}
    -
    {{ $t("interfaces.no_interfaces_description") }}
    -
    -
    -
    -
    -
    - Discovery -
    -
    Interface Discovery
    -
    - Publish your interfaces for others to find, or listen for announced entrypoints and - auto-connect to them. -
    -
    - - - Configure Per-Interface - +
    +
    -
    -
    -
    Publish (Server)
    -
    - Enable discovery while adding or editing an interface to broadcast reachable details. - Reticulum will sign and stamp announces automatically. + +
    +
    +
    + Configured
    -
    - Requires LXMF in the Python environment. Transport is optional for publishing, but - usually recommended so peers can connect back. +
    Interfaces
    +
    + +
    +
    + +
    {{ $t("interfaces.no_interfaces_found") }}
    +
    {{ $t("interfaces.no_interfaces_description") }}
    -
    -
    -
    -
    - Discover Interfaces (Peer) + +
    +
    +
    +
    + Discovered Interfaces +
    +
    + Recently Heard Announces +
    +
    + Cards appear/disappear as announces are heard. Connected entries show a green + pill; disconnected entries are dimmed with a red label. +
    +
    +
    + + +
    +
    + +
    + No discovered interfaces yet. +
    + +
    +
    +
    + +
    +
    + + {{ $t("app.disabled") }} +
    +
    + +
    + +
    + +
    +
    +
    + {{ iface.name }} +
    + {{ iface.type }} +
    + +
    + + Stamps: {{ iface.value }} + + + Connected + +
    + +
    + Hops: {{ iface.hops }} + {{ + iface.status + }} + + Heard: {{ formatLastHeard(iface.last_heard) }} + +
    + +
    +
    + + Address: {{ iface.reachable_on }}:{{ iface.port }} +
    + +
    + + Transport ID: {{ iface.transport_id }} +
    + +
    + + Network ID: {{ iface.network_id }} +
    + +
    + + Loc: {{ iface.latitude }}, {{ iface.longitude }} +
    + +
    + + TX {{ discoveredBytes(iface).tx }} · RX + {{ discoveredBytes(iface).rx }} +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Discovery +
    +
    + Interface Discovery +
    +
    + Publish your interfaces for others to find, or listen for announced entrypoints + and auto-connect to them. +
    +
    + + + Configure Per-Interface + +
    +
    +
    +
    Publish (Server)
    +
    + Enable discovery while adding or editing an interface to broadcast reachable + details. Reticulum will sign and stamp announces automatically.
    - Listen for discovery announces and optionally auto-connect to available - interfaces. + Requires LXMF in the Python environment. Transport is optional for publishing, + but usually recommended so peers can connect back.
    - -
    -
    -
    -
    - Allowed Sources +
    +
    +
    +
    + Discover Interfaces (Peer) +
    +
    + Listen for discovery announces and optionally auto-connect to available + interfaces. +
    +
    +
    - -
    -
    -
    - Required Stamp Value +
    +
    +
    + Allowed Sources +
    + +
    +
    +
    + Required Stamp Value +
    + +
    +
    +
    + Auto-connect Slots +
    + +
    + 0 disables auto-connect. +
    +
    +
    +
    + Network Identity Path +
    + +
    - -
    -
    -
    - Auto-connect Slots +
    +
    - -
    0 disables auto-connect.
    -
    -
    - Network Identity Path -
    - -
    -
    -
    -
    - -
    - -
    @@ -286,6 +520,10 @@ export default { network_identity: "", }, savingDiscovery: false, + discoveredInterfaces: [], + discoveredActive: [], + discoveryInterval: null, + activeTab: "overview", }; }, computed: { @@ -357,19 +595,57 @@ export default { this.interfacesWithStats.forEach((iface) => types.add(iface.type)); return Array.from(types).sort(); }, + sortedDiscoveredInterfaces() { + return [...this.discoveredInterfaces].sort((a, b) => (b.last_heard || 0) - (a.last_heard || 0)); + }, + interfacesWithLocation() { + return this.discoveredInterfaces.filter((iface) => iface.latitude != null && iface.longitude != null); + }, + activeInterfaceStats() { + return Object.values(this.interfaceStats || {}); + }, + tabChipClass() { + return (isActive) => (isActive ? "primary-chip text-xs" : "secondary-chip text-xs"); + }, + discoveredActiveSet() { + const set = new Set(); + this.discoveredActive.forEach((a) => { + const host = a.target_host || a.remote || a.listen_ip; + const port = a.target_port || a.listen_port; + if (host && port) { + set.add(`${host}:${port}`); + } + }); + return set; + }, + discoveredActiveTransportIds() { + const set = new Set(); + this.discoveredActive.forEach((a) => { + if (a.transport_id) { + set.add(a.transport_id); + } + }); + return set; + }, }, beforeUnmount() { clearInterval(this.reloadInterval); + clearInterval(this.discoveryInterval); }, mounted() { this.loadInterfaces(); this.updateInterfaceStats(); this.loadDiscoveryConfig(); + this.loadDiscoveredInterfaces(); // update info every few seconds this.reloadInterval = setInterval(() => { this.updateInterfaceStats(); }, 1000); + + this.discoveryInterval = setInterval(() => { + this.loadDiscoveredInterfaces(); + }, 5000); }, methods: { relaunch() { @@ -506,6 +782,77 @@ export default { this.trackInterfaceChange(); } }, + async loadDiscoveredInterfaces() { + try { + const response = await window.axios.get(`/api/v1/reticulum/discovered-interfaces`); + this.discoveredInterfaces = response.data?.interfaces ?? []; + this.discoveredActive = response.data?.active ?? []; + } catch (e) { + console.log(e); + } + }, + formatLastHeard(ts) { + const seconds = Math.max(0, Math.floor(Date.now() / 1000 - ts)); + if (seconds < 60) return `${seconds}s ago`; + if (seconds < 3600) return `${Math.floor(seconds / 60)}m ago`; + if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ago`; + return `${Math.floor(seconds / 86400)}d ago`; + }, + isDiscoveredConnected(iface) { + const reach = iface.reachable_on; + const port = iface.port; + if (iface.transport_id && this.discoveredActiveTransportIds.has(iface.transport_id)) { + return true; + } + if (reach && port && this.discoveredActiveSet && this.discoveredActiveSet.has(`${reach}:${port}`)) { + return true; + } + return this.activeInterfaceStats.some((s) => { + const hostMatch = + (s.target_host && reach && s.target_host === reach) || (s.remote && reach && s.remote === reach); + const portMatch = + (s.target_port && port && Number(s.target_port) === Number(port)) || + (s.listen_port && port && Number(s.listen_port) === Number(port)); + return hostMatch && portMatch && (s.connected || s.online); + }); + }, + goToMap(iface) { + if (iface.latitude == null || iface.longitude == null) return; + this.$router.push({ + name: "map", + query: { + lat: iface.latitude, + lon: iface.longitude, + label: iface.name, + }, + }); + }, + mapAllDiscovered() { + this.$router.push({ + name: "map", + query: { view: "discovered" }, + }); + }, + discoveredBytes(iface) { + const reach = iface.reachable_on; + const port = iface.port; + const stats = this.activeInterfaceStats || []; + const match = stats.find((s) => { + const host = s.target_host || s.remote || s.interface_name; + const p = s.target_port || s.listen_port; + const hostMatch = host && reach && host === reach; + const portMatch = p && port && Number(p) === Number(port); + return hostMatch && portMatch; + }); + if (!match) return null; + return { + tx: this.formatBytes(match.txb || 0), + rx: this.formatBytes(match.rxb || 0), + }; + }, + formatBytes(bytes) { + return Utils.formatBytes(bytes || 0); + }, parseBool(value) { if (typeof value === "string") { return ["true", "yes", "1", "y", "on"].includes(value.toLowerCase()); @@ -565,6 +912,39 @@ export default { this.savingDiscovery = false; } }, + getDiscoveryIcon(iface) { + switch (iface.type) { + case "AutoInterface": + return "home-automation"; + case "RNodeInterface": + return iface.port && iface.port.toString().startsWith("tcp://") ? "lan-connect" : "radio-tower"; + case "RNodeMultiInterface": + return "access-point-network"; + case "TCPClientInterface": + case "BackboneInterface": + return "lan-connect"; + case "TCPServerInterface": + return "lan"; + case "UDPInterface": + return "wan"; + case "SerialInterface": + return "usb-port"; + case "KISSInterface": + case "AX25KISSInterface": + return "antenna"; + case "I2PInterface": + return "eye"; + case "PipeInterface": + return "pipe"; + default: + return "server-network"; + } + }, + copyToClipboard(text, label) { + if (!text) return; + navigator.clipboard.writeText(text); + ToastUtils.success(`${label} copied to clipboard`); + }, setStatusFilter(value) { this.statusFilter = value; }, diff --git a/meshchatx/src/frontend/components/map/MapPage.vue b/meshchatx/src/frontend/components/map/MapPage.vue index 85c7219..b8aeb4a 100644 --- a/meshchatx/src/frontend/components/map/MapPage.vue +++ b/meshchatx/src/frontend/components/map/MapPage.vue @@ -28,6 +28,13 @@
    + +
    + +
    + + +
    +
    +
    +
    +
    +
    + + All Messages +
    +
    + + Uncategorized +
    +
    + + {{ folder.name }} + +
    +
    +
    +
    +
    +
    +
    + + + {{ selectedHashes.size }} selected + +
    +
    + + +
    + +
    + + +
    +
    +
    +
    +
    +
    + Move to Folder +
    + +
    + +
    +
    + +
    +
    @@ -340,6 +626,7 @@ diff --git a/meshchatx/src/frontend/components/messages/ConversationDropDownMenu.vue b/meshchatx/src/frontend/components/messages/ConversationDropDownMenu.vue index 3eb8660..6a8418e 100644 --- a/meshchatx/src/frontend/components/messages/ConversationDropDownMenu.vue +++ b/meshchatx/src/frontend/components/messages/ConversationDropDownMenu.vue @@ -2,7 +2,7 @@ @@ -70,7 +86,18 @@ export default { required: true, }, }, - emits: ["conversation-deleted", "set-custom-display-name", "block-status-changed", "popout"], + emits: [ + "conversation-deleted", + "set-custom-display-name", + "block-status-changed", + "popout", + "view-telemetry-history", + ], + data() { + return { + contact: null, + }; + }, computed: { isBlocked() { if (!this.peer) { @@ -79,7 +106,72 @@ export default { return GlobalState.blockedDestinations.some((b) => b.destination_hash === this.peer.destination_hash); }, }, + watch: { + peer: { + immediate: true, + handler() { + this.fetchContact(); + }, + }, + }, + mounted() { + GlobalEmitter.on("contact-updated", this.onContactUpdated); + }, + unmounted() { + GlobalEmitter.off("contact-updated", this.onContactUpdated); + }, methods: { + onContactUpdated(data) { + if (this.peer?.destination_hash === data.remote_identity_hash) { + this.fetchContact(); + } + }, + async fetchContact() { + if (!this.peer || !this.peer.destination_hash) return; + try { + const response = await window.axios.get( + `/api/v1/telephone/contacts/check/${this.peer.destination_hash}` + ); + if (response.data.is_contact) { + this.contact = response.data.contact; + } else { + this.contact = null; + } + } catch (e) { + console.error("Failed to fetch contact", e); + } + }, + async onToggleTelemetryTrust() { + const newStatus = !this.contact?.is_telemetry_trusted; + try { + if (!this.contact) { + // create contact first + await window.axios.post("/api/v1/telephone/contacts", { + name: this.peer.display_name, + remote_identity_hash: this.peer.destination_hash, + is_telemetry_trusted: true, + }); + await this.fetchContact(); + } else { + await window.axios.patch(`/api/v1/telephone/contacts/${this.contact.id}`, { + is_telemetry_trusted: newStatus, + }); + this.contact.is_telemetry_trusted = newStatus; + } + GlobalEmitter.emit("contact-updated", { + remote_identity_hash: this.peer.destination_hash, + is_telemetry_trusted: newStatus, + }); + DialogUtils.alert( + newStatus + ? this.$t("app.telemetry_trust_granted_alert") + : this.$t("app.telemetry_trust_revoked_alert") + ); + } catch (e) { + DialogUtils.alert(this.$t("app.telemetry_trust_failed")); + console.error(e); + } + }, async onBlockDestination() { if ( !(await DialogUtils.confirm( diff --git a/meshchatx/src/frontend/components/messages/ConversationViewer.vue b/meshchatx/src/frontend/components/messages/ConversationViewer.vue index fd09aaf..6911874 100644 --- a/meshchatx/src/frontend/components/messages/ConversationViewer.vue +++ b/meshchatx/src/frontend/components/messages/ConversationViewer.vue @@ -57,24 +57,32 @@ {{ selectedPeer.custom_display_name ?? selectedPeer.display_name }}
    -
    +
    -
    -
    - {{ formatDestinationHash(selectedPeer.destination_hash) }} -
    +
    + {{ formatDestinationHash(selectedPeer.destination_hash) }}
    -
    -
    +
    + + +
    {{ @@ -84,19 +92,30 @@ - - - {{ - $t("messages.snr", { snr: selectedPeerSignalMetrics.snr }) - }} + + + {{ $t("messages.snr", { snr: selectedPeerSignalMetrics.snr }) }} - - - {{ - $t("messages.stamp_cost", { cost: selectedPeerLxmfStampInfo.stamp_cost }) - }} + + + {{ + $t("messages.stamp_cost", { cost: selectedPeerLxmfStampInfo.stamp_cost }) + }}
    @@ -104,7 +123,7 @@
    -
    +
    - + + + + + + + + + + + + + + + + - - - - - - - - - - - +
    + +
    +
    +
    +
    + +

    Telemetry History

    +
    + +
    +
    +
    + No telemetry history found for this peer. +
    +
    +
    + + {{ item.is_outbound ? "Sent" : "Received" }} + + {{ + formatTimeAgo(item.lxmf_message.created_at) + }} +
    + + +
    + +
    + + +
    + + + Battery: {{ item.lxmf_message.fields.telemetry.battery.charge_percent }}% + + + + SNR: {{ item.lxmf_message.fields.telemetry.physical_link.snr }}dB + +
    + + +
    + + Location Request +
    +
    +
    +
    +
    +
    + Battery Level (%) + {{ telemetryBatteryHistory[0].y }}% → + {{ telemetryBatteryHistory[telemetryBatteryHistory.length - 1].y }}% +
    + + + + +
    + +
    + + +
    +
    +
    +
    +
    +
    + + + +
    - {{ chatItem.lxmf_message.content }} + + + {{ chatItem.is_outbound ? "Telemetry update sent" : "Telemetry update received" }} + +
    + +
    + + Telemetry stream received ({{ + chatItem.lxmf_message.fields.telemetry_stream.length + }} + entries) +
    + +
    + + + {{ chatItem.is_outbound ? "Location Request Sent" : "Location Request Received" }} +
    @@ -481,29 +682,120 @@
    - -
    - +
    +
    + + +
    +
    + + + + +
    + + +
    +
    + + {{ chatItem.lxmf_message.fields.telemetry.battery.charge_percent }}% +
    +
    + + SNR: {{ chatItem.lxmf_message.fields.telemetry.physical_link.snr }}dB +
    +
    @@ -1395,6 +1687,7 @@ import GlobalEmitter from "../../js/GlobalEmitter"; import ToastUtils from "../../js/ToastUtils"; import PaperMessageModal from "./PaperMessageModal.vue"; import GlobalState from "../../js/GlobalState"; +import MarkdownRenderer from "../../js/MarkdownRenderer"; export default { name: "ConversationViewer", @@ -1428,7 +1721,7 @@ export default { required: true, }, }, - emits: ["close", "reload-conversations", "update:selectedPeer"], + emits: ["close", "reload-conversations", "update:selectedPeer", "update-peer-tracking"], data() { return { GlobalState, @@ -1493,6 +1786,9 @@ export default { translatorLanguages: [], propagationNodeStatus: null, propagationStatusInterval: null, + + showTelemetryInChat: false, + isTelemetryHistoryModalOpen: false, }; }, computed: { @@ -1605,7 +1901,15 @@ export default { chatItem.lxmf_message.source_hash === this.selectedPeer.destination_hash; const isToSelectedPeer = chatItem.lxmf_message.destination_hash === this.selectedPeer.destination_hash; - return isFromSelectedPeer || isToSelectedPeer; + + if (!(isFromSelectedPeer || isToSelectedPeer)) return false; + + // filter telemetry if disabled + if (!this.showTelemetryInChat && this.isTelemetryOnly(chatItem.lxmf_message)) { + return false; + } + + return true; } return false; @@ -1615,6 +1919,24 @@ export default { // no peer, so no chat items! return []; }, + selectedPeerTelemetryItems() { + if (!this.selectedPeer) return []; + return this.chatItems + .filter((chatItem) => { + if (chatItem.type === "lxmf_message") { + const isFromSelectedPeer = + chatItem.lxmf_message.source_hash === this.selectedPeer.destination_hash; + const isToSelectedPeer = + chatItem.lxmf_message.destination_hash === this.selectedPeer.destination_hash; + + if (!(isFromSelectedPeer || isToSelectedPeer)) return false; + + return this.isTelemetryOnly(chatItem.lxmf_message); + } + return false; + }) + .reverse(); + }, selectedPeerChatItemsReversed() { // ensure a copy of the array is returned in reverse order return this.selectedPeerChatItems.map((message) => message).reverse(); @@ -1631,6 +1953,31 @@ export default { (item) => item.is_outbound && ["failed", "cancelled"].includes(item.lxmf_message?.state) ); }, + telemetryBatteryHistory() { + return this.selectedPeerTelemetryItems + .filter((item) => item.lxmf_message.fields?.telemetry?.battery) + .map((item) => ({ + x: item.lxmf_message.timestamp, + y: item.lxmf_message.fields.telemetry.battery.charge_percent, + })) + .sort((a, b) => a.x - b.x); + }, + batterySparklinePath() { + const history = this.telemetryBatteryHistory; + if (history.length < 2) return ""; + + const minX = history[0].x; + const maxX = history[history.length - 1].x; + const rangeX = maxX - minX || 1; + + return history + .map((p, i) => { + const x = ((p.x - minX) / rangeX) * 100; + const y = 100 - p.y; // SVG y is top-down + return `${i === 0 ? "M" : "L"} ${x} ${y}`; + }) + .join(" "); + }, }, watch: { selectedPeer: { @@ -1695,6 +2042,26 @@ export default { }, 2000); }, methods: { + renderMarkdown(text) { + return MarkdownRenderer.render(text); + }, + handleMessageClick(event) { + const nomadnetLink = event.target.closest(".nomadnet-link"); + if (nomadnetLink) { + event.preventDefault(); + const url = nomadnetLink.getAttribute("data-nomadnet-url"); + if (url) { + const [hash, ...pathParts] = url.split(":"); + const path = pathParts.join(":"); + const routeName = this.$route.meta.isPopout ? "nomadnetwork-popout" : "nomadnetwork"; + this.$router.push({ + name: routeName, + params: { destinationHash: hash }, + query: { path: path }, + }); + } + } + }, async updatePropagationNodeStatus() { try { const response = await window.axios.get("/api/v1/lxmf/propagation-node/status"); @@ -2048,13 +2415,7 @@ export default { break; } case "lxm.ingest_uri.result": { - if (json.status === "success") { - ToastUtils.success(json.message); - } else if (json.status === "error") { - ToastUtils.error(json.message); - } else { - ToastUtils.warning(json.message); - } + // Handled in App.vue or MessagesPage.vue break; } } @@ -2661,6 +3022,7 @@ export default { fileAttachmentsTotalSize += file.size; fileAttachments.push({ file_name: file.name, + file_size: file.size, file_bytes: Utils.arrayBufferToBase64(await file.arrayBuffer()), }); } @@ -2675,6 +3037,7 @@ export default { imageTotalSize += image.size; images.push({ image_type: image.type.replace("image/", ""), + image_size: image.size, image_bytes: Utils.arrayBufferToBase64(await image.arrayBuffer()), name: image.name, }); @@ -2687,6 +3050,7 @@ export default { audioTotalSize = this.newMessageAudio.size; fields["audio"] = { audio_mode: this.newMessageAudio.audio_mode, + audio_size: this.newMessageAudio.size, audio_bytes: Utils.arrayBufferToBase64(await this.newMessageAudio.audio_blob.arrayBuffer()), }; } @@ -2882,27 +3246,59 @@ export default { } }, async shareLocation() { + const toastKey = "location_share"; try { + if (this.config?.location_source === "manual") { + const lat = parseFloat(this.config.location_manual_lat); + const lon = parseFloat(this.config.location_manual_lon); + const alt = parseFloat(this.config.location_manual_alt); + + if (isNaN(lat) || isNaN(lon)) { + ToastUtils.error("Invalid manual coordinates in settings", 5000, toastKey); + return; + } + + this.newMessageTelemetry = { + latitude: lat, + longitude: lon, + altitude: isNaN(alt) ? 0 : alt, + speed: 0, + bearing: 0, + accuracy: 0, + last_update: Math.floor(Date.now() / 1000), + }; + this.sendMessage(); + ToastUtils.success(this.$t("messages.location_sent"), 3000, toastKey); + return; + } + if (!navigator.geolocation) { DialogUtils.alert(this.$t("map.geolocation_not_supported")); return; } + ToastUtils.loading(this.$t("messages.fetching_location"), 0, toastKey); + navigator.geolocation.getCurrentPosition( (position) => { this.newMessageTelemetry = { latitude: position.coords.latitude, longitude: position.coords.longitude, altitude: position.coords.altitude || 0, - speed: (position.coords.speed || 0) * 3.6, // m/s to km/h to match Sideband + speed: (position.coords.speed || 0) * 3.6, // m/s to km/h bearing: position.coords.heading || 0, accuracy: position.coords.accuracy || 0, last_update: Math.floor(Date.now() / 1000), }; this.sendMessage(); + ToastUtils.success(this.$t("messages.location_sent"), 3000, toastKey); }, (error) => { - DialogUtils.alert(`Failed to get location: ${error.message}`); + ToastUtils.error( + `Failed to get location: ${error.message}. Try setting location manually in Settings.`, + 5000, + toastKey + ); }, { enableHighAccuracy: true, @@ -2912,6 +3308,7 @@ export default { ); } catch (e) { console.log(e); + ToastUtils.error(`Error: ${e.message}`, 5000, toastKey); } }, async requestLocation() { @@ -2924,9 +3321,7 @@ export default { destination_hash: this.selectedPeer.destination_hash, content: "", fields: { - commands: [ - { "0x01": Math.floor(Date.now() / 1000) }, // Sideband TELEMETRY_REQUEST - ], + commands: [{ "0x01": Math.floor(Date.now() / 1000) }], }, }, }); @@ -2948,6 +3343,32 @@ export default { }, }); }, + isTelemetryOnly(msg) { + const hasContent = msg.content && msg.content.trim() !== ""; + const hasAttachments = msg.fields?.image || msg.fields?.audio || msg.fields?.file_attachments; + const hasTelemetry = msg.fields?.telemetry || msg.fields?.telemetry_stream; + const hasCommands = msg.fields?.commands && msg.fields.commands.some((c) => c["0x01"]); + + return !hasContent && !hasAttachments && (hasTelemetry || hasCommands); + }, + async toggleTracking() { + if (!this.selectedPeer) return; + const hash = this.selectedPeer.destination_hash; + try { + const response = await window.axios.post(`/api/v1/telemetry/tracking/${hash}/toggle`, { + is_tracking: !this.selectedPeer.is_tracking, + }); + // Emit event to parent to update peer status + this.$emit("update-peer-tracking", { + destination_hash: hash, + is_tracking: response.data.is_tracking, + }); + ToastUtils.success(response.data.is_tracking ? "Live tracking enabled" : "Live tracking disabled"); + } catch (e) { + console.error("Failed to toggle tracking", e); + ToastUtils.error("Failed to update tracking status"); + } + }, formatTimeAgo: function (datetimeString) { return Utils.formatTimeAgo(datetimeString); }, @@ -3387,4 +3808,29 @@ export default { .dark .audio-controls-dark { filter: invert(1) hue-rotate(180deg); } +.markdown-content :deep(p) { + margin: 0.5rem 0; +} + +.markdown-content :deep(strong) { + font-weight: 700; +} + +.markdown-content :deep(em) { + font-style: italic; +} + +.markdown-content :deep(pre) { + margin: 0.75rem 0; +} + +.markdown-content :deep(code) { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + +.markdown-content :deep(h1), +.markdown-content :deep(h2), +.markdown-content :deep(h3) { + line-height: 1.2; +} diff --git a/meshchatx/src/frontend/components/messages/MessagesPage.vue b/meshchatx/src/frontend/components/messages/MessagesPage.vue index 466dcfd..954a038 100644 --- a/meshchatx/src/frontend/components/messages/MessagesPage.vue +++ b/meshchatx/src/frontend/components/messages/MessagesPage.vue @@ -50,6 +50,7 @@ :selected-peer="selectedPeer" :conversations="conversations" @update:selected-peer="onPeerClick" + @update-peer-tracking="onUpdatePeerTracking" @close="onCloseConversationViewer" @reload-conversations="getConversations" /> @@ -293,16 +294,21 @@ export default { await this.getConversations(); break; } + case "lxmf.telemetry": { + // update tracking status if peer matches + const destHash = json.destination_hash; + if (this.peers[destHash]) { + this.peers[destHash].is_tracking = json.is_tracking; + } + if (this.selectedPeer && this.selectedPeer.destination_hash === destHash) { + this.selectedPeer.is_tracking = json.is_tracking; + } + break; + } case "lxm.ingest_uri.result": { if (json.status === "success") { - ToastUtils.success(json.message); + this.ingestUri = ""; await this.getConversations(); - } else if (json.status === "error") { - ToastUtils.error(json.message); - } else if (json.status === "warning") { - ToastUtils.warning(json.message); - } else { - ToastUtils.info(json.message); } break; } @@ -398,6 +404,7 @@ export default { contact_image: conversation.contact_image ?? existingPeer.contact_image, lxmf_user_icon: conversation.lxmf_user_icon ?? existingPeer.lxmf_user_icon, updated_at: conversation.updated_at ?? existingPeer.updated_at, + is_tracking: conversation.is_tracking ?? existingPeer.is_tracking, }; } @@ -561,6 +568,14 @@ export default { const existing = this.peers[announce.destination_hash] || {}; this.peers[announce.destination_hash] = { ...existing, ...announce }; }, + onUpdatePeerTracking({ destination_hash, is_tracking }) { + if (this.peers[destination_hash]) { + this.peers[destination_hash].is_tracking = is_tracking; + } + if (this.selectedPeer && this.selectedPeer.destination_hash === destination_hash) { + this.selectedPeer.is_tracking = is_tracking; + } + }, onPeerClick: function (peer) { // update selected peer this.selectedPeer = peer; diff --git a/meshchatx/src/frontend/components/messages/MessagesSidebar.vue b/meshchatx/src/frontend/components/messages/MessagesSidebar.vue index 96f26de..c1699be 100644 --- a/meshchatx/src/frontend/components/messages/MessagesSidebar.vue +++ b/meshchatx/src/frontend/components/messages/MessagesSidebar.vue @@ -390,27 +390,37 @@
    {{ - conversation.latest_message_preview ?? - conversation.latest_message_title ?? - "No messages yet" + stripMarkdown( + conversation.latest_message_preview ?? conversation.latest_message_title + ) ?? "No messages yet" }}
    -
    -
    - +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    -
    -
    -
    -
    -
    -
    + +
    @@ -430,6 +440,31 @@ Mark as Read
    + +
    @@ -634,6 +669,8 @@ import DialogUtils from "../../js/DialogUtils"; import MaterialDesignIcon from "../MaterialDesignIcon.vue"; import LxmfUserIcon from "../LxmfUserIcon.vue"; import GlobalState from "../../js/GlobalState"; +import GlobalEmitter from "../../js/GlobalEmitter"; +import MarkdownRenderer from "../../js/MarkdownRenderer"; export default { name: "MessagesSidebar", @@ -749,6 +786,7 @@ export default { x: 0, y: 0, targetHash: null, + targetContact: null, }, draggedHash: null, dragOverFolderId: null, @@ -813,7 +851,35 @@ export default { } }, }, + mounted() { + // listen for contact updates + GlobalEmitter.on("contact-updated", this.onContactUpdated); + }, + unmounted() { + GlobalEmitter.off("contact-updated", this.onContactUpdated); + }, methods: { + onContactUpdated(data) { + // update local contact info if context menu is showing this peer + if (this.contextMenu.show && this.contextMenu.targetHash === data.remote_identity_hash) { + this.fetchContactForContextMenu(data.remote_identity_hash); + } + }, + async fetchContactForContextMenu(hash) { + try { + const response = await window.axios.get(`/api/v1/telephone/contacts/check/${hash}`); + if (response.data.is_contact) { + this.contextMenu.targetContact = response.data.contact; + } else { + this.contextMenu.targetContact = null; + } + } catch (e) { + console.error("Failed to fetch contact for context menu", e); + } + }, + stripMarkdown(text) { + return MarkdownRenderer.strip(text); + }, toggleSelectionMode() { this.selectionMode = !this.selectionMode; if (!this.selectionMode) { @@ -834,7 +900,7 @@ export default { this.selectedHashes.add(hash); } }, - onRightClick(event, hash) { + async onRightClick(event, hash) { event.preventDefault(); if (this.selectionMode && !this.selectedHashes.has(hash)) { this.selectedHashes.add(hash); @@ -843,6 +909,10 @@ export default { this.contextMenu.y = event.clientY; this.contextMenu.targetHash = hash; this.contextMenu.show = true; + this.contextMenu.targetContact = null; + + // fetch contact info for trust status + await this.fetchContactForContextMenu(hash); }, onFolderContextMenu(event) { event.preventDefault(); @@ -897,6 +967,38 @@ export default { this.$emit("delete-folder", folder.id); } }, + async toggleTelemetryTrust(hash) { + const contact = this.contextMenu.targetContact; + const newStatus = !contact?.is_telemetry_trusted; + try { + if (!contact) { + // find display name from conversations + const conv = this.conversations.find((c) => c.destination_hash === hash); + await window.axios.post("/api/v1/telephone/contacts", { + name: conv?.display_name || hash.substring(0, 8), + remote_identity_hash: hash, + is_telemetry_trusted: true, + }); + } else { + await window.axios.patch(`/api/v1/telephone/contacts/${contact.id}`, { + is_telemetry_trusted: newStatus, + }); + } + GlobalEmitter.emit("contact-updated", { + remote_identity_hash: hash, + is_telemetry_trusted: newStatus, + }); + this.contextMenu.show = false; + DialogUtils.alert( + newStatus + ? this.$t("app.telemetry_trust_granted_alert") + : this.$t("app.telemetry_trust_revoked_alert") + ); + } catch (e) { + DialogUtils.alert(this.$t("app.telemetry_trust_failed")); + console.error(e); + } + }, bulkMarkAsRead() { const hashes = this.selectionMode ? Array.from(this.selectedHashes) : [this.contextMenu.targetHash]; this.$emit("bulk-mark-as-read", hashes); diff --git a/meshchatx/src/frontend/components/messages/PaperMessageModal.vue b/meshchatx/src/frontend/components/messages/PaperMessageModal.vue index 7839bc4..9293762 100644 --- a/meshchatx/src/frontend/components/messages/PaperMessageModal.vue +++ b/meshchatx/src/frontend/components/messages/PaperMessageModal.vue @@ -277,38 +277,37 @@ export default { } }, async sendPaperMessage() { - const canvas = this.$refs.qrcode; - if (!canvas || !this.recipientHash || !this.uri) return; + if (!this.recipientHash || !this.uri) return; try { this.isSending = true; - // get data url from canvas (format: data:image/png;base64,iVBORw0KG...) - const dataUrl = canvas.toDataURL("image/png"); - - // extract base64 data by removing the prefix - const imageBytes = dataUrl.split(",")[1]; - // build lxmf message const lxmf_message = { destination_hash: this.recipientHash, - content: this.uri, - fields: { - image: { - image_type: "png", - image_bytes: imageBytes, - name: "qrcode.png", - }, - }, + content: `Please scan the attached Paper Message or manually ingest this URI: ${this.uri}`, + fields: {}, }; + // get data url from canvas if available + const canvas = this.$refs.qrcode; + if (canvas) { + const dataUrl = canvas.toDataURL("image/png"); + const imageBytes = dataUrl.split(",")[1]; + lxmf_message.fields.image = { + image_type: "png", + image_bytes: imageBytes, + name: "paper_message_qr.png", + }; + } + // send message const response = await window.axios.post(`/api/v1/lxmf-messages/send`, { delivery_method: "opportunistic", lxmf_message: lxmf_message, }); - if (response.data.status === "success") { + if (response.data.lxmf_message) { ToastUtils.success(this.$t("messages.paper_message_sent")); this.close(); } else { diff --git a/meshchatx/src/frontend/components/ping/PingPage.vue b/meshchatx/src/frontend/components/ping/PingPage.vue index 7f1cca3..da6d4e1 100644 --- a/meshchatx/src/frontend/components/ping/PingPage.vue +++ b/meshchatx/src/frontend/components/ping/PingPage.vue @@ -171,6 +171,14 @@ export default { beforeUnmount() { this.stop(); }, + mounted() { + if (this.$route.query.hash) { + this.destinationHash = this.$route.query.hash; + if (this.$route.query.autostart === "1" || this.$route.query.autostart === "true") { + this.start(); + } + } + }, methods: { async start() { // do nothing if already running diff --git a/meshchatx/src/frontend/components/rncp/RNCPPage.vue b/meshchatx/src/frontend/components/rncp/RNCPPage.vue index 21227b8..43532fe 100644 --- a/meshchatx/src/frontend/components/rncp/RNCPPage.vue +++ b/meshchatx/src/frontend/components/rncp/RNCPPage.vue @@ -28,14 +28,17 @@

    @@ -336,6 +339,7 @@ import DialogUtils from "../../js/DialogUtils"; import MaterialDesignIcon from "../MaterialDesignIcon.vue"; import WebSocketConnection from "../../js/WebSocketConnection"; +import MarkdownRenderer from "../../js/MarkdownRenderer"; export default { name: "RNCPPage", @@ -520,8 +524,23 @@ export default { this.listenResult = null; }, renderMarkdown(text) { - if (!text) return ""; - return text.replace(/\*\*(.*?)\*\*/g, "$1"); + return MarkdownRenderer.render(text); + }, + handleMessageClick(event) { + const nomadnetLink = event.target.closest(".nomadnet-link"); + if (nomadnetLink) { + event.preventDefault(); + const url = nomadnetLink.getAttribute("data-nomadnet-url"); + if (url) { + const [hash, ...pathParts] = url.split(":"); + const path = pathParts.join(":"); + this.$router.push({ + name: "nomadnetwork", + params: { destinationHash: hash }, + query: { path: path }, + }); + } + } }, }, }; diff --git a/meshchatx/src/frontend/components/settings/SettingsPage.vue b/meshchatx/src/frontend/components/settings/SettingsPage.vue index e3a0920..a95b4d7 100644 --- a/meshchatx/src/frontend/components/settings/SettingsPage.vue +++ b/meshchatx/src/frontend/components/settings/SettingsPage.vue @@ -106,7 +106,7 @@ +
    +
    +
    +
    + +
    English +
    @@ -959,6 +1119,98 @@
    + +
    +
    +
    +
    Security
    +

    {{ $t("app.csp_settings") }}

    +

    {{ $t("app.csp_description") }}

    +
    +
    +
    +
    +
    + {{ $t("app.csp_extra_connect_src") }} +
    + +
    + {{ $t("app.csp_extra_connect_src_description") }} +
    +
    + +
    +
    + {{ $t("app.csp_extra_img_src") }} +
    + +
    + {{ $t("app.csp_extra_img_src_description") }} +
    +
    + +
    +
    + {{ $t("app.csp_extra_frame_src") }} +
    + +
    + {{ $t("app.csp_extra_frame_src_description") }} +
    +
    + +
    +
    + {{ $t("app.csp_extra_script_src") }} +
    + +
    + {{ $t("app.csp_extra_script_src_description") }} +
    +
    + +
    +
    + {{ $t("app.csp_extra_style_src") }} +
    + +
    + {{ $t("app.csp_extra_style_src_description") }} +
    +
    +
    +
    +
    @@ -1256,13 +1508,24 @@ export default { message_icon_size: 28, telephone_tone_generator_enabled: true, telephone_tone_generator_volume: 50, + location_source: "browser", + location_manual_lat: "0.0", + location_manual_lon: "0.0", + location_manual_alt: "0.0", + telemetry_enabled: false, gitea_base_url: "https://git.quad4.io", docs_download_urls: "", + csp_extra_connect_src: "", + csp_extra_img_src: "", + csp_extra_frame_src: "", + csp_extra_script_src: "", + csp_extra_style_src: "", }, saveTimeouts: {}, shortcuts: [], reloadingRns: false, searchQuery: "", + trustedTelemetryPeers: [], sectionKeywords: { banishment: [ "Visuals", @@ -1305,6 +1568,18 @@ export default { ], archiver: ["Browsing", "Page Archiver", "archiver", "archive", "versions", "storage", "flush"], crawler: ["Discovery", "Smart Crawler", "crawler", "crawl", "retries", "delay", "concurrent"], + csp: [ + "Security", + "app.csp_settings", + "app.csp_description", + "app.csp_extra_connect_src", + "app.csp_extra_img_src", + "app.csp_extra_frame_src", + "app.csp_extra_script_src", + "app.csp_extra_style_src", + "CSP", + "Content Security Policy", + ], appearance: [ "Personalise", "app.appearance", @@ -1374,6 +1649,17 @@ export default { "app.propagation_stamp_cost", "app.propagation_stamp_description", ], + location: [ + "Location", + "GPS", + "Privacy", + "manual", + "latitude", + "longitude", + "altitude", + "telemetry", + "trusted peers", + ], shortcuts: ["Keyboard Shortcuts", "actions", "workflow"], }, }; @@ -1391,6 +1677,10 @@ export default { lxmf_address_hash: "", theme: "dark", is_transport_enabled: false, + location_source: "browser", + location_manual_lat: "0.0", + location_manual_lon: "0.0", + location_manual_alt: "0.0", }; } return this.config; @@ -1419,8 +1709,29 @@ export default { WebSocketConnection.on("message", this.onWebsocketMessage); this.getConfig(); + this.getTrustedTelemetryPeers(); }, methods: { + async getTrustedTelemetryPeers() { + try { + const response = await window.axios.get("/api/v1/telemetry/trusted-peers"); + this.trustedTelemetryPeers = response.data.trusted_peers; + } catch (e) { + console.error("Failed to fetch trusted telemetry peers", e); + } + }, + async revokeTelemetryTrust(peer) { + try { + await window.axios.patch(`/api/v1/telephone/contacts/${peer.id}`, { + is_telemetry_trusted: false, + }); + this.getTrustedTelemetryPeers(); + ToastUtils.success(this.$t("app.telemetry_trust_revoked", { name: peer.name })); + } catch (e) { + ToastUtils.error("Failed to revoke telemetry trust"); + console.error(e); + } + }, matchesSearch(...texts) { if (!this.searchQuery) return true; const query = this.searchQuery.toLowerCase(); @@ -1787,6 +2098,21 @@ export default { ); }, 1000); }, + async onCspConfigChange() { + if (this.saveTimeouts.csp) clearTimeout(this.saveTimeouts.csp); + this.saveTimeouts.csp = setTimeout(async () => { + await this.updateConfig( + { + csp_extra_connect_src: this.config.csp_extra_connect_src, + csp_extra_img_src: this.config.csp_extra_img_src, + csp_extra_frame_src: this.config.csp_extra_frame_src, + csp_extra_script_src: this.config.csp_extra_script_src, + csp_extra_style_src: this.config.csp_extra_style_src, + }, + "csp_settings" + ); + }, 1000); + }, async onBackupConfigChange() { if (this.saveTimeouts.backup) clearTimeout(this.saveTimeouts.backup); this.saveTimeouts.backup = setTimeout(async () => { diff --git a/meshchatx/src/frontend/components/tools/PaperMessagePage.vue b/meshchatx/src/frontend/components/tools/PaperMessagePage.vue index b0c8230..c10b15a 100644 --- a/meshchatx/src/frontend/components/tools/PaperMessagePage.vue +++ b/meshchatx/src/frontend/components/tools/PaperMessagePage.vue @@ -267,12 +267,7 @@ export default { } } else if (json.type === "lxm.ingest_uri.result") { if (json.status === "success") { - ToastUtils.success(json.message); this.ingestUri = ""; - } else if (json.status === "error") { - ToastUtils.error(json.message); - } else { - ToastUtils.warning(json.message); } } }, @@ -384,7 +379,7 @@ export default { lxmf_message: lxmf_message, }); - if (response.data.status === "success") { + if (response.data.lxmf_message) { ToastUtils.success(this.$t("messages.paper_message_sent")); this.generatedUri = null; this.destinationHash = ""; diff --git a/meshchatx/src/frontend/components/tools/RNPathTracePage.vue b/meshchatx/src/frontend/components/tools/RNPathTracePage.vue new file mode 100644 index 0000000..78fdf80 --- /dev/null +++ b/meshchatx/src/frontend/components/tools/RNPathTracePage.vue @@ -0,0 +1,377 @@ + + + + + diff --git a/meshchatx/src/frontend/components/tools/ToolsPage.vue b/meshchatx/src/frontend/components/tools/ToolsPage.vue index d2fd529..6f0bfe7 100644 --- a/meshchatx/src/frontend/components/tools/ToolsPage.vue +++ b/meshchatx/src/frontend/components/tools/ToolsPage.vue @@ -4,30 +4,41 @@ >
    -
    -
    - {{ $t("tools.utilities") }} +
    +
    +
    + {{ $t("tools.utilities") }} +
    +
    + {{ $t("tools.power_tools") }} +
    +
    + {{ $t("tools.diagnostics_description") }} +
    -
    - {{ $t("tools.power_tools") }} -
    -
    - {{ $t("tools.diagnostics_description") }} -
    -
    -
    -
    - - +
    +
    +
    + +
    + + +
    @@ -147,6 +158,14 @@ export default { titleKey: "tools.rnpath.title", descriptionKey: "tools.rnpath.description", }, + { + name: "rnpath-trace", + route: { name: "rnpath-trace" }, + icon: "map-marker-path", + iconBg: "tool-card__icon bg-blue-50 text-blue-500 dark:bg-blue-900/30 dark:text-blue-200", + titleKey: "tools.rnpath_trace.title", + descriptionKey: "tools.rnpath_trace.description", + }, { name: "translator", route: { name: "translator" }, From 55f718c72b76013892822692b66d45cff10b71ea Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Wed, 7 Jan 2026 19:13:35 -0600 Subject: [PATCH 201/234] feat(frontend): enhance link rendering and markdown processing - Added LinkUtils for detecting and rendering NomadNet and standard links in text. - Introduced MarkdownRenderer for converting Markdown to HTML, including support for code blocks, headers, and inline formatting. - Implemented escapeHtml utility function to prevent XSS in rendered text. - Updated ToastUtils to support an optional key parameter for toast notifications. - Included Italian language support in the frontend localization. --- electron/main.js | 4 +- meshchatx/src/frontend/js/LinkUtils.js | 41 +++++++ meshchatx/src/frontend/js/MarkdownRenderer.js | 101 ++++++++++++++++++ meshchatx/src/frontend/js/ToastUtils.js | 24 +++-- meshchatx/src/frontend/js/Utils.js | 14 +++ meshchatx/src/frontend/main.js | 7 ++ 6 files changed, 179 insertions(+), 12 deletions(-) create mode 100644 meshchatx/src/frontend/js/LinkUtils.js create mode 100644 meshchatx/src/frontend/js/MarkdownRenderer.js diff --git a/electron/main.js b/electron/main.js index 4cdd531..59b8cc3 100644 --- a/electron/main.js +++ b/electron/main.js @@ -348,9 +348,9 @@ app.whenReady().then(async () => { "default-src 'self'", "script-src 'self' 'unsafe-inline' 'unsafe-eval'", "style-src 'self' 'unsafe-inline'", - "img-src 'self' data: blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org", + "img-src 'self' data: blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://*.cartocdn.com", "font-src 'self' data:", - "connect-src 'self' http://localhost:9337 https://localhost:9337 ws://localhost:* wss://localhost:* blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://nominatim.openstreetmap.org https://git.quad4.io", + "connect-src 'self' http://localhost:9337 https://localhost:9337 ws://localhost:* wss://localhost:* blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://nominatim.openstreetmap.org https://git.quad4.io https://*.cartocdn.com", "media-src 'self' blob:", "worker-src 'self' blob:", "frame-src 'self'", diff --git a/meshchatx/src/frontend/js/LinkUtils.js b/meshchatx/src/frontend/js/LinkUtils.js new file mode 100644 index 0000000..c19a80c --- /dev/null +++ b/meshchatx/src/frontend/js/LinkUtils.js @@ -0,0 +1,41 @@ +export default class LinkUtils { + /** + * Detects and wraps NomadNet links in HTML. + * Supports nomadnet://:/path and :/path + */ + static renderNomadNetLinks(text) { + if (!text) return ""; + + // Hash is 32 hex chars. Path is optional. + const hashPattern = "[a-fA-F0-9]{32}"; + const nomadnetRegex = new RegExp(`(?:nomadnet://)?(${hashPattern})(?::(/[\\w\\d./?%&=-]*))?`, "g"); + + return text.replace(nomadnetRegex, (match, hash, path) => { + const fullPath = path || "/page/index.mu"; + const url = `${hash}:${fullPath}`; + return `${match}`; + }); + } + + /** + * Basic URL detection for standard http/https links. + */ + static renderStandardLinks(text) { + if (!text) return ""; + + // Simple regex for URLs + const urlRegex = /(https?:\/\/[^\s<]+)/g; + return text.replace(urlRegex, (url) => { + return `${url}`; + }); + } + + /** + * Applies all link rendering. + */ + static renderAllLinks(text) { + text = this.renderStandardLinks(text); + text = this.renderNomadNetLinks(text); + return text; + } +} diff --git a/meshchatx/src/frontend/js/MarkdownRenderer.js b/meshchatx/src/frontend/js/MarkdownRenderer.js new file mode 100644 index 0000000..8da04b8 --- /dev/null +++ b/meshchatx/src/frontend/js/MarkdownRenderer.js @@ -0,0 +1,101 @@ +import Utils from "./Utils"; +import LinkUtils from "./LinkUtils"; + +export default class MarkdownRenderer { + /** + * A simple Markdown to HTML renderer, cause we dont need another library for this. + * Ported and simplified from meshchatx/src/backend/markdown_renderer.py + */ + static render(text) { + if (!text) { + return ""; + } + + // Escape HTML entities first to prevent XSS + text = Utils.escapeHtml(text); + + // Fenced code blocks - process these FIRST and replace with placeholders + const code_blocks = []; + text = text.replace(/```(\w+)?\n([\s\S]*?)\n```/g, (match, lang, code) => { + const placeholder = `[[CB${code_blocks.length}]]`; + code_blocks.push( + `
    ${code}
    ` + ); + return placeholder; + }); + + // Headers + text = text.replace(/^# (.*)$/gm, '

    $1

    '); + text = text.replace(/^## (.*)$/gm, '

    $1

    '); + text = text.replace(/^### (.*)$/gm, '

    $1

    '); + + // Bold and Italic + text = text.replace(/\*\*\*(.*?)\*\*\*/g, "$1"); + text = text.replace(/\*\*(.*?)\*\*/g, "$1"); + text = text.replace(/\*(.*?)\*/g, "$1"); + text = text.replace(/___(.*?)___/g, "$1"); + text = text.replace(/__(.*?)__/g, "$1"); + text = text.replace(/_(.*?)_/g, "$1"); + + // Inline code + text = text.replace( + /`([^`]+)`/g, + '$1' + ); + + // Links + text = LinkUtils.renderAllLinks(text); + + // Restore code blocks + for (let i = 0; i < code_blocks.length; i++) { + text = text.replace(`[[CB${i}]]`, code_blocks[i]); + } + + // Paragraphs - double newline to p tag + const parts = text.split(/\n\n+/); + const processed_parts = []; + for (let part of parts) { + part = part.trim(); + if (!part) continue; + + // If it's a placeholder for code block, don't wrap in

    + if (part.startsWith(" for line breaks within paragraphs + part = part.replace(/\n/g, "
    "); + processed_parts.push(`

    ${part}

    `); + } + } + + return processed_parts.join("\n"); + } + + /** + * Strips markdown from text for previews. + */ + static strip(text) { + if (!text) { + return ""; + } + + // Strip fenced code blocks + text = text.replace(/```(\w+)?\n([\s\S]*?)\n```/g, "[Code Block]"); + + // Strip headers + text = text.replace(/^#+ (.*)$/gm, "$1"); + + // Strip bold and italic + text = text.replace(/\*\*\*(.*?)\*\*\*/g, "$1"); + text = text.replace(/\*\*(.*?)\*\*/g, "$1"); + text = text.replace(/\*(.*?)\*/g, "$1"); + text = text.replace(/___(.*?)___/g, "$1"); + text = text.replace(/__(.*?)__/g, "$1"); + text = text.replace(/_(.*?)_/g, "$1"); + + // Strip inline code + text = text.replace(/`([^`]+)`/g, "$1"); + + return text; + } +} diff --git a/meshchatx/src/frontend/js/ToastUtils.js b/meshchatx/src/frontend/js/ToastUtils.js index 600fb32..ca328d0 100644 --- a/meshchatx/src/frontend/js/ToastUtils.js +++ b/meshchatx/src/frontend/js/ToastUtils.js @@ -1,24 +1,28 @@ import GlobalEmitter from "./GlobalEmitter"; class ToastUtils { - static show(message, type = "info", duration = 5000) { - GlobalEmitter.emit("toast", { message, type, duration }); + static show(message, type = "info", duration = 5000, key = null) { + GlobalEmitter.emit("toast", { message, type, duration, key }); } - static success(message, duration = 5000) { - this.show(message, "success", duration); + static success(message, duration = 5000, key = null) { + this.show(message, "success", duration, key); } - static error(message, duration = 5000) { - this.show(message, "error", duration); + static error(message, duration = 5000, key = null) { + this.show(message, "error", duration, key); } - static warning(message, duration = 5000) { - this.show(message, "warning", duration); + static warning(message, duration = 5000, key = null) { + this.show(message, "warning", duration, key); } - static info(message, duration = 5000) { - this.show(message, "info", duration); + static info(message, duration = 5000, key = null) { + this.show(message, "info", duration, key); + } + + static loading(message, duration = 0, key = null) { + this.show(message, "loading", duration, key); } } diff --git a/meshchatx/src/frontend/js/Utils.js b/meshchatx/src/frontend/js/Utils.js index 125939b..9dfb99c 100644 --- a/meshchatx/src/frontend/js/Utils.js +++ b/meshchatx/src/frontend/js/Utils.js @@ -183,6 +183,20 @@ class Utils { const value = rawValue?.toString()?.toLowerCase(); return value === "on" || value === "yes" || value === "true"; } + + static escapeHtml(text) { + if (!text) return ""; + const map = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + }; + return text.replace(/[&<>"']/g, function (m) { + return map[m]; + }); + } } export default Utils; diff --git a/meshchatx/src/frontend/main.js b/meshchatx/src/frontend/main.js index b4dcf8c..9e60072 100644 --- a/meshchatx/src/frontend/main.js +++ b/meshchatx/src/frontend/main.js @@ -12,6 +12,7 @@ import App from "./components/App.vue"; import en from "./locales/en.json"; import de from "./locales/de.json"; import ru from "./locales/ru.json"; +import it from "./locales/it.json"; // init i18n const i18n = createI18n({ @@ -22,6 +23,7 @@ const i18n = createI18n({ en, de, ru, + it, }, }); @@ -179,6 +181,11 @@ const router = createRouter({ path: "/rnpath", component: defineAsyncComponent(() => import("./components/tools/RNPathPage.vue")), }, + { + name: "rnpath-trace", + path: "/rnpath-trace", + component: defineAsyncComponent(() => import("./components/tools/RNPathTracePage.vue")), + }, { name: "rnprobe", path: "/rnprobe", From d8af5509b9d95ef45b0a29763d57d1a0a8c55ce0 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Wed, 7 Jan 2026 19:13:48 -0600 Subject: [PATCH 202/234] feat(locales): update German and Russian translations, add Italian localization - Enhanced German and Russian JSON files with new entries for telemetry, location management, and content security policy settings. - Added Italian localization file with comprehensive translations for the application, covering various features and settings. - Improved user experience by ensuring consistent terminology across all supported languages. --- meshchatx/src/frontend/locales/de.json | 78 +- meshchatx/src/frontend/locales/en.json | 66 +- meshchatx/src/frontend/locales/it.json | 1503 ++++++++++++++++++++++++ meshchatx/src/frontend/locales/ru.json | 78 +- 4 files changed, 1695 insertions(+), 30 deletions(-) create mode 100644 meshchatx/src/frontend/locales/it.json diff --git a/meshchatx/src/frontend/locales/de.json b/meshchatx/src/frontend/locales/de.json index 1ad9e3e..5997a6a 100644 --- a/meshchatx/src/frontend/locales/de.json +++ b/meshchatx/src/frontend/locales/de.json @@ -194,9 +194,42 @@ "emergency_mode_active": "Notfallmodus aktiv - In-Memory-Datenbank und eingeschränkte Dienste werden verwendet.", "blackhole_integration_enabled": "Blackhole-Integration", "blackhole_integration_description": "Identitäten automatisch auf der Reticulum-Transportebene sperren (Blackhole), wenn Benutzer in MeshChatX verbannt werden.", - "failed_announce": "failed to announce", - "search_settings": "Search settings...", - "show_qr": "Show QR Code" + "failed_announce": "Ankündigung fehlgeschlagen", + "search_settings": "Einstellungen suchen...", + "show_qr": "QR-Code anzeigen", + "csp_settings": "Content-Security-Policy (CSP)", + "csp_description": "Fügen Sie manuell erlaubte Domains und Quellen für verschiedene Ressourcentypen hinzu. Dies ist nützlich für benutzerdefinierte Kachelserver, Bots oder externe Integrationen.", + "csp_extra_connect_src": "Zusätzliche Connect-Quellen", + "csp_extra_connect_src_description": "Zusätzliche Quellen für fetch/Websocket-Verbindungen (z. B. https://api.example.com).", + "csp_extra_img_src": "Zusätzliche Bildquellen", + "csp_extra_img_src_description": "Zusätzliche Quellen für Bilder und Kacheln.", + "csp_extra_frame_src": "Zusätzliche Frame-Quellen", + "csp_extra_frame_src_description": "Zusätzliche Quellen für Iframes.", + "csp_extra_script_src": "Zusätzliche Skriptquellen", + "csp_extra_script_src_description": "Zusätzliche Quellen für Skripte (nur für fortgeschrittene Benutzer).", + "csp_extra_style_src": "Zusätzliche Style-Quellen", + "csp_extra_style_src_description": "Zusätzliche Quellen für Stylesheets.", + "location": "Standort", + "location_source": "Standortquelle", + "location_source_browser": "Automatisch (Browser)", + "location_source_manual": "Manuell", + "location_source_browser_desc": "Verwendet die Geolocation-API Ihres Browsers. Hinweis: In der Desktop-App kann dies Google-Dienste nutzen.", + "location_source_manual_desc": "Verwenden Sie manuell eingegebene Koordinaten für maximale Privatsphäre.", + "location_manual_lat": "Breitengrad", + "location_manual_lon": "Längengrad", + "location_manual_alt": "Höhe (m)", + "telemetry_enabled": "Telemetrie aktiviert", + "telemetry_description": "Erlauben Sie MeshChatX das Senden und Empfangen von Telemetriedaten. Dies beinhaltet die Beantwortung von Standortanfragen von vertrauenswürdigen Peers.", + "telemetry_trusted_peers": "Vertrauenswürdige Telemetrie-Peers", + "telemetry_no_trusted_peers": "Keine vertrauenswürdigen Peers konfiguriert. Vertrauen Sie Peers aus dem Chat-Menü, um ihnen zu erlauben, Ihren Standort abzufragen.", + "telemetry_revoke_trust": "Vertrauen entziehen", + "telemetry_trust_revoked": "Telemetrie-Vertrauen für {name} entzogen", + "telemetry_trust_granted_alert": "Peer ist nun für Telemetrie vertrauenswürdig.", + "telemetry_trust_revoked_alert": "Telemetrie-Vertrauen entzogen.", + "telemetry_trust_failed": "Fehler beim Aktualisieren des Telemetrie-Vertrauens.", + "telemetry_trust_revoke": "Telemetrie-Vertrauen entziehen", + "telemetry_trust_grant": "Für Telemetrie vertrauen", + "location_manage_desc": "Verwalten Sie, wie Ihr Standort geteilt wird." }, "common": { "open": "Öffnen", @@ -362,6 +395,7 @@ "export_all": "Alle exportieren", "search_placeholder": "Suche nach Name, Typ, Host...", "all": "Alle", + "connected_only": "Nur verbundene", "all_types": "Alle Typen", "no_interfaces_found": "Keine Schnittstellen gefunden", "no_interfaces_description": "Passen Sie Ihre Suche an oder fügen Sie eine neue Schnittstelle hinzu.", @@ -572,7 +606,10 @@ "no_contacts_telephone": "No contacts found in telephone", "failed_load_contacts": "Failed to load contacts", "location_request_sent": "Location request sent", - "failed_send_location_request": "Failed to send location request", + "failed_send_location_request": "Senden der Standortanfrage fehlgeschlagen", + "fetching_location": "Standort wird abgerufen...", + "location_sent": "Standort erfolgreich geteilt", + "location_requested": "Standort angefordert", "remove_image_confirm": "Are you sure you want to remove this image attachment?", "failed_start_recording": "failed to start recording", "remove_audio_confirm": "Are you sure you want to remove this audio attachment?", @@ -740,6 +777,21 @@ "queues_purged": "Announce queues purged", "failed_purge": "Failed to purge queues" }, + "rnpath_trace": { + "title": "RNS Pfad-Verfolgung", + "description": "Visualisiere den Pfad und die Hops zu einem Ziel-Hash im Mesh.", + "destination_hash": "Ziel-Hash", + "placeholder": "32-stelligen Ziel-Hash eingeben...", + "trace": "Pfad verfolgen", + "tracing": "Verfolge Pfad durch das Mesh...", + "total_hops": "Gesamt Hops", + "interface": "Ausgangs-Schnittstelle", + "next_hop": "Nächster Hop", + "ready_title": "Einen Pfad verfolgen", + "ready_desc": "Gib oben einen Ziel-Hash ein, um zu visualisieren, wie Pakete durch das Mesh reisen.", + "unknown_hops": "{count} Zwischen-Hops", + "ping_test": "Mit Ping testen" + }, "translator": { "title": "Übersetzer", "description": "Text mit der LibreTranslate API oder lokalem Argos Translate übersetzen." @@ -897,15 +949,15 @@ "description": "Erstellen und lesen Sie LXMF-signierte Papiernachrichten über QR-Codes." }, "rns_page_node": { - "title": "RNS Page-Knoten", + "title": "RNS Page Node", "description": "Nomadnet-Micron-Seiten hosten und Dateien mühelos teilen." }, "rns_tunnel": { - "title": "RNS-Tunnel", + "title": "RNSTunnel", "description": "Regulären IP-Verkehr über Reticulum-Netzwerkverbindungen tunneln." }, "rns_filesync": { - "title": "RNS-Dateisynchronisierung", + "title": "RNSFilesync", "description": "Dateien effizient mit anderen Mesh-Peers teilen und synchronisieren." }, "bots": { @@ -1328,14 +1380,16 @@ "nav_settings_desc": "Einstellungsseite öffnen", "nav_ping": "Ping", "nav_ping_desc": "Netzwerkknoten pingen", - "nav_rnprobe": "RN Probe", + "nav_rnprobe": "RNProbe", "nav_rnprobe_desc": "Reticulum-Knoten sondieren", - "nav_rncp": "RN CP", + "nav_rncp": "RNCP", "nav_rncp_desc": "Reticulum Control Protocol", - "nav_rnstatus": "RN Status", + "nav_rnstatus": "RNStatus", "nav_rnstatus_desc": "Reticulum-Status anzeigen", - "nav_rnpath": "RN Pfad", + "nav_rnpath": "RNPath", "nav_rnpath_desc": "Netzwerkpfade anzeigen", + "nav_rnpath_trace": "RNPath-Verfolgung", + "nav_rnpath_trace_desc": "Netzwerkpfade visualisieren", "nav_translator": "Übersetzer", "nav_translator_desc": "Nachrichten übersetzen", "nav_forwarder": "Weiterleiter", @@ -1450,4 +1504,4 @@ "banishment_lifted": "Banishment lifted successfully", "failed_lift_banishment": "Failed to lift banishment" } -} \ No newline at end of file +} diff --git a/meshchatx/src/frontend/locales/en.json b/meshchatx/src/frontend/locales/en.json index fa5ba68..4ffb4bc 100644 --- a/meshchatx/src/frontend/locales/en.json +++ b/meshchatx/src/frontend/locales/en.json @@ -196,7 +196,40 @@ "loading_identity": "Loading your identity", "emergency_mode_active": "Emergency Mode Active - Using in-memory database and restricted services.", "blackhole_integration_enabled": "Blackhole Integration", - "blackhole_integration_description": "Automatically blackhole identities at the Reticulum transport layer when banishing users in MeshChatX." + "blackhole_integration_description": "Automatically blackhole identities at the Reticulum transport layer when banishing users in MeshChatX.", + "csp_settings": "Content Security Policy (CSP)", + "csp_description": "Manually add allowed domains and sources for various resource types. This is useful for custom tile servers, bots, or external integrations.", + "csp_extra_connect_src": "Extra Connect Sources", + "csp_extra_connect_src_description": "Additional sources for fetch/websocket connections (e.g. https://api.example.com).", + "csp_extra_img_src": "Extra Image Sources", + "csp_extra_img_src_description": "Additional sources for images and tiles.", + "csp_extra_frame_src": "Extra Frame Sources", + "csp_extra_frame_src_description": "Additional sources for iframes.", + "csp_extra_script_src": "Extra Script Sources", + "csp_extra_script_src_description": "Additional sources for scripts (advanced use only).", + "csp_extra_style_src": "Extra Style Sources", + "csp_extra_style_src_description": "Additional sources for stylesheets.", + "location": "Location", + "location_source": "Location Source", + "location_source_browser": "Automatic (Browser)", + "location_source_manual": "Manual", + "location_source_browser_desc": "Uses your browser's geolocation API. Note: In the desktop app, this may use Google services.", + "location_source_manual_desc": "Use manually entered coordinates for maximum privacy.", + "location_manual_lat": "Latitude", + "location_manual_lon": "Longitude", + "location_manual_alt": "Altitude (m)", + "telemetry_enabled": "Telemetry Enabled", + "telemetry_description": "Allow MeshChatX to send and receive telemetry data. This includes responding to location requests from trusted peers.", + "telemetry_trusted_peers": "Trusted Telemetry Peers", + "telemetry_no_trusted_peers": "No trusted peers configured. Trust peers from the chat menu to allow them to request your location.", + "telemetry_revoke_trust": "Revoke Trust", + "telemetry_trust_revoked": "Revoked telemetry trust for {name}", + "telemetry_trust_granted_alert": "Peer is now trusted for telemetry.", + "telemetry_trust_revoked_alert": "Telemetry trust revoked.", + "telemetry_trust_failed": "Failed to update telemetry trust.", + "telemetry_trust_revoke": "Revoke Telemetry Trust", + "telemetry_trust_grant": "Trust for Telemetry", + "location_manage_desc": "Manage how your location is shared." }, "common": { "open": "Open", @@ -362,6 +395,7 @@ "export_all": "Export all", "search_placeholder": "Search by name, type, host...", "all": "All", + "connected_only": "Connected only", "all_types": "All types", "no_interfaces_found": "No interfaces found", "no_interfaces_description": "Adjust your search or add a new interface.", @@ -575,6 +609,9 @@ "failed_load_contacts": "Failed to load contacts", "location_request_sent": "Location request sent", "failed_send_location_request": "Failed to send location request", + "fetching_location": "Fetching location...", + "location_sent": "Location shared successfully", + "location_requested": "Location requested", "remove_image_confirm": "Are you sure you want to remove this image attachment?", "failed_start_recording": "failed to start recording", "remove_audio_confirm": "Are you sure you want to remove this audio attachment?", @@ -829,6 +866,21 @@ "queues_purged": "Announce queues purged", "failed_purge": "Failed to purge queues" }, + "rnpath_trace": { + "title": "RNS Path Trace", + "description": "Visualize the path and hops to any destination hash on the mesh.", + "destination_hash": "Destination Hash", + "placeholder": "Enter 32-char destination hash...", + "trace": "Trace Path", + "tracing": "Tracing path through the mesh...", + "total_hops": "Total Hops", + "interface": "Exit Interface", + "next_hop": "Next Hop", + "ready_title": "Trace a Path", + "ready_desc": "Enter a destination hash above to visualize how packets travel through the mesh to reach it.", + "unknown_hops": "{count} Intermediate Hops", + "ping_test": "Test with Ping" + }, "translator": { "title": "Translator", "description": "Translate text using LibreTranslate API or local Argos Translate." @@ -1417,14 +1469,16 @@ "nav_settings_desc": "Open settings page", "nav_ping": "Ping", "nav_ping_desc": "Ping network nodes", - "nav_rnprobe": "RN Probe", + "nav_rnprobe": "RNProbe", "nav_rnprobe_desc": "Probe Reticulum nodes", - "nav_rncp": "RN CP", + "nav_rncp": "RNCP", "nav_rncp_desc": "Reticulum Control Protocol", - "nav_rnstatus": "RN Status", + "nav_rnstatus": "RNStatus", "nav_rnstatus_desc": "View Reticulum status", - "nav_rnpath": "RN Path", + "nav_rnpath": "RNPath", "nav_rnpath_desc": "View network paths", + "nav_rnpath_trace": "RNPath Trace", + "nav_rnpath_trace_desc": "Visualize network paths", "nav_translator": "Translator", "nav_translator_desc": "Translate messages", "nav_forwarder": "Forwarder", @@ -1450,4 +1504,4 @@ "action_changelog": "Changelog", "action_changelog_desc": "View what's new" } -} \ No newline at end of file +} diff --git a/meshchatx/src/frontend/locales/it.json b/meshchatx/src/frontend/locales/it.json new file mode 100644 index 0000000..0023723 --- /dev/null +++ b/meshchatx/src/frontend/locales/it.json @@ -0,0 +1,1503 @@ +{ + "bots": { + "title": "LXMFy Bot", + "description": "Gestisci bot automatizzati per echo, note e promemoria usando LXMFy.", + "bot_framework": "Bot Framework", + "lxmfy_not_detected": "LXMFy non rilevato", + "lxmfy_not_detected_desc": "Per usare i bot, devi installare il pacchetto LXMFy:", + "install_via_pip": "Installa via pip", + "create_new_bot": "Crea Nuovo Bot", + "running_bots": "Bot in Esecuzione", + "no_bots_running": "Nessun bot è attualmente in esecuzione.", + "select": "Seleziona", + "start_bot": "Avvia Bot", + "stop_bot": "Ferma Bot", + "restart_bot": "Riavvia Bot", + "saved_bots": "Bot Salvati", + "bot_name": "Nome Bot", + "cancel": "Annulla", + "bot_started": "Bot avviato con successo", + "bot_stopped": "Bot fermato", + "failed_to_start": "Impossibile avviare il bot", + "failed_to_stop": "Impossibile fermare il bot", + "delete_bot": "Elimina Bot", + "export_identity": "Esporta Identità", + "bot_deleted": "Bot eliminato con successo", + "failed_to_delete": "Impossibile eliminare il bot", + "more_bots_coming": "Altri bot in arrivo!" + }, + "app": { + "name": "Reticulum MeshChatX", + "sync_messages": "Sincronizza Messaggi", + "compose": "Componi", + "messages": "Messaggi", + "nomad_network": "Nomad Network", + "map": "Mappa", + "archives": "Archivi", + "propagation_nodes": "Nodi di Propagazione", + "network_visualiser": "Visualizzatore di Rete", + "interfaces": "Interfacce", + "tools": "Strumenti", + "settings": "Impostazioni", + "identities": "Identità", + "documentation": "Documentazione", + "about": "Informazioni", + "changelog_title": "Novità", + "do_not_show_again": "Non mostrare più per questa versione", + "do_not_show_ever": "Non mostrare mai più", + "tutorial_title": "Guida Introduttiva", + "tutorial_welcome": "Benvenuto in MeshChatX", + "tutorial_connect": "Connettiti alla Mesh", + "tutorial_finish": "Pronto per Iniziare!", + "tutorial_restart_required": "Riavvio Richiesto", + "tutorial_docker_note": "Se stai usando Docker, assicurati di riavviare il container.", + "my_identity": "La Mia Identità", + "identity_hash": "Hash Identità", + "lxmf_address": "Indirizzo LXMF", + "announce": "Annuncia", + "announce_now": "Annuncia Ora", + "show_qr": "Mostra Codice QR", + "failed_announce": "impossibile annunciare", + "last_announced": "Ultimo annuncio: {time}", + "last_announced_never": "Ultimo annuncio: Mai", + "display_name_placeholder": "Nome Visualizzato", + "profile": "Profilo", + "manage_identity": "Gestisci la tua identità, la partecipazione al trasporto e i predefiniti LXMF.", + "theme": "Tema", + "theme_mode": "Modalità {mode}", + "transport": "Trasporto", + "enabled": "Abilitato", + "disabled": "Disabilitato", + "propagation": "Propagazione", + "local_node_running": "Nodo locale in esecuzione", + "client_only": "Solo client", + "copy": "Copia", + "appearance": "Aspetto", + "appearance_description": "Passa tra i temi chiaro e scuro in qualsiasi momento.", + "light_theme": "Tema Chiaro", + "dark_theme": "Tema Scuro", + "live_preview": "L'anteprima si aggiorna istantaneamente.", + "realtime": "Tempo Reale", + "transport_mode": "Modalità Trasporto", + "transport_description": "Inoltra percorsi e traffico per i peer vicini.", + "enable_transport_mode": "Abilita Modalità Trasporto", + "transport_toggle_description": "Inoltra annunci, rispondi alle richieste di percorso e aiuta la tua mesh a rimanere online.", + "requires_restart": "Richiede il riavvio dopo la modifica.", + "show_community_interfaces": "Mostra Interfacce della Comunità", + "community_interfaces_description": "Mostra i preset mantenuti dalla comunità quando aggiungi nuove interfacce.", + "reliability": "Affidabilità", + "messages_description": "Configura come MeshChat gestisce i fallimenti di consegna dei messaggi. Controlla il comportamento dei tentativi automatici, la ritrasmissione degli allegati e i meccanismi di fallback per garantire una consegna affidabile dei messaggi nella rete mesh.", + "auto_resend_title": "Invia automaticamente quando il peer annuncia", + "auto_resend_description": "I messaggi falliti vengono riprovati automaticamente quando la destinazione trasmette di nuovo.", + "retry_attachments_title": "Consenti tentativi con allegati", + "retry_attachments_description": "Anche i carichi utili di grandi dimensioni verranno riprovati (utile quando entrambi i peer hanno limiti elevati).", + "auto_fallback_title": "Fallback automatico al nodo di propagazione", + "auto_fallback_description": "Le consegne dirette fallite vengono messe in coda sul tuo nodo di propagazione preferito.", + "inbound_stamp_cost": "Costo Francobollo Messaggio in Entrata", + "inbound_stamp_description": "Richiedi francobolli proof-of-work per i messaggi a consegna diretta inviati a te. Valori più alti richiedono più lavoro computazionale dai mittenti. Intervallo: 1-254. Predefinito: 8.", + "browse_nodes": "Sfoglia Nodi", + "propagation_nodes_description": "Mantieni il flusso delle conversazioni anche quando i peer sono offline.", + "nodes_info_1": "I nodi di propagazione conservano i messaggi in modo sicuro fino a quando i destinatari non si sincronizzano di nuovo.", + "nodes_info_2": "I nodi si collegano tra loro per distribuire carichi utili crittografati.", + "nodes_info_3": "La maggior parte dei nodi conserva i dati per circa 30 giorni, poi scarta gli elementi non consegnati.", + "run_local_node": "Esegui un nodo di propagazione locale", + "run_local_node_description": "MeshChat annuncerà e manterrà un nodo usando questo hash di destinazione locale.", + "preferred_propagation_node": "Nodo di Propagazione Preferito", + "preferred_node_placeholder": "Hash di destinazione, es. a39610c89d18bb48c73e429582423c24", + "fallback_node_description": "I messaggi ripiegano su questo nodo ogni volta che la consegna diretta fallisce.", + "auto_sync_interval": "Intervallo Sincronizzazione Automatica", + "last_synced": "Ultima sincronizzazione {time} fa.", + "last_synced_never": "Ultima sincronizzazione: mai.", + "propagation_stamp_cost": "Costo Francobollo Nodo di Propagazione", + "propagation_stamp_description": "Richiedi francobolli proof-of-work per i messaggi propagati attraverso il tuo nodo. Valori più alti richiedono più lavoro computazionale. Intervallo: 13-254. Predefinito: 16. **Nota:** La modifica richiede il riavvio dell'app.", + "language": "Lingua", + "select_language": "Seleziona la tua lingua preferita.", + "custom_fork_by": "Fork personalizzato da", + "open": "Apri", + "identity": "Identità", + "lxmf_address_hash": "Hash Indirizzo LXMF", + "propagation_node_status": "Stato Nodo di Propagazione", + "last_sync": "Ultima Sincronizzazione: {time} fa", + "last_sync_never": "Ultima Sincronizzazione: mai", + "syncing": "Sincronizzazione...", + "syncing_node": "Sincronizzazione... ({state})", + "synced": "Sincronizzato", + "not_synced": "Non Sincronizzato", + "not_configured": "Non Configurato", + "toggle_source": "Attiva/Disattiva Codice Sorgente", + "audio_calls": "Telefono", + "calls": "Chiamate", + "status": "Stato", + "active_call": "Chiamata Attiva", + "incoming": "In entrata", + "outgoing": "In uscita", + "call": "Chiama", + "calls_plural": "Chiamate", + "hop": "salto", + "hops_plural": "salti", + "hung_up_waiting": "Riattaccato, in attesa di chiamata...", + "view_incoming_calls": "Visualizza Chiamate in Entrata", + "hangup_all_calls": "Riattacca Tutte le Chiamate", + "clear_history": "Cancella Cronologia", + "no_active_calls": "Nessuna chiamata attiva", + "incoming_call": "Chiamata in arrivo...", + "outgoing_call": "Chiamata in uscita...", + "call_active": "Attiva", + "call_ended": "Terminata", + "propagation_node": "Nodo di Propagazione", + "sync_now": "Sincronizza Ora", + "setting_auto_saved": "Impostazione {label} salvata automaticamente", + "backup_max_count": "Limite backup automatici", + "message_font_size": "Dimensione carattere messaggi", + "message_icon_size": "Dimensione icona", + "search_settings": "Cerca impostazioni...", + "auto_resend": "Invio Automatico", + "retry_attachments": "Riprova Allegati", + "auto_fallback": "Fallback Automatico", + "community_interfaces": "Interfacce Comunità", + "preferred_node": "Nodo Preferito", + "local_node": "Nodo Locale", + "auto_sync": "Sincronizzazione Automatica", + "inbound_stamp_cost_label": "Costo Francobollo in Entrata", + "propagation_stamp_cost_label": "Costo Francobollo Propagazione", + "page_archiver": "Archiviatore Pagine", + "smart_crawler": "Smart Crawler", + "authentication": "Autenticazione", + "banishment": "Esilio", + "banishment_description": "Personalizza l'effetto visivo mostrato per i peer e i nodi esiliati.", + "banished_effect_enabled": "Abilita Effetto Esilio", + "banished_effect_description": "Mostra una sovrapposizione visiva sui peer e sui nodi esiliati.", + "banished_text_label": "Testo Esilio", + "banished_text_description": "Messaggio personalizzato da visualizzare sulla sovrapposizione.", + "banished_color_label": "Colore Esilio", + "banished_color_description": "Il colore usato per l'effetto esilio.", + "desktop_open_calls_in_separate_window": "Apri Chiamate in 2ª Finestra", + "desktop_open_calls_in_separate_window_description": "Quando una chiamata è attiva, verrà mostrata in una finestra popup separata invece che all'interno dell'app.", + "desktop_hardware_acceleration_enabled": "Accelerazione Hardware", + "desktop_hardware_acceleration_enabled_description": "Disabilita se riscontri sfarfallio dell'interfaccia utente, schermi neri o glitch grafici.", + "translator": "Traduttore", + "translator_enabled": "Abilita Traduttore", + "translator_description": "Abilita le funzioni di traduzione nelle conversazioni.", + "libretranslate_url": "URL LibreTranslate", + "libretranslate_url_description": "L'URL dove l'API LibreTranslate è accessibile.", + "system": "Sistema", + "reticulum_stack": "Stack Reticulum", + "reticulum_stack_description": "Gestisci lo stack di rete Reticulum sottostante.", + "reload_rns": "Ricarica RNS", + "reload_rns_description": "Deregistra tutte le destinazioni, ferma l'istanza RNS corrente e ricaricala. Utile per applicare modifiche alla configurazione o riavviare lo stack di rete mesh senza riavviare l'intera applicazione.", + "reloading_rns": "Ricaricando RNS...", + "reloaded_rns": "Reticulum ricaricato con successo", + "announce_interval": "Intervallo Annuncio", + "stop_sync_confirm": "Sei sicuro di voler interrompere la sincronizzazione?", + "sync_error_generic": "Qualcosa è andato storto. Riprova più tardi.", + "sync_complete": "Sincronizzazione completata. {count} messaggi ricevuti.", + "sync_error": "Errore sincronizzazione: {status}", + "switching_identity": "Cambiando Identità...", + "loading_identity": "Caricamento della tua identità", + "emergency_mode_active": "Modalità Emergenza Attiva - Utilizzo del database in memoria e servizi limitati.", + "blackhole_integration_enabled": "Integrazione Blackhole", + "blackhole_integration_description": "Metti automaticamente in blackhole le identità a livello di trasporto Reticulum quando esili gli utenti in MeshChatX.", + "csp_settings": "Content Security Policy (CSP)", + "csp_description": "Aggiungi manualmente domini e sorgenti consentiti per vari tipi di risorse. Utile per server di tile personalizzati, bot o integrazioni esterne.", + "csp_extra_connect_src": "Sorgenti di Connessione Extra", + "csp_extra_connect_src_description": "Sorgenti aggiuntive per connessioni fetch/websocket (es. https://api.example.com).", + "csp_extra_img_src": "Sorgenti Immagine Extra", + "csp_extra_img_src_description": "Sorgenti aggiuntive per immagini e tile.", + "csp_extra_frame_src": "Sorgenti Frame Extra", + "csp_extra_frame_src_description": "Sorgenti aggiuntive per iframe.", + "csp_extra_script_src": "Sorgenti Script Extra", + "csp_extra_script_src_description": "Sorgenti aggiuntive per script (solo per uso avanzato).", + "csp_extra_style_src": "Sorgenti Stile Extra", + "csp_extra_style_src_description": "Sorgenti aggiuntive per fogli di stile.", + "location": "Posizione", + "location_source": "Sorgente posizione", + "location_source_browser": "Automatica (Browser)", + "location_source_manual": "Manuale", + "location_source_browser_desc": "Utilizza l'API di geolocalizzazione del browser. Nota: nell'app desktop, potrebbe utilizzare i servizi Google.", + "location_source_manual_desc": "Usa coordinate inserite manualmente per la massima privacy.", + "location_manual_lat": "Latitudine", + "location_manual_lon": "Longitudine", + "location_manual_alt": "Altitudine (m)", + "telemetry_enabled": "Telemetria abilitata", + "telemetry_description": "Consenti a MeshChatX di inviare e ricevere dati telemetrici. Ciò include la risposta alle richieste di posizione da parte di peer fidati.", + "telemetry_trusted_peers": "Peer Telemetrici Fidati", + "telemetry_no_trusted_peers": "Nessun peer fidato configurato. Fidati dei peer dal menu della chat per consentire loro di richiedere la tua posizione.", + "telemetry_revoke_trust": "Revoca Fiducia", + "telemetry_trust_revoked": "Fiducia telemetrica revocata per {name}", + "telemetry_trust_granted_alert": "Il peer è ora considerato fidato per la telemetria.", + "telemetry_trust_revoked_alert": "Fiducia telemetrica revocata.", + "telemetry_trust_failed": "Impossibile aggiornare la fiducia telemetrica.", + "telemetry_trust_revoke": "Revoca Fiducia Telemetrica", + "telemetry_trust_grant": "Fidati per la Telemetria", + "location_manage_desc": "Gestisci come viene condivisa la tua posizione." + }, + "common": { + "open": "Apri", + "close": "Chiudi", + "cancel": "Annulla", + "save": "Salva", + "block": "Esilia", + "delete": "Elimina", + "edit": "Modifica", + "add": "Aggiungi", + "sync": "Sincronizza", + "restart_app": "Riavvia App", + "reveal": "Rivela", + "refresh": "Aggiorna", + "copy": "Copia", + "copy_to_clipboard": "Copia negli appunti", + "vacuum": "Vacuum", + "auto_recover": "Recupero Automatico", + "shutdown": "Spegni", + "acknowledge_reset": "Conferma e Reimposta", + "continue": "Continua", + "confirm": "Conferma", + "delete_confirm": "Sei sicuro di voler eliminare questo elemento? L'azione non può essere annullata.", + "search": "Cerca strumenti...", + "no_results": "Nessuno strumento trovato", + "error": "Errore", + "success": "Successo", + "warning": "Avviso", + "info": "Info", + "copied": "Copiato negli appunti", + "failed_to_copy": "Impossibile copiare negli appunti", + "save_failed": "Impossibile salvare la configurazione!", + "invalid_address": "Indirizzo Non Valido", + "loading": "Caricamento...", + "ok": "OK" + }, + "maintenance": { + "title": "Manutenzione e Dati", + "description": "Gestisci i tuoi dati locali, svuota le cache e fai il backup delle conversazioni.", + "clear_messages": "Cancella Tutti i Messaggi", + "clear_messages_desc": "Elimina permanentemente tutti i messaggi inviati e ricevuti.", + "clear_announces": "Cancella Tutti gli Annunci", + "clear_announces_desc": "Rimuovi tutti i peer e i nodi scoperti dalla tua cache.", + "clear_nomadnet_favs": "Cancella Preferiti NomadNetwork", + "clear_nomadnet_favs_desc": "Rimuovi tutti i nodi NomadNetwork salvati dai tuoi preferiti.", + "clear_lxmf_icons": "Cancella Icone LXMF", + "clear_lxmf_icons_desc": "Rimuovi le icone utente LXMF memorizzate sul tuo dispositivo.", + "clear_archives": "Cancella Archivi Pagine", + "clear_archives_desc": "Elimina tutte le pagine NomadNetwork memorizzate.", + "clear_confirm": "Sei sicuro? Questa azione non può essere annullata.", + "messages_cleared": "Messaggi cancellati con successo", + "announces_cleared": "Annunci cancellati con successo", + "favourites_cleared": "Preferiti cancellati con successo", + "lxmf_icons_cleared": "Icone LXMF cancellate con successo", + "archives_cleared": "Archivi cancellati con successo", + "import_success": "Importati con successo {count} messaggi", + "import_failed": "Impossibile importare i messaggi" + }, + "identities": { + "title": "Identità", + "manage": "Gestisci e passa tra più identità Reticulum.", + "new_identity": "Nuova Identità", + "generate_fresh": "Genera una nuova identità Reticulum.", + "display_name": "Nome Visualizzato", + "display_name_hint": "es. Agente Segreto", + "current": "Corrente", + "switch": "Passa a questa identità", + "delete": "Elimina identità", + "no_identities": "Nessuna identità trovata", + "create_first": "Crea una nuova identità per iniziare.", + "switch_confirm": "Passare all'identità \"{name}\"? L'applicazione dovrà essere riavviata.", + "delete_confirm": "Sei sicuro di voler eliminare l'identità \"{name}\"? L'azione non può essere annullata.", + "switched": "Identità cambiata. L'applicazione si riavvierà ora per applicare le modifiche.", + "created": "Identità creata con successo", + "deleted": "Identità eliminata", + "failed_load": "Impossibile caricare le identità", + "enter_display_name_warning": "Inserisci un nome visualizzato", + "failed_create": "Impossibile creare l'identità", + "switch_scheduled": "Cambio programmato. Ricaricando l'applicazione...", + "failed_switch": "Impossibile cambiare identità", + "failed_delete": "Impossibile eliminare l'identità" + }, + "about": { + "title": "Informazioni", + "version": "v{version}", + "rns_version": "RNS {version}", + "lxmf_version": "LXMF {version}", + "python_version": "Python {version}", + "config_path": "Percorso config", + "database_path": "Percorso database", + "database_size": "Dimensione database", + "database_health": "Salute Database", + "database_health_description": "Controllo rapido, ottimizzazione WAL e strumenti di recupero per il database MeshChatX.", + "running_checks": "Esecuzione controlli...", + "integrity": "Integrità", + "journal_mode": "Modalità journal", + "wal_autocheckpoint": "Autocheckpoint WAL", + "page_size": "Dimensione pagina", + "pages_free": "Pagine / Libere", + "free_space_estimate": "Spazio libero stimato", + "system_resources": "Risorse di Sistema", + "live": "Live", + "memory_rss": "Memoria (RSS)", + "virtual_memory": "Memoria Virtuale", + "network_stats": "Statistiche di Rete", + "sent": "Inviati", + "received": "Ricevuti", + "packets_sent": "Pacchetti Inviati", + "packets_received": "Pacchetti Ricevuti", + "reticulum_stats": "Statistiche Reticulum", + "total_paths": "Percorsi Totali", + "announces_per_second": "Annunci / sec", + "announces_per_minute": "Annunci / min", + "announces_per_hour": "Annunci / ora", + "download_activity": "Attività di Download", + "no_downloads_yet": "Ancora nessun download", + "runtime_status": "Stato Runtime", + "shared_instance": "Istanza Condivisa", + "standalone_instance": "Istanza Standalone", + "transport_enabled": "Trasporto Abilitato", + "transport_disabled": "Trasporto Disabilitato", + "identity_addresses": "Identità e Indirizzi", + "telephone_address": "Indirizzo Telefono", + "security_integrity": "Integrità di Sicurezza", + "security_integrity_description": "Stato di verifica del sistema per il backend e i file dei dati", + "secured": "Protetto", + "tampering_detected": "Manomissione Rilevata", + "technical_issues": "Problemi Tecnici:", + "integrity_backend_error": "Il binario del backend dell'applicazione (estratto da ASAR) sembra essere stato modificato o sostituito. Questo potrebbe indicare un attore malevolo che tenta di compromettere la tua comunicazione mesh.", + "integrity_data_error": "Le tue identità o i file del database sembrano essere stati modificati mentre l'app era chiusa.", + "integrity_warning_footer": "Procedi con cautela. Se non hai aggiornato o modificato manualmente questi file, la tua installazione potrebbe essere compromessa.", + "no_integrity_violations": "Nessuna violazione di integrità rilevata dall'ultimo avvio.", + "dependency_chain": "Catena di Dipendenze", + "other_core_components": "Altri Componenti Core", + "backend_dependencies": "Dipendenze Backend", + "delete_snapshot_confirm": "Sei sicuro di voler eliminare questo snapshot?", + "snapshot_deleted": "Snapshot eliminato", + "failed_delete_snapshot": "Impossibile eliminare lo snapshot", + "delete_backup_confirm": "Sei sicuro di voler eliminare questo backup?", + "backup_deleted": "Backup eliminato", + "failed_delete_backup": "Impossibile eliminare il backup", + "database_restored": "Database ripristinato. Riavvio...", + "failed_restore_snapshot": "Impossibile ripristinare lo snapshot", + "restore_snapshot_confirm": "Sei sicuro di voler ripristinare questo snapshot? Questo sovrascriverà il database corrente e richiederà il riavvio dell'app.", + "integrity_acknowledged": "Problemi di integrità confermati", + "integrity_acknowledged_reset": "Problemi di integrità confermati e manifest reimpostato", + "integrity_acknowledge_confirm": "Sei sicuro di voler confermare questi problemi di integrità? Questo aggiornerà il manifest di sicurezza per riflettere lo stato attuale dei tuoi file.", + "failed_acknowledge_integrity": "Impossibile confermare i problemi di integrità", + "shutdown_sent": "Comando di spegnimento inviato al server.", + "identity_exported": "File chiave identità esportato", + "identity_copied": "Chiave identità Base32 copiata negli appunti" + }, + "interfaces": { + "title": "Interfacce", + "manage": "Gestisci", + "description": "Cerca, filtra ed esporta i tuoi adattatori Reticulum.", + "add_interface": "Aggiungi Interfaccia", + "import": "Importa", + "export_all": "Esporta tutto", + "search_placeholder": "Cerca per nome, tipo, host...", + "all": "Tutte", + "connected_only": "Solo connesse", + "all_types": "Tutti i tipi", + "no_interfaces_found": "Nessuna interfaccia trovata", + "no_interfaces_description": "Modifica la tua ricerca o aggiungi una nuova interfaccia.", + "restart_required": "Riavvio richiesto", + "restart_description": "Reticulum MeshChatX deve essere riavviato affinché le modifiche alle interfacce abbiano effetto.", + "restart_now": "Riavvia ora", + "failed_enable": "impossibile abilitare l'interfaccia", + "failed_disable": "impossibile disabilitare l'interfaccia", + "delete_confirm": "Sei sicuro di voler eliminare questa interfaccia? L'azione non può essere annullata!", + "failed_delete": "impossibile eliminare l'interfaccia", + "failed_export_all": "Impossibile esportare le interfacce", + "failed_export_single": "Impossibile esportare l'interfaccia", + "failed_reload": "Impossibile ricaricare Reticulum!", + "interface_not_found": "L'interfaccia selezionata per la modifica non è stata trovata.", + "discovery_settings_saved": "Impostazioni di scoperta salvate", + "failed_save_discovery": "Impossibile salvare le impostazioni di scoperta", + "no_interfaces_found_config": "Nessuna interfaccia trovata nel file di configurazione selezionato", + "failed_parse_config": "Impossibile analizzare il file di configurazione", + "select_config_file": "Seleziona un file di configurazione", + "select_at_least_one": "Seleziona almeno un'interfaccia da importare", + "import_success": "Interfacce importate con successo. MeshChat deve essere riavviato per applicare le modifiche.", + "failed_import_all": "Impossibile importare le interfacce" + }, + "map": { + "title": "Mappa", + "description": "Mappa compatibile con l'uso offline e supporto MBTiles.", + "upload_mbtiles": "Carica MBTiles", + "select_file": "Seleziona file MBTiles", + "offline_mode": "Modalità Offline", + "online_mode": "Modalità Online", + "attribution": "Attribuzione", + "bounds": "Confini", + "center": "Centro", + "zoom": "Zoom", + "uploading": "Caricamento...", + "upload_success": "Mappa caricata con successo", + "upload_failed": "Impossibile caricare la mappa", + "no_map_loaded": "Nessuna mappa offline caricata. Carica un file .mbtiles per abilitare la modalità offline.", + "invalid_file": "File MBTiles non valido. Sono supportate solo le tile raster.", + "default_view": "Vista Predefinita", + "set_as_default": "Imposta come Vista Predefinita", + "export_area": "Esporta Area", + "export_instructions": "Trascina sulla mappa per selezionare un'area.", + "min_zoom": "Zoom Min", + "max_zoom": "Zoom Max", + "tile_count": "Tile Stimate", + "start_export": "Inizia Esportazione", + "exporting": "Esportazione Mappa...", + "download_ready": "Esportazione Completata", + "download_now": "Scarica MBTiles", + "caching_enabled": "Caching Tile", + "clear_cache": "Svuota Cache", + "cache_cleared": "Cache tile svuotata", + "tile_server_url": "URL Server Tile", + "tile_server_url_placeholder": "https://tile.openstreetmap.org/{z}/{x}/{y}.png", + "tile_server_url_hint": "Usa {z}, {x}, {y} per zoom, colonna, riga", + "tile_server_saved": "URL server tile salvato", + "tile_server_openstreetmap": "OpenStreetMap", + "nominatim_api_url": "URL API Nominatim", + "nominatim_api_url_placeholder": "https://nominatim.openstreetmap.org", + "nominatim_api_url_hint": "URL di base per il servizio di geocodifica Nominatim", + "nominatim_api_saved": "URL API Nominatim salvato", + "search_placeholder": "Cerca una posizione...", + "search_offline_error": "La ricerca è disponibile solo in modalità online", + "search_connection_error": "Impossibile connettersi al servizio di ricerca. Controlla la tua connessione internet.", + "search_error": "Errore di ricerca", + "search_no_results": "Nessun risultato trovato", + "custom_tile_server_unavailable": "Il server tile personalizzato non è accessibile in modalità offline", + "custom_nominatim_unavailable": "Il server Nominatim personalizzato non è accessibile in modalità offline", + "onboarding_title": "Esporta in MBTiles!", + "onboarding_text": "Usa lo strumento di esportazione per scaricare aree della mappa come file MBTiles per l'uso offline.", + "onboarding_got_it": "Ho capito", + "tool_point": "Disegna Punto", + "tool_linestring": "Disegna Linea", + "tool_polygon": "Disegna Poligono", + "tool_circle": "Disegna Cerchio", + "tool_measure": "Misura Distanza/Area", + "tool_clear": "Cancella Disegni", + "save_drawing": "Salva Livello Disegno", + "load_drawing": "Carica Livello Disegno", + "save_drawing_title": "Salva Livello Disegno", + "save_drawing_desc": "Salva le tue annotazioni attuali sulla mappa nel database.", + "drawing_name": "Nome Livello", + "drawing_name_placeholder": "es. Area Target Alpha", + "load_drawing_title": "Carica Livello Disegno", + "loading_drawings": "Caricamento livelli salvati...", + "no_drawings": "Nessun Livello Salvato", + "no_drawings_desc": "Non hai ancora salvato alcuna annotazione sulla mappa.", + "saved_on": "Salvato il", + "settings": "Impostazioni Mappa", + "go_to_my_location": "Vai alla Mia Posizione", + "source_updated": "Sorgente mappa aggiornata", + "failed_set_active": "Impossibile impostare la mappa attiva", + "file_deleted": "File eliminato", + "failed_delete_file": "Impossibile eliminare il file", + "storage_saved": "Directory di archiviazione salvata", + "failed_save_storage": "Impossibile salvare la directory", + "export_cancelled": "Esportazione annullata", + "failed_cancel_export": "Impossibile annullare l'esportazione", + "failed_start_export": "Impossibile avviare l'esportazione", + "select_mbtiles_error": "Seleziona un file .mbtiles", + "view_saved": "Vista predefinita salvata", + "failed_save_view": "Impossibile salvare la vista predefinita", + "failed_clear_cache": "Impossibile svuotare la cache", + "failed_save_tile_server": "Impossibile salvare l'URL del server tile", + "failed_save_nominatim": "Impossibile salvare l'URL dell'API Nominatim", + "copied_coordinates": "Coordinate copiate", + "failed_load_drawings": "Impossibile caricare i disegni", + "not_initialized": "Mappa non inizializzata", + "drawing_saved": "Disegno salvato", + "failed_save_drawing": "Impossibile salvare il disegno", + "deleted": "Eliminato", + "failed_delete": "Impossibile eliminare", + "location_not_determined": "Impossibile determinare la tua posizione", + "geolocation_not_supported": "La geolocalizzazione non è supportata dal tuo browser", + "no_nodes_location": "Nessun nodo scoperto con posizione trovata", + "failed_fetch_nodes": "Impossibile recuperare i nodi scoperti per la mappatura" + }, + "interface": { + "disable": "Disabilita", + "enable": "Abilita", + "edit_interface": "Modifica Interfaccia", + "export_interface": "Esporta Interfaccia", + "delete_interface": "Elimina Interfaccia", + "listen": "Ascolta", + "forward": "Inoltra", + "port": "Porta", + "frequency": "Frequenza", + "bandwidth": "Larghezza di banda", + "txpower": "Potenza TX", + "spreading_factor": "SF", + "coding_rate": "Coding Rate", + "bitrate": "Bitrate", + "tx": "TX", + "rx": "RX", + "noise": "Rumore", + "clients": "Client" + }, + "messages": { + "title": "Messaggi", + "conversations": "Conversazioni", + "announces": "Annunci", + "search_placeholder": "Cerca in {count} conversazioni...", + "unread": "Non letti", + "failed": "Falliti", + "attachments": "Allegati", + "no_messages_yet": "Ancora nessun messaggio", + "loading_conversations": "Caricamento conversazioni...", + "no_conversations": "Nessuna Conversazione", + "discover_peers": "Scopri i peer nella scheda Annunci", + "no_search_results": "Nessun Risultato Trovato", + "try_another_search": "Prova un termine di ricerca diverso", + "no_search_results_conversations": "La tua ricerca non corrisponde ad alcuna conversazione.", + "search_placeholder_announces": "Cerca in {count} annunci recenti...", + "no_peers_discovered": "Nessun Peer Scoperto", + "waiting_for_announce": "In attesa che qualcuno annunci!", + "no_search_results_peers": "La tua ricerca non corrisponde ad alcun Peer!", + "direct": "Diretto", + "downloading": "Scaricamento", + "hops": "{count} salti", + "hops_away": "{count} salti di distanza", + "snr": "SNR {snr}", + "stamp_cost": "Costo Francobollo {cost}", + "pop_out_chat": "Estrai chat", + "custom_display_name": "Nome Visualizzato Personalizzato", + "send_placeholder": "Scrivi un messaggio...", + "no_messages_in_conversation": "Ancora nessun messaggio in questa conversazione.", + "say_hello": "Di' ciao!", + "no_active_chat": "Nessuna Chat Attiva", + "select_peer_or_enter_address": "Seleziona un peer dalla barra laterale o inserisci un indirizzo qui sotto", + "add_files": "Aggiungi File", + "paste_from_clipboard": "Incolla dagli Appunti", + "location": "Posizione", + "share_location": "Condividi Posizione", + "request_location": "Richiedi Posizione", + "view_on_map": "Visualizza sulla Mappa", + "request": "Richiesta", + "generate_paper_message": "Genera Messaggio Cartaceo (LXM)", + "recording": "Registrazione: {duration}", + "nomad_network_node": "Nodo Nomad Network", + "toggle_source": "Attiva/Disattiva Codice Sorgente", + "folder_created": "Cartella creata", + "failed_create_folder": "Impossibile creare la cartella", + "folder_renamed": "Cartella rinominata", + "failed_rename_folder": "Impossibile rinominare la cartella", + "folder_deleted": "Cartella eliminata", + "failed_delete_folder": "Impossibile eliminare la cartella", + "moved_to_folder": "Spostato nella cartella", + "failed_move_folder": "Impossibile spostare nella cartella", + "marked_read": "Segnato come letto", + "failed_mark_read": "Impossibile segnare come letto", + "conversations_deleted": "Conversazioni eliminate", + "failed_delete_conversations": "Impossibile eliminare le conversazioni", + "failed_export_folders": "Impossibile esportare le cartelle", + "folders_imported": "Cartelle importate", + "failed_import_folders": "Impossibile importare le cartelle", + "failed_read_clipboard": "Impossibile leggere dagli appunti", + "failed_send_ingest": "Impossibile inviare la richiesta di ingest", + "address_copied": "Il tuo indirizzo LXMF è stato copiato negli appunti", + "hash_copied": "Hash identità copiato negli appunti", + "failed_to_copy_hash": "Impossibile copiare l'hash identità", + "failed_copy_address": "Impossibile copiare l'indirizzo", + "translation_failed": "Traduzione fallita", + "failed_add_contact": "Impossibile aggiungere il contatto", + "ingesting_paper_message": "Ingesting messaggio cartaceo...", + "failed_ingest_paper": "Impossibile ingerire il messaggio cartaceo", + "enter_display_name": "Inserisci un nome visualizzato personalizzato", + "failed_update_display_name": "Impossibile aggiornare il nome visualizzato", + "failed_load_audio": "Impossibile caricare l'allegato audio.", + "no_contacts_telephone": "Nessun contatto trovato nel telefono", + "failed_load_contacts": "Impossibile caricare i contatti", + "location_request_sent": "Richiesta di posizione inviata", + "failed_send_location_request": "Impossibile inviare la richiesta di posizione", + "fetching_location": "Recupero della posizione...", + "location_sent": "Posizione condivisa con successo", + "location_requested": "Posizione richiesta", + "remove_image_confirm": "Sei sicuro di voler rimuovere questo allegato immagine?", + "failed_start_recording": "impossibile avviare la registrazione", + "remove_audio_confirm": "Sei sicuro di voler rimuovere questo allegato audio?", + "failed_generate_qr": "Impossibile generare il QR", + "enter_folder_name": "Inserisci il nome della cartella", + "new_folder": "Nuova Cartella", + "rename_folder": "Rinomina cartella", + "failed_render_qr": "Impossibile renderizzare il codice QR", + "uri_copied": "URI copiato negli appunti", + "failed_copy_uri": "Impossibile copiare l'URI", + "paper_message_sent": "Messaggio cartaceo inviato con successo", + "failed_send_paper": "Impossibile inviare il messaggio cartaceo", + "failed_load_config": "Impossibile caricare la configurazione", + "profile_icon_saved": "Icona del profilo salvata con successo", + "failed_save_profile_icon": "Impossibile salvare l'icona del profilo", + "select_colors_warning": "Seleziona sia il colore di sfondo che quello dell'icona", + "select_icon_warning": "Seleziona un'icona", + "changes_reset": "Modifiche reimpostate ai valori salvati", + "profile_icon_removed": "Icona del profilo rimossa con successo", + "user_banished": "Utente esiliato con successo", + "failed_banish_user": "Impossibile esiliare l'utente", + "delete_conversation_confirm": "Sei sicuro di voler eliminare questa conversazione?", + "failed_delete_conversation": "impossibile eliminare la conversazione", + "delete_history_confirm": "Sei sicuro di voler eliminare tutti i messaggi in questa conversazione? L'azione non può essere annullata!", + "failed_delete_history": "impossibile eliminare la cronologia", + "invalid_destination_hash": "Hash di destinazione non valido", + "invalid_destination_hash_format": "Formato hash di destinazione non valido", + "ping_failed": "Ping fallito. Riprova più tardi", + "ping_reply_from": "Risposta valida da {hash}", + "duration": "Durata: {duration}", + "hops_there": "Salti Andata: {count}", + "hops_back": "Salti Ritorno: {count}", + "signal_quality": "Qualità Segnale: {quality}%", + "rssi_val": "RSSI: {rssi}dBm", + "snr_val": "SNR: {snr}dB" + }, + "settings": { + "shortcut_saved": "Scorciatoia salvata", + "shortcut_deleted": "Scorciatoia eliminata", + "archived_pages_flushed": "Pagine archiviate svuotate.", + "failed_enable_transport": "Impossibile abilitare la modalità trasporto!", + "failed_disable_transport": "Impossibile disabilitare la modalità trasporto!", + "failed_reload_reticulum": "Impossibile ricaricare Reticulum!", + "folders_exported": "Cartelle esportate", + "failed_export_folders": "Impossibile esportare le cartelle", + "folders_imported": "Cartelle e mappature importate con successo", + "failed_import_folders": "Impossibile importare le cartelle" + }, + "debug": { + "title": "Log di Debug", + "description": "Visualizza i log dell'applicazione e le anomalie rilevate.", + "failed_fetch_logs": "Impossibile recuperare i log", + "logs_copied": "I log in questa pagina sono stati copiati negli appunti", + "failed_copy_logs": "Impossibile copiare i log" + }, + "visualiser": { + "title": "Visualizzatore di Rete", + "description": "Visualizza la topologia della rete mesh.", + "reticulum_mesh": "Reticulum Mesh", + "network_visualizer": "Visualizzatore di Rete", + "node_info": "Info Nodo", + "hash": "Hash", + "hops": "Salti", + "interface": "Interfaccia", + "rssi": "RSSI", + "snr": "SNR", + "first_seen": "Visto per la prima volta", + "last_seen": "Visto l'ultima volta", + "center_node": "Centra sul nodo", + "copy_hash": "Copia Hash", + "banish_identity": "Esilia identità", + "banished_identities": "Identità esiliate", + "filter_nodes": "Filtra nodi...", + "all": "Tutti", + "direct": "Diretto", + "one_hop": "1 Salto", + "multi_hops": "2+ Salti", + "clear": "Cancella", + "show_labels": "Mostra tutte le etichette", + "bouncing_balls": "Modalità palle rimbalzanti", + "orbit_mode": "Modalità orbita", + "show_edges": "Mostra bordi", + "show_tooltips": "Mostra tooltip", + "show_rssi": "Mostra RSSI", + "show_snr": "Mostra SNR", + "show_hops": "Mostra Salti", + "physics": "Fisica", + "gravity": "Gravità", + "spring_length": "Lunghezza molla", + "spring_strength": "Forza molla", + "damping": "Smorzamento", + "central_gravity": "Gravità centrale", + "edge_strength": "Forza bordo", + "force_atlas_2": "Force Atlas 2", + "barns_hut": "Barns Hut", + "repulsion": "Repulsione", + "reset_physics": "Reimposta fisica", + "reset_camera": "Reimposta Telecamera", + "clear_graph": "Cancella grafico", + "total_nodes": "Nodi totali", + "total_edges": "Bordi totali", + "discovered": "Scoperti", + "wait_between_batches": "Attesa tra i batch", + "batch": "Batch", + "loading_status": "Stato caricamento", + "failed_load": "Impossibile caricare i dati di rete" + }, + "banishment": { + "title": "Esiliati", + "description": "Gestisci gli utenti e i nodi esiliati", + "failed_load_banished": "Impossibile caricare le destinazioni esiliate", + "search_placeholder": "Cerca per hash o nome visualizzato...", + "loading_items": "Caricamento elementi esiliati...", + "no_items": "Nessun elemento esiliato trovato", + "lift_banishment": "Revoca Esilio", + "lift_banishment_confirm": "Sei sicuro di voler revocare l'esilio per {name}?", + "banished_at": "Esiliato il", + "banished_until": "Esiliato fino al", + "reason": "Motivo", + "type": "Tipo", + "user": "Utente", + "node": "Nodo", + "banishment_lifted": "Esilio revocato con successo", + "failed_lift_banishment": "Impossibile revocare l'esilio" + }, + "nomadnet": { + "remove_favourite": "Rimuovi dai Preferiti", + "add_favourite": "Aggiungi ai Preferiti", + "page_archives": "Archivi Pagine", + "archive_current_version": "Archivia Versione Corrente", + "no_archives_for_this_page": "Nessun archivio per questa pagina", + "viewing_archived_version_from": "Visualizzazione versione archiviata del {time}", + "viewing_archived_version": "Visualizzazione versione archiviata", + "load_live": "Carica Live", + "failed_to_load_page": "Impossibile caricare la pagina", + "archived_version_available": "È disponibile una versione archiviata di questa pagina.", + "view_archive": "Visualizza Archivio", + "no_active_node": "Nessun Nodo Attivo", + "select_node_to_browse": "Seleziona un Nodo per iniziare a navigare!", + "open_nomadnet_url": "Apri un URL Nomadnet", + "unknown_node": "Nodo Sconosciuto", + "existing_download_in_progress": "Un download è già in corso. Attendi che finisca prima di iniziarne un altro.", + "favourites": "Preferiti", + "announces": "Annunci", + "search_favourites_placeholder": "Cerca in {count} preferiti...", + "search_placeholder_announces": "Cerca in {count} annunci recenti...", + "rename": "Rinomina", + "remove": "Rimuovi", + "no_favourites": "Nessun preferito", + "add_nodes_from_announces": "Aggiungi nodi dalla scheda annunci.", + "search_announces": "Cerca annunci", + "announced_time_ago": "Annunciato {time} fa", + "block_node": "Esilia Nodo", + "no_announces_yet": "Ancora nessun annuncio", + "no_search_results_peers": "Nessun peer trovato corrispondente alla tua ricerca.", + "listening_for_peers": "Ascolto dei peer sulla mesh.", + "block_node_confirm": "Sei sicuro di voler esiliare {name}? I suoi annunci verranno ignorati e non apparirà nel flusso degli annunci.", + "node_blocked_successfully": "Nodo esiliato con successo", + "failed_to_block_node": "Impossibile esiliare il nodo", + "failed_rename_favourite": "Impossibile rinominare il preferito", + "rename_favourite": "Rinomina questo preferito", + "remove_favourite_confirm": "Sei sicuro di voler rimuovere questo preferito?", + "enter_nomadnet_url": "Inserisci un URL Nomadnet", + "archiving_page": "Archiviazione pagina...", + "page_archived_successfully": "Pagina archiviata con successo.", + "identify_confirm": "Sei sicuro di volerti identificare su questo nodo NomadNetwork? La pagina si ricaricherà dopo l'invio della tua identità.", + "banishment_lifted": "Esilio revocato con successo", + "failed_lift_banishment": "Impossibile revocare l'esilio", + "enter_section_name": "Inserisci il nome della sezione", + "new_section": "Nuova Sezione", + "rename_section": "Rinomina sezione", + "delete_section_confirm": "Eliminare questa sezione? I preferiti verranno spostati nella sezione principale.", + "unsupported_url": "url non supportato: " + }, + "forwarder": { + "title": "Inoltro LXMF", + "description": "Inoltra i messaggi da un indirizzo a un altro, con instradamento di ritorno trasparente.", + "add_rule": "Aggiungi Regola di Inoltro", + "name": "Nome", + "name_placeholder": "Nome regola (es. Nodo Casa)...", + "forward_to_hash": "Inoltra all'Hash", + "destination_placeholder": "Hash LXMF di destinazione...", + "source_filter": "Filtro Sorgente (Opzionale)", + "source_filter_placeholder": "Inoltra solo da questo hash...", + "add_button": "Aggiungi Regola", + "active_rules": "Regole Attive", + "no_rules": "Nessuna regola di inoltro configurata.", + "active": "Attiva", + "disabled": "Disabilitata", + "forwarding_to": "Inoltro a: {hash}", + "source_filter_display": "Filtro sorgente: {hash}", + "delete_confirm": "Sei sicuro di voler eliminare questa regola?" + }, + "archives": { + "description": "Cerca e visualizza le pagine Nomad Network archiviate", + "search_placeholder": "Cerca contenuto, hash o percorso...", + "loading": "Caricamento archivi...", + "no_archives_found": "Nessun archivio trovato", + "adjust_filters": "Prova a regolare i tuoi filtri di ricerca.", + "browse_to_archive": "Le pagine archiviate appariranno qui una volta che avrai visitato i siti Nomad Network.", + "page": "Pagina", + "pages": "Pagine", + "view": "Visualizza", + "showing_range": "Visualizzazione da {start} a {end} di {total} archivi", + "page_of": "Pagina {page} di {total_pages}" + }, + "docs": { + "title": "Documentazione", + "subtitle": "Manuali e guide Reticulum.", + "status_title": "Stato Documentazione", + "status_downloading": "Scaricamento...", + "status_available": "Manuale Offline Disponibile", + "status_not_downloaded": "Non Scaricato", + "btn_download": "Scarica Manuali", + "btn_update": "Aggiorna Manuale", + "error": "Errore", + "failed_update_docs": "Impossibile aggiornare le sorgenti della documentazione", + "docs_link_copied": "Link alla documentazione copiato negli appunti", + "failed_copy_link": "Impossibile copiare il link" + }, + "tools": { + "utilities": "Utilità", + "power_tools": "Strumenti avanzati per operatori", + "diagnostics_description": "Gli strumenti di diagnostica e gli assistenti firmware sono inclusi in MeshChat per consentirti di risolvere i problemi dei peer senza lasciare la console.", + "ping": { + "title": "Ping", + "description": "Test di latenza per qualsiasi destinazione LXMF con stato in tempo reale." + }, + "rnprobe": { + "title": "RNProbe", + "description": "Sonda le destinazioni con dimensioni dei pacchetti personalizzate per testare la connettività." + }, + "rncp": { + "title": "RNCP", + "description": "Invia e ricevi file su RNS con monitoraggio dell'avanzamento." + }, + "rnstatus": { + "title": "RNStatus", + "description": "Visualizza le statistiche delle interfacce e le informazioni sullo stato della rete." + }, + "rnpath": { + "title": "RNPath", + "description": "Gestisci la tabella dei percorsi, visualizza i tassi di annuncio e richiedi percorsi.", + "failed_fetch": "Impossibile recuperare i dati del percorso", + "path_dropped": "Percorso eliminato", + "failed_drop": "Impossibile eliminare il percorso", + "error_drop": "Errore durante l'eliminazione del percorso", + "failed_request": "Impossibile richiedere il percorso", + "paths_dropped": "Percorsi eliminati", + "failed_drop_paths": "Impossibile eliminare i percorsi", + "purge_confirm": "Svuotare tutte le code di annuncio? L'azione non può essere annullata.", + "queues_purged": "Code di annuncio svuotate", + "failed_purge": "Impossibile svuotare le code" + }, + "rnpath_trace": { + "title": "RNS Path Trace", + "description": "Visualizza il percorso e i salti verso qualsiasi hash di destinazione sulla mesh.", + "destination_hash": "Hash di Destinazione", + "placeholder": "Inserisci hash di destinazione a 32 caratteri...", + "trace": "Traccia Percorso", + "tracing": "Tracciamento del percorso attraverso la mesh...", + "total_hops": "Salti Totali", + "interface": "Interfaccia di Uscita", + "next_hop": "Prossimo Salto", + "ready_title": "Traccia un Percorso", + "ready_desc": "Inserisci un hash di destinazione sopra per visualizzare come i pacchetti viaggiano attraverso la mesh per raggiungerlo.", + "unknown_hops": "{count} Salti Intermedi", + "ping_test": "Test con Ping" + }, + "translator": { + "title": "Traduttore", + "description": "Traduci testo usando l'API LibreTranslate o Argos Translate locale." + }, + "forwarder": { + "title": "Inoltro", + "description": "Inoltro LXMF con instradamento del percorso di ritorno." + }, + "rnode_flasher": { + "title": "Flasher RNode", + "description": "Flasher e aggiornamento degli adattatori RNode senza toccare la riga di comando.", + "select_device": "1. Seleziona il tuo dispositivo", + "product": "Prodotto", + "model": "Modello", + "select_product": "Seleziona un Prodotto", + "select_model": "Seleziona un Modello", + "enter_dfu_mode": "Entra in Modalità DFU", + "entering_dfu_mode": "Entrata in Modalità DFU...", + "find_device_issue": "Non trovi il tuo dispositivo? Apri una segnalazione su", + "select_firmware": "2. Seleziona il firmware da flashare (.zip)", + "flash_now": "Flasha Ora", + "flashing": "Flashing: {percentage}%", + "flashing_file_progress": "File {current}/{total}: {percentage}%", + "connecting_device": "Connessione al dispositivo...", + "download_firmware": "Scarica Firmware", + "official_firmware": "Firmware Ufficiale", + "ce_firmware": "Firmware CE", + "transport_node_firmware": "Firmware Nodo di Trasporto", + "common_issues": "Problemi Comuni", + "hardware_failure": "Guasto Hardware:", + "provision_eeprom_hint": "Devi inizializzare la eeprom al passaggio 3.", + "firmware_corrupt": "Firmware Corrotto:", + "set_firmware_hash_hint": "Devi impostare l'hash del firmware al passaggio 4.", + "step_provision": "3. Inizializza EEPROM", + "provision_description": "Imposta info dispositivo, checksum e firma vuota", + "provision": "Inizializza", + "provisioning_wait": "Inizializzazione: attendi...", + "step_set_hash": "4. Imposta Hash Firmware", + "set_hash_description": "Usa l'hash dalla scheda", + "set_firmware_hash": "Imposta Hash Firmware", + "setting_hash_wait": "Impostazione Hash Firmware: attendi...", + "step_done": "5. Finalizza", + "download_recommended": "Scarica e Carica Firmware Consigliato", + "downloading": "Scaricamento...", + "done_description": "Se sei arrivato fin qui e tutti i passaggi precedenti sono riusciti, il tuo RNode dovrebbe essere pronto all'uso.", + "meshchat_usage": "Per usare RNode con MeshChat, dovrai aggiungere una RNodeInterface nella pagina Interfacce → Aggiungi Interfaccia.", + "sideband_usage": "Per usare RNode con Sideband, dovrai configurarlo in Hardware → RNode e abilitare Connectivity → Connect via RNode.", + "restart_warning": "Devi riavviare MeshChat e Sideband affinché le modifiche alle impostazioni dell'interfaccia abbiano effetto!", + "advanced_tools": "Strumenti Avanzati", + "detect_rnode": "Rileva RNode", + "reboot_rnode": "Riavvia RNode", + "read_display": "Leggi Display", + "dump_eeprom": "Dump EEPROM", + "wipe_eeprom": "Cancella EEPROM", + "eeprom_console_hint": "I dump della EEPROM sono mostrati nella console degli strumenti per sviluppatori.", + "configure_bluetooth": "Configura Bluetooth (opzionale)", + "bluetooth_info_1": "Il Bluetooth non è supportato su tutti i dispositivi.", + "bluetooth_info_2": "Alcuni dispositivi usano il Bluetooth Classico, altri il BLE (Bluetooth Low Energy)", + "bluetooth_info_3": "Metti l'RNode in modalità accoppiamento Bluetooth, quindi connettiti ad esso dalle impostazioni Bluetooth di Android.", + "bluetooth_info_4": "Una volta avviata una richiesta di accoppiamento da Android, dovrebbe apparire un PIN sul display dell'RNode.", + "bluetooth_info_5": "In Sideband dovrai abilitare Connect using Bluetooth in Hardware → RNode.", + "bluetooth_info_6": "Se il tuo dispositivo usa BLE, dovrai anche abilitare Device requires BLE in Hardware → RNode.", + "bluetooth_restart_warning": "Non dimenticare di riavviare Sideband affinché le impostazioni abbiano effetto!", + "enable": "Abilita", + "disable": "Disabilita", + "start_pairing": "Inizia Accoppiamento", + "configure_tnc": "Configura Modalità TNC (opzionale)", + "tnc_info_1": "La modalità TNC consente di utilizzare un RNode come TNC compatibile KISS sulla porta seriale.", + "tnc_info_2": "Questa modalità lo rende utilizzabile con software per radioamatori che possono comunicare con un TNC KISS tramite una porta seriale.", + "tnc_warning": "Devi lasciare disabilitata la modalità TNC quando usi RNode con app come MeshChat o Sideband.", + "frequency": "Frequenza (Hz)", + "bandwidth": "Larghezza di banda", + "tx_power": "Potenza Tx (dBm)", + "spreading_factor": "Spreading Factor", + "coding_rate": "Coding Rate", + "configure_display": "Configura Display", + "rotation": "Rotazione", + "reconditioning": "Ricondizionamento", + "start": "Inizia", + "stop": "Ferma", + "rotation_v180_warning": "L'impostazione della rotazione del display richiede il firmware v1.80+", + "errors": { + "failed_download": "Impossibile scaricare il firmware: {error}", + "firmware_not_found_in_release": "Firmware consigliato non trovato nell'ultima release.", + "web_serial_not_supported": "Il Web Serial non è supportato in questo browser. Usa Chrome, Edge o un altro browser basato su Chromium.", + "no_device_selected": "Nessun dispositivo selezionato. Seleziona una porta seriale.", + "failed_connect": "Connessione al dispositivo fallita: {error}", + "not_an_rnode": "Il dispositivo selezionato non è un RNode! Assicurati di aver selezionato la porta seriale corretta.", + "failed_dfu": "Impossibile entrare in modalità DFU: {error}", + "select_firmware_first": "Seleziona prima un file firmware (.zip).", + "failed_flash": "Flashing del firmware fallito: {error}", + "esptool_not_loaded": "impossibile caricare esptool-js. Ricarica la pagina e riprova.", + "no_flash_config": "La configurazione di flash non è disponibile per il dispositivo selezionato. Seleziona un altro dispositivo o controlla il file del firmware.", + "failed_extract": "File richiesto \"{file}\" non trovato nel file ZIP del firmware. Scarica il firmware corretto per il tuo dispositivo.", + "failed_detect": "Impossibile rilevare l'RNode. Assicurati che il dispositivo sia connesso e nella modalità corretta.", + "provisioned_already": "La eeprom è già inizializzata. Devi cancellarla per reinizializzarla!", + "select_product_first": "Seleziona prima un prodotto!", + "select_model_first": "Seleziona prima un modello!", + "not_provisioned": "La eeprom non è inizializzata. Devi farlo prima!", + "failed_provision": "inizializzazione fallita: {error}", + "failed_set_hash": "impossibile impostare l'hash del firmware: {error}", + "failed_reboot": "Impossibile riavviare l'RNode: {error}", + "failed_read_display": "Impossibile leggere il display: {error}", + "failed_dump_eeprom": "Impossibile eseguire il dump della EEPROM: {error}", + "failed_wipe_eeprom": "Impossibile cancellare la EEPROM: {error}", + "failed_enable_tnc": "Impossibile abilitare la modalità TNC: {error}", + "failed_disable_tnc": "Impossibile disabilitare la modalità TNC: {error}", + "failed_enable_bluetooth": "Impossibile abilitare il Bluetooth: {error}", + "failed_disable_bluetooth": "Impossibile disabilitare il Bluetooth: {error}", + "failed_start_pairing": "Impossibile avviare l'accoppiamento: {error}", + "failed_set_rotation": "Impossibile impostare la rotazione del display: {error}", + "failed_start_reconditioning": "Impossibile avviare il ricondizionamento del display: {error}" + }, + "alerts": { + "firmware_downloaded": "Il firmware consigliato è stato scaricato e caricato.", + "dfu_ready": "Il dispositivo dovrebbe ora essere in modalità DFU. Puoi procedere con il flashing del firmware.", + "flash_success": "Il firmware è stato flashato con successo!", + "rebooting": "La scheda si sta riavviando!", + "eeprom_wipe_confirm": "Sei sicuro di voler cancellare la eeprom su questo dispositivo? L'operazione richiederà circa 30 secondi. Verrà mostrato un avviso al termine.", + "eeprom_wiped": "la eeprom è stata cancellata!", + "eeprom_dumped": "Dump della EEPROM eseguito in console", + "rnode_detected": "Rilevato RNode v{version}", + "provision_success": "il dispositivo è stato inizializzato!", + "hash_success": "l'hash del firmware è stato impostato!", + "tnc_enabled": "La modalità TNC è stata abilitata!", + "tnc_disabled": "La modalità TNC è stata disabilitata!", + "bluetooth_enabled": "Il Bluetooth è stato abilitato!", + "bluetooth_disabled": "Il Bluetooth è stato disabilitato!", + "bluetooth_pairing_pin": "PIN Accoppiamento Bluetooth: {pin}", + "bluetooth_pairing_started": "Modalità accoppiamento avviata (30s)", + "rotation_updated": "Rotazione aggiornata", + "reconditioning_started": "Ricondizionamento avviato" + } + }, + "micron_editor": { + "title": "Editor Micron", + "description": "Modifica e visualizza l'anteprima del markup Micron con rendering live.", + "editor": "Editor", + "preview": "Anteprima", + "download": "Scarica", + "edit": "Modifica", + "view_preview": "Visualizza Anteprima", + "placeholder": "Inserisci qui il tuo markup Micron...", + "reset": "Reimposta", + "new_tab": "Nuova Scheda", + "rename_tab": "Rinomina Scheda", + "confirm_reset": "Sei sicuro di voler reimpostare l'editor? Tutte le schede e i contenuti andranno persi.", + "confirm_delete_tab": "Sei sicuro di voler eliminare questa scheda?", + "main_tab": "Principale", + "guide_tab": "Guida NomadNet", + "parser_by": "Utilizzando il Parser Micron di" + }, + "paper_message": { + "title": "Messaggio Cartaceo", + "description": "Genera e leggi messaggi cartacei LXMF firmati tramite codici QR." + }, + "rns_page_node": { + "title": "RNS Page Node", + "description": "Ospita pagine micron Nomadnet e condividi file con facilità." + }, + "rns_tunnel": { + "title": "RNS Tunnel", + "description": "Crea tunnel per il traffico IP regolare su collegamenti di rete Reticulum." + }, + "rns_filesync": { + "title": "RNS Filesync", + "description": "Condividi e sincronizza file in modo efficiente con altri peer della mesh." + }, + "bots": { + "title": "LXMFy Bot", + "description": "Gestisci bot automatizzati per echo, note e promemoria usando LXMFy." + } + }, + "ping": { + "title": "Ping Peer della Mesh", + "description": "Solo le destinazioni {code} rispondono al ping.", + "destination_hash": "Hash di Destinazione", + "timeout_seconds": "Timeout Ping (secondi)", + "start_ping": "Inizia Ping", + "stop": "Ferma", + "clear_results": "Cancella Risultati", + "drop_path": "Elimina Percorso", + "status": "Stato", + "running": "In esecuzione", + "idle": "Inattivo", + "last_rtt": "Ultimo RTT", + "last_error": "Ultimo Errore", + "console_output": "Output Console", + "streaming_responses": "Risposte seq in streaming in tempo reale", + "no_pings_yet": "Nessun ping ancora. Inizia una sessione per raccogliere dati RTT.", + "invalid_hash": "Hash di destinazione non valido!", + "timeout_must_be_number": "Il timeout deve essere un numero!" + }, + "rncp": { + "file_transfer": "Trasferimento File", + "title": "RNCP - Reticulum Network Copy", + "description": "Invia e ricevi file sulla rete Reticulum usando le risorse RNS. Questo strumento consente un trasferimento affidabile dei file tra i nodi della mesh anche su collegamenti ad alta latenza.", + "usage_steps": "Come usare RNCP:", + "step_1": "1. Per **ricevere** un file, vai alla scheda **Ascolta**, inserisci gli hash delle identità consentite (chi può inviarti file) e clicca su **Inizia Ascolto**.", + "step_2": "2. Per **inviare** un file, ottieni l'**Hash di Destinazione** di un nodo in ascolto, inserisci il **Percorso File Locale** e clicca su **Invia File**.", + "step_3": "3. Per **recuperare** un file, ottieni l'**Hash di Destinazione** di un nodo in ascolto con 'Consenti Recupero' abilitato, inserisci il **Percorso File Remoto** e clicca su **Recupera File**.", + "send_file": "Invia File", + "fetch_file": "Recupera File", + "listen": "Ascolta", + "destination_hash": "Hash di Destinazione", + "file_path": "Percorso File", + "timeout_seconds": "Timeout (secondi)", + "disable_compression": "Disabilita compressione", + "cancel": "Annulla", + "progress": "Avanzamento", + "invalid_hash": "Hash di destinazione non valido!", + "provide_file_path": "Fornisci un percorso file!", + "file_sent_successfully": "File inviato con successo. ID Trasferimento: {id}", + "failed_to_send": "Impossibile inviare il file", + "remote_file_path": "Percorso File Remoto", + "save_path_optional": "Percorso di Salvataggio (opzionale)", + "save_path_placeholder": "Lascia vuoto per la directory corrente", + "allow_overwrite": "Consenti sovrascrittura", + "provide_remote_file_path": "Fornisci un percorso file remoto!", + "file_fetched_successfully": "File recuperato con successo. Salvato in: {path}", + "failed_to_fetch": "Impossibile recuperare il file", + "allowed_hashes": "Hash Identità Consentiti (uno per riga)", + "fetch_jail_path": "Percorso Jail di Recupero (opzionale)", + "allow_fetch": "Consenti recupero", + "start_listening": "Inizia Ascolto", + "stop_listening": "Ferma Ascolto", + "listening_on": "In ascolto su:", + "provide_allowed_hash": "Fornisci almeno un hash di identità consentito!", + "failed_to_start_listener": "Impossibile avviare il listener" + }, + "rnprobe": { + "network_diagnostics": "Diagnostica di Rete", + "title": "RNProbe - Sonda Destinazione", + "description": "Sonda le destinazioni con dimensioni dei pacchetti personalizzate per testare la connettività e misurare l'RTT.", + "destination_hash": "Hash di Destinazione", + "full_destination_name": "Nome Destinazione Completo", + "probe_size_bytes": "Dimensione Sonda (byte)", + "number_of_probes": "Numero di Sonde", + "wait_between_probes": "Attesa tra le Sonde (secondi)", + "start_probe": "Inizia Sonda", + "stop": "Ferma", + "clear_results": "Cancella Risultati", + "summary": "Riepilogo", + "sent": "Inviate", + "delivered": "Consegnate", + "timeouts": "Timeout", + "failed": "Fallite", + "probe_results": "Risultati Sonda", + "probe_responses_realtime": "Risposte della sonda in tempo reale", + "no_probes_yet": "Nessuna sonda ancora. Inizia una sonda per testare la connettività.", + "probe_number": "Sonda #{number}", + "bytes": "byte", + "hops": "Salti", + "rtt": "RTT", + "rssi": "RSSI", + "snr": "SNR", + "quality": "Qualità", + "timeout": "Timeout", + "invalid_hash": "Hash di destinazione non valido!", + "provide_full_name": "Fornisci un nome destinazione completo!", + "failed_to_probe": "Impossibile sondare la destinazione" + }, + "rnstatus": { + "network_diagnostics": "Diagnostica di Rete", + "title": "RNStatus - Stato della Rete", + "description": "Visualizza le statistiche delle interfacce e le informazioni sullo stato della rete.", + "refresh": "Aggiorna", + "include_link_stats": "Includi Statistiche Collegamento", + "sort_by": "Ordina per:", + "none": "Nessuno", + "bitrate": "Bitrate", + "rx_bytes": "Byte RX", + "tx_bytes": "Byte TX", + "total_traffic": "Traffico Totale", + "announces": "Annunci", + "active_links": "Collegamenti Attivi: {count}", + "no_interfaces_found": "Nessuna interfaccia trovata. Clicca su aggiorna per caricare lo stato.", + "mode": "Modalità", + "rx_packets": "Pacchetti RX", + "tx_packets": "Pacchetti TX", + "clients": "Client", + "peers_reachable": "raggiungibile", + "noise_floor": "Rumore di Fondo", + "interference": "Interferenza", + "cpu_load": "Carico CPU", + "cpu_temp": "Temp CPU", + "memory_load": "Carico Memoria", + "battery": "Batteria", + "network": "Rete", + "incoming_announces": "Annunci in Entrata", + "outgoing_announces": "Annunci in Uscita", + "airtime": "Airtime", + "channel_load": "Carico Canale" + }, + "translator": { + "text_translation": "Traduzione Testo", + "title": "Traduttore", + "description": "Traduci testo usando l'API LibreTranslate o Argos Translate locale.", + "argos_translate": "Argos Translate", + "libretranslate": "LibreTranslate", + "api_server": "Server API LibreTranslate", + "api_server_description": "Inserisci l'URL di base del tuo server LibreTranslate (es. http://localhost:5000)", + "source_language": "Lingua Sorgente", + "auto_detect": "Rilevamento automatico", + "target_language": "Lingua Destinazione", + "select_target_language": "Seleziona lingua destinazione", + "argos_not_detected": "Argos Translate non rilevato", + "argos_not_detected_desc": "Per usare la traduzione locale, devi installare il pacchetto Argos Translate usando uno dei seguenti metodi:", + "method_pip_venv": "Metodo 1: pip (venv)", + "method_pipx": "Metodo 2: pipx", + "note_restart_required": "Nota: Dopo l'installazione, potrebbe essere necessario riavviare l'applicazione e installare i pacchetti lingua tramite la CLI di Argos Translate.", + "no_language_packages": "Nessun pacchetto lingua rilevato", + "no_language_packages_desc": "Argos Translate è installato ma non sono disponibili pacchetti lingua. Installa i pacchetti lingua usando uno dei seguenti comandi:", + "install_all_languages": "Installa tutte le lingue", + "install_specific_pair": "Installa coppia di lingue specifica (esempio: da Inglese a Tedesco)", + "after_install_note": "Dopo aver installato i pacchetti lingua, clicca su \"Aggiorna Lingue\" per ricaricare le lingue disponibili.", + "text_to_translate": "Testo da Tradurre", + "enter_text_placeholder": "Inserisci il testo da tradurre...", + "translate": "Traduci", + "swap": "Scambia", + "clear": "Cancella", + "translation": "Traduzione", + "source": "Sorgente", + "detected": "Rilevata", + "available_languages": "Lingue Disponibili", + "languages_loaded_from": "Le lingue sono caricate dall'API LibreTranslate o dai pacchetti Argos Translate.", + "refresh_languages": "Aggiorna Lingue", + "failed_load_languages": "Impossibile caricare le lingue. Assicurati che LibreTranslate sia in esecuzione o che Argos Translate sia installato.", + "failed_translate": "Traduzione fallita. Assicurati che LibreTranslate sia in esecuzione o che Argos Translate sia installato.", + "select_languages_warning": "Seleziona sia la lingua sorgente che quella di destinazione.", + "auto_detect_not_supported": "Il rilevamento automatico non è supportato con Argos Translate. Seleziona una lingua sorgente.", + "copied_to_clipboard": "Copiato negli appunti" + }, + "call": { + "phone": "Telefono", + "voicemail": "Segreteria", + "settings": "Impostazioni", + "unknown": "Sconosciuto", + "call_ended": "Chiamata Terminata", + "call_declined": "Chiamata Rifiutata", + "initiation": "Inizializzazione...", + "send_to_voicemail": "Invia alla Segreteria", + "incoming_call": "Chiamata in Arrivo...", + "busy": "Occupato...", + "rejected": "Rifiutata...", + "calling": "Chiamata in corso...", + "available": "Disponibile...", + "ringing": "Squilla...", + "connecting": "Connessione...", + "connected": "Connesso", + "accept": "Accetta", + "decline": "Rifiuta", + "hangup": "Riattacca", + "answer_call": "Rispondi alla Chiamata", + "decline_call": "Rifiuta Chiamata", + "hangup_call": "Termina Chiamata", + "mute_mic": "Disattiva Mic", + "unmute_mic": "Attiva Mic", + "mute_speaker": "Disattiva Altoparlante", + "unmute_speaker": "Attiva Altoparlante", + "telephone": "Telefono", + "enter_identity_hash_to_call": "Inserisci un'identità da chiamare.", + "identity_hash": "Hash Identità", + "call_history": "Cronologia Chiamate", + "call_back": "Richiama", + "no_voicemails": "Nessun Messaggio in Segreteria", + "voicemails_will_appear_here": "Quando qualcuno ti lascia un messaggio, apparirà qui.", + "voicemail_inbox": "Messaggi Ricevuti", + "messages": "Messaggi", + "delete": "Elimina", + "voicemail_settings": "Impostazioni Segreteria", + "dependencies_missing": "Dipendenze Mancanti", + "voicemail_requires_espeak": "La segreteria richiede `espeak-ng` per generare i saluti. Installalo sul tuo sistema.", + "voicemail_requires_ffmpeg": "La segreteria richiede `ffmpeg` per elaborare i file audio. Installalo sul tuo sistema.", + "enable_voicemail": "Abilita Segreteria", + "enable_voicemail_description": "Accetta chiamate automaticamente e registra messaggi", + "greeting_message": "Messaggio di Saluto", + "enter_greeting_text": "Inserisci il testo del saluto...", + "greeting_text_description": "Questo testo verrà convertito in voce usando eSpeak NG.", + "tts_speed": "Velocità TTS", + "tts_pitch": "Tonalità TTS", + "tts_voice": "Voce TTS", + "tts_word_gap": "Intervallo Parole TTS", + "save_and_generate": "Salva e Genera", + "generating": "Generazione...", + "preview_greeting": "Anteprima Saluto", + "stop_preview": "Ferma Anteprima", + "answer_delay_seconds": "Ritardo Risposta (s)", + "max_recording_seconds": "Registrazione Max (s)", + "recording_voicemail": "Registrazione Messaggio", + "call_status": "Stato Chiamata", + "call_recording": "Registratore Chiamate", + "call_recording_description": "Registra le chiamate vocali in memoria", + "recordings": "Registrazioni", + "no_recordings": "Nessuna registrazione trovata", + "remote_rx": "Remoto (RX)", + "local_tx": "Locale (TX)", + "download_rx": "Scarica RX", + "download_tx": "Scarica TX", + "default_quality": "Qualità Predefinita", + "active_call": "Chiamata Attiva", + "status": "Stato", + "failed_to_answer_call": "Impossibile rispondere alla chiamata", + "failed_to_hangup_call": "Impossibile terminare la chiamata", + "failed_to_toggle_microphone": "Impossibile attivare/disattivare il microfono", + "failed_to_toggle_speaker": "Impossibile attivare/disattivare l'altoparlante", + "failed_to_switch_audio_profile": "Impossibile cambiare il profilo audio", + "failed_to_initiate_call": "Impossibile avviare la chiamata", + "enter_identity_hash_to_call_error": "Inserisci un'identità da chiamare", + "failed_to_save_settings": "Impossibile salvare le impostazioni", + "do_not_disturb": "Non Disturbare", + "load_more": "Carica Altri", + "go_to_phone_page": "Vai alla Pagina Telefono", + "search_history": "Cerca nella cronologia...", + "allow_calls_from_contacts_only": "Consenti chiamate solo dai contatti", + "settings_saved": "Impostazioni salvate", + "greeting_generated_successfully": "Saluto generato con successo", + "failed_to_generate_greeting": "Impossibile generare il saluto", + "no_greeting_audio_found": "Nessun audio del saluto trovato. Generane uno prima.", + "voicemail_deleted": "Messaggio eliminato", + "failed_to_delete_voicemail": "Impossibile eliminare il messaggio", + "ringtone": "Suoneria", + "ringtone_settings": "Impostazioni Suoneria", + "enable_custom_ringtone": "Abilita Suoneria Personalizzata", + "enable_custom_ringtone_description": "Riproduci un file audio personalizzato per tutte le chiamate in arrivo", + "upload_ringtone": "Carica Suoneria", + "uploading_ringtone": "Caricamento Suoneria...", + "no_custom_ringtone_uploaded": "Nessuna suoneria personalizzata caricata", + "supports_audio_formats": "Supporta MP3, OGG, WAV, M4A, FLAC. Verrà convertito in Opus.", + "preview_ringtone": "Anteprima Suoneria", + "remove_ringtone": "Rimuovi Suoneria", + "ringtone_uploaded_successfully": "Suoneria caricata con successo", + "failed_to_upload_ringtone": "Impossibile caricare la suoneria", + "ringtone_deleted": "Suoneria eliminata", + "failed_to_delete_ringtone": "Impossibile eliminare la suoneria", + "no_ringtone_audio_found": "Nessun audio della suoneria trovato. Caricane uno prima.", + "ringtone_volume": "Volume Suoneria", + "default_ringtone": "Suoneria Predefinita", + "ringtone_for_non_contacts": "Suoneria per chi non è nei contatti", + "primary_system_default": "Principale (Predefinita di Sistema)", + "random": "Casuale", + "edit_contact": "Modifica Contatto", + "add_contact": "Aggiungi Contatto", + "contact_name": "Nome Contatto", + "preferred_ringtone": "Suoneria Preferita", + "default_global_setting": "Predefinita (Impostazione Globale)", + "uploaded_ringtones": "Suonerie Caricate", + "save_contact": "Salva Contatto", + "primary_ringtone_set": "Suoneria principale impostata", + "failed_to_set_primary_ringtone": "Impossibile impostare la suoneria principale", + "failed_to_update_ringtone_name": "Impossibile aggiornare il nome della suoneria", + "failed_to_play_ringtone": "Impossibile riprodurre la suoneria", + "failed_to_play_voicemail": "Impossibile riprodurre il messaggio", + "web_audio_not_available": "Audio web non disponibile", + "no_audio_input_found": "Nessun dispositivo audio di input trovato. Controlla il microfono e i permessi.", + "microphone_permission_denied": "Permesso microfono negato. Consenti l'accesso e riprova.", + "failed_to_update_dnd": "Impossibile aggiornare lo stato Non Disturbare", + "failed_to_update_call_settings": "Impossibile aggiornare le impostazioni di chiamata", + "failed_to_update_recording_status": "Impossibile aggiornare lo stato di registrazione chiamata", + "call_history_cleared": "Cronologia chiamate cancellata", + "failed_to_clear_call_history": "Impossibile cancellare la cronologia chiamate", + "identity_banished": "Identità esiliata", + "failed_to_banish_identity": "Impossibile esiliare l'identità", + "name_and_hash_required": "Nome e hash identità richiesti", + "contact_updated": "Contatto aggiornato", + "contact_added": "Contatto aggiunto", + "contact_deleted": "Contatto eliminato", + "failed_to_delete_contact": "Impossibile eliminare il contatto", + "hash_copied": "Hash copiato negli appunti", + "failed_to_copy_hash": "Impossibile copiare l'hash", + "greeting_uploaded_successfully": "Saluto caricato con successo", + "greeting_deleted": "Saluto eliminato", + "failed_to_delete_greeting": "Impossibile eliminare il saluto", + "failed_to_start_recording_greeting": "Impossibile avviare la registrazione del saluto", + "greeting_recorded_from_mic": "Saluto registrato dal mic", + "failed_to_stop_recording_greeting": "Impossibile fermare la registrazione del saluto", + "failed_to_load_recording": "Impossibile caricare l'audio della registrazione", + "recording_deleted": "Registrazione eliminata", + "failed_to_delete_recording": "Impossibile eliminare la registrazione", + "call_sent_to_voicemail": "Chiamata inviata alla segreteria", + "failed_to_send_to_voicemail": "Impossibile inviare la chiamata alla segreteria", + "failed_load_audio_edit": "Impossibile caricare l'audio per la modifica", + "ringtone_saved": "Suoneria salvata con successo", + "failed_save_ringtone": "Impossibile salvare la suoneria modificata" + }, + "tutorial": { + "title": "Guida Introduttiva", + "welcome": "Benvenuto in", + "welcome_desc": "Il futuro della comunicazione off-grid. Sicuro, decentralizzato e inarrestabile.", + "security": "Sicurezza e Prestazioni", + "security_desc": "Miglioramenti massicci in velocità, sicurezza e recupero dai crash.", + "security_desc_page": "Miglioramenti massicci in velocità, sicurezza e integrità con recupero dai crash integrato.", + "maps": "Mappe", + "maps_desc": "OpenLayers con supporto MBTiles (esportazione e supporto offline) e endpoint API personalizzati.", + "maps_desc_page": "Supporto OpenLayers con MBTiles offline (esportazione e supporto offline) e endpoint API personalizzati per mappe online.", + "voice": "Voce LXST Completa", + "voice_desc": "Segreteria, suonerie, rubrica e condivisione contatti.", + "voice_desc_page": "Chiamate vocali cristalline su mesh. Segreteria, suonerie personalizzate e scoperta rubrica.", + "tools": "Strumenti Avanzati", + "tools_desc": "Editor Micron, NomadNet, strumenti RNS, Documentazione.", + "tools_desc_page": "Editor Micron, nodi NomadNet, strumenti RNS e documentazione integrata.", + "archiver": "Archiviatore", + "archiver_desc": "Archiviazione pagine manuale e automatizzata.", + "archiver_desc_page": "Strumenti di archiviazione pagine manuali e automatizzati per la navigazione offline.", + "banishment": "Esilio", + "banishment_desc": "Esilia persone e nodi fastidiosi, con supporto per il blocco degli annunci a livello di blackhole RNS", + "palette": "Tavolozza Comandi + Scorciatoie", + "palette_desc": "Naviga istantaneamente ovunque e personalizza le scorciatoie.", + "palette_desc_page": "Naviga nell'intera applicazione e personalizza il tuo flusso di lavoro con scorciatoie istantanee.", + "i18n": "Supporto i18n", + "i18n_desc": "Disponibile in Inglese, Tedesco e Russo.", + "i18n_desc_page": "Supporto completo all'internazionalizzazione per le lingue Inglese, Tedesco e Russo.", + "more_features": "+ molte altre funzioni!", + "connect": "Connettiti alla Mesh", + "connect_desc": "Per inviare messaggi, devi connetterti a un'interfaccia Reticulum.", + "connect_desc_page": "Usa una delle reti pubbliche qui sotto o aggiungi un'interfaccia personalizzata dalla pagina Interfacce.", + "suggested_networks": "Reti Pubbliche Suggerite", + "suggested_relays": "Relè Suggeriti", + "use": "Usa", + "online": "Online", + "custom_interfaces": "Interfacce Personalizzate", + "custom_interfaces_desc": "Vuoi aggiungere un'interfaccia specifica? Vai alla pagina Interfacce per configurare una connessione personalizzata.", + "custom_interfaces_desc_page": "Per qualsiasi relè privato o hardware gestito da te, aggiungilo tramite la pagina Interfacce dedicata.", + "open_interfaces": "Apri la pagina Interfacce", + "learn_create": "Impara e Crea", + "learn_create_desc": "Scopri come usare MeshChatX al massimo delle sue potenzialità.", + "learn_create_desc_page": "Scopri come usare MeshChatX al massimo delle sue potenzialità e crea i tuoi contenuti.", + "documentation": "Documentazione", + "documentation_desc": "Leggi la documentazione ufficiale di MeshChatX e Reticulum.", + "documentation_desc_page": "Guide complete per MeshChatX e lo stack di rete Reticulum sottostante.", + "meshchatx_docs": "Doc MeshChatX", + "reticulum_docs": "Doc Reticulum", + "read_meshchatx_docs": "Leggi Doc MeshChatX", + "reticulum_manual": "Manuale di Rete Reticulum", + "micron_editor": "Editor Micron", + "micron_editor_desc": "Dai un'occhiata all'Editor Micron per una guida sulla creazione di pagine mesh-native.", + "micron_editor_desc_page": "Impara come creare pagine mesh-native e contenuti interattivi usando il linguaggio di markup Micron.", + "open_micron_editor": "Apri Editor Micron", + "paper_messages": "Esplora Nodi NomadNet", + "paper_messages_desc": "Sfoglia pagine e servizi decentralizzati.", + "send_messages": "Invia Messaggi", + "send_messages_desc": "Inizia una conversazione sicura.", + "explore_nodes": "Visualizza Nodi", + "explore_nodes_desc": "Visualizza la mappa e la topologia della rete.", + "voice_calls": "Chiamate Vocali", + "voice_calls_desc": "Prova il fantastico editor di suonerie!", + "ready": "Pronto per Iniziare!", + "ready_desc": "Tutto è configurato. Devi riavviare l'applicazione affinché le modifiche abbiano effetto.", + "ready_desc_page": "MeshChatX è ora configurato. Devi riavviare l'applicazione per finalizzare la connessione.", + "docker_note": "Se stai usando Docker, assicurati di riavviare il container", + "restart_required": "Riavvio Richiesto", + "restart_desc_page": "Se stai usando Docker, assicurati di riavviare il container. Le app native si riavvieranno automaticamente.", + "back": "Indietro", + "skip": "Salta", + "next": "Avanti", + "restart_start": "Avvia MeshChatX", + "skip_setup": "Salta Configurazione", + "continue": "Continua", + "skip_confirm": "Sei sicuro di voler saltare la configurazione? Dovrai aggiungere le interfacce manualmente in seguito.", + "discovery_question": "Vuoi usare la scoperta delle interfacce della comunità e la connessione automatica?", + "discovery_desc": "Questo consente a MeshChatX di trovare e connettersi automaticamente ai nodi pubblici della comunità vicino a te o su internet.", + "yes": "Sì, usa la scoperta", + "no": "No, configurazione manuale", + "discovery_enabled": "Scoperta della comunità abilitata", + "failed_enable_discovery": "Impossibile abilitare la scoperta" + }, + "command_palette": { + "search_placeholder": "Cerca comandi, naviga o trova peer...", + "no_results": "Nessun risultato trovato per \"{query}\"", + "group_actions": "Azioni", + "group_recent": "Peer Recenti", + "group_contacts": "Contatti", + "footer_navigate": "Naviga", + "footer_select": "Seleziona", + "nav_messages": "Messaggi", + "nav_messages_desc": "Apri la pagina dei messaggi", + "nav_nomad": "Nomad Network", + "nav_nomad_desc": "Sfoglia le pagine Nomad Network", + "nav_map": "Mappa", + "nav_map_desc": "Visualizza la mappa della topologia di rete", + "nav_paper": "Messaggi Cartacei", + "nav_paper_desc": "Genera messaggi offline", + "nav_call": "Chiamate Vocali", + "nav_call_desc": "Apri la pagina delle chiamate vocali", + "nav_settings": "Impostazioni", + "nav_settings_desc": "Apri la pagina delle impostazioni", + "nav_ping": "Ping", + "nav_ping_desc": "Ping nodi di rete", + "nav_rnprobe": "RNProbe", + "nav_rnprobe_desc": "Sonda i nodi Reticulum", + "nav_rncp": "RNCP", + "nav_rncp_desc": "Reticulum Control Protocol", + "nav_rnstatus": "RNStatus", + "nav_rnstatus_desc": "Visualizza lo stato di Reticulum", + "nav_rnpath": "RNPath", + "nav_rnpath_desc": "Visualizza i percorsi di rete", + "nav_rnpath_trace": "RNPath Trace", + "nav_rnpath_trace_desc": "Visualizza i percorsi di rete", + "nav_translator": "Traduttore", + "nav_translator_desc": "Traduci messaggi", + "nav_forwarder": "Inoltro", + "nav_forwarder_desc": "Strumento di inoltro messaggi", + "nav_documentation": "Documentazione", + "nav_documentation_desc": "Visualizza la documentazione", + "nav_micron_editor": "Editor Micron", + "nav_micron_editor_desc": "Crea pagine mesh-native", + "nav_rnode_flasher": "Flasher RNode", + "nav_rnode_flasher_desc": "Flasha il firmware RNode", + "nav_debug_logs": "Log di Debug", + "nav_debug_logs_desc": "Visualizza i log di debug", + "action_sync": "Sincronizza Messaggi", + "action_sync_desc": "Sincronizza con il nodo di propagazione", + "action_compose": "Componi Messaggio", + "action_compose_desc": "Inizia un nuovo messaggio", + "action_orbit": "Attiva/Disattiva Orbita", + "action_orbit_desc": "Attiva o disattiva la modalità orbita", + "action_bouncing_balls": "Palle Rimbalzanti", + "action_bouncing_balls_desc": "Attiva o disattiva la modalità palle rimbalzanti", + "action_getting_started": "Guida Introduttiva", + "action_getting_started_desc": "Mostra la guida introduttiva", + "action_changelog": "Changelog", + "action_changelog_desc": "Visualizza le novità" + } +} diff --git a/meshchatx/src/frontend/locales/ru.json b/meshchatx/src/frontend/locales/ru.json index e878f3b..af5494a 100644 --- a/meshchatx/src/frontend/locales/ru.json +++ b/meshchatx/src/frontend/locales/ru.json @@ -194,9 +194,42 @@ "emergency_mode_active": "Аварийный режим активен — используется база данных в оперативной памяти и ограниченные службы.", "blackhole_integration_enabled": "Интеграция Blackhole", "blackhole_integration_description": "Автоматически блокировать (blackhole) личности на транспортном уровне Reticulum при изгнании пользователей в MeshChatX.", - "failed_announce": "failed to announce", - "search_settings": "Search settings...", - "show_qr": "Show QR Code" + "failed_announce": "ошибка анонса", + "search_settings": "Поиск настроек...", + "show_qr": "Показать QR-код", + "csp_settings": "Политика безопасности контента (CSP)", + "csp_description": "Вручную добавьте разрешенные домены и источники для различных типов ресурсов. Это полезно для пользовательских серверов тайлов, ботов или внешних интеграций.", + "csp_extra_connect_src": "Дополнительные источники соединений", + "csp_extra_connect_src_description": "Дополнительные источники для соединений fetch/websocket (например, https://api.example.com).", + "csp_extra_img_src": "Дополнительные источники изображений", + "csp_extra_img_src_description": "Дополнительные источники для изображений и тайлов.", + "csp_extra_frame_src": "Дополнительные источники фреймов", + "csp_extra_frame_src_description": "Дополнительные источники для iframe.", + "csp_extra_script_src": "Дополнительные источники скриптов", + "csp_extra_script_src_description": "Дополнительные источники для скриптов (только для продвинутых пользователей).", + "csp_extra_style_src": "Дополнительные источники стилей", + "csp_extra_style_src_description": "Дополнительные источники для таблиц стилей.", + "location": "Местоположение", + "location_source": "Источник местоположения", + "location_source_browser": "Автоматически (браузер)", + "location_source_manual": "Вручную", + "location_source_browser_desc": "Использует API геолокации вашего браузера. Примечание: в десктопном приложении это может использовать сервисы Google.", + "location_source_manual_desc": "Используйте координаты, введенные вручную, для максимальной конфиденциальности.", + "location_manual_lat": "Широта", + "location_manual_lon": "Долгота", + "location_manual_alt": "Высота (м)", + "telemetry_enabled": "Телеметрия включена", + "telemetry_description": "Разрешить MeshChatX отправлять и получать телеметрические данные. Это включает ответ на запросы местоположения от доверенных узлов.", + "telemetry_trusted_peers": "Доверенные телеметрические узлы", + "telemetry_no_trusted_peers": "Нет настроенных доверенных узлов. Добавьте узлы в список доверенных из меню чата, чтобы разрешить им запрашивать ваше местоположение.", + "telemetry_revoke_trust": "Отозвать доверие", + "telemetry_trust_revoked": "Доверие телеметрии для {name} отозвано", + "telemetry_trust_granted_alert": "Узел теперь является доверенным для телеметрии.", + "telemetry_trust_revoked_alert": "Доверие телеметрии отозвано.", + "telemetry_trust_failed": "Не удалось обновить доверие телеметрии.", + "telemetry_trust_revoke": "Отозвать доверие телеметрии", + "telemetry_trust_grant": "Доверять телеметрии", + "location_manage_desc": "Управление тем, как передается ваше местоположение." }, "common": { "open": "Открыть", @@ -362,6 +395,7 @@ "export_all": "Экспорт всех", "search_placeholder": "Поиск по имени, типу, хосту...", "all": "Все", + "connected_only": "Только подключенные", "all_types": "Все типы", "no_interfaces_found": "Интерфейсы не найдены", "no_interfaces_description": "Измените параметры поиска или добавьте новый интерфейс.", @@ -572,7 +606,10 @@ "no_contacts_telephone": "No contacts found in telephone", "failed_load_contacts": "Failed to load contacts", "location_request_sent": "Location request sent", - "failed_send_location_request": "Failed to send location request", + "failed_send_location_request": "Не удалось отправить запрос местоположения", + "fetching_location": "Получение местоположения...", + "location_sent": "Местоположение успешно отправлено", + "location_requested": "Запрошено местоположение", "remove_image_confirm": "Are you sure you want to remove this image attachment?", "failed_start_recording": "failed to start recording", "remove_audio_confirm": "Are you sure you want to remove this audio attachment?", @@ -740,6 +777,21 @@ "queues_purged": "Announce queues purged", "failed_purge": "Failed to purge queues" }, + "rnpath_trace": { + "title": "RNS Трассировка пути", + "description": "Визуализация пути и переходов к любому хэшу назначения в сети.", + "destination_hash": "Хэш назначения", + "placeholder": "Введите 32-символьный хэш...", + "trace": "Трассировать путь", + "tracing": "Трассировка пути через сеть...", + "total_hops": "Всего переходов", + "interface": "Выходной интерфейс", + "next_hop": "Следующий переход", + "ready_title": "Трассировка пути", + "ready_desc": "Введите хэш назначения выше, чтобы увидеть, как пакеты проходят через сеть.", + "unknown_hops": "{count} промежуточных переходов", + "ping_test": "Проверить с помощью Ping" + }, "translator": { "title": "Translator", "description": "Перевод текста через LibreTranslate API или локальный Argos Translate." @@ -897,15 +949,15 @@ "description": "Создание и чтение подписанных бумажных сообщений LXMF через QR-коды." }, "rns_page_node": { - "title": "RNS Page-узел", + "title": "RNS Page Node", "description": "Хостинг микрон-страниц Nomadnet и удобный обмен файлами." }, "rns_tunnel": { - "title": "RNS-туннель", + "title": "RNS Tunnel", "description": "Туннелирование обычного IP-трафика через сеть Reticulum." }, "rns_filesync": { - "title": "RNS-файлообмен", + "title": "RNS Filesync", "description": "Эффективный обмен и синхронизация файлов с другими узлами mesh." }, "bots": { @@ -1328,14 +1380,16 @@ "nav_settings_desc": "Открыть страницу настроек", "nav_ping": "Ping", "nav_ping_desc": "Пинг узлов сети", - "nav_rnprobe": "RN Probe", + "nav_rnprobe": "RNProbe", "nav_rnprobe_desc": "Зондирование узлов Reticulum", - "nav_rncp": "RN CP", + "nav_rncp": "RNCP", "nav_rncp_desc": "Reticulum Control Protocol", - "nav_rnstatus": "RN Status", + "nav_rnstatus": "RNStatus", "nav_rnstatus_desc": "Просмотр статуса Reticulum", - "nav_rnpath": "RN Path", + "nav_rnpath": "RNPath", "nav_rnpath_desc": "Просмотр сетевых путей", + "nav_rnpath_trace": "Трассировка пути", + "nav_rnpath_trace_desc": "Визуализация сетевых путей", "nav_translator": "Переводчик", "nav_translator_desc": "Перевод сообщений", "nav_forwarder": "Форвардер", @@ -1450,4 +1504,4 @@ "banishment_lifted": "Banishment lifted successfully", "failed_lift_banishment": "Failed to lift banishment" } -} \ No newline at end of file +} From ecfd124f8f5f3a0742c8930b577246741889f9c2 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Wed, 7 Jan 2026 19:20:04 -0600 Subject: [PATCH 203/234] chore(workflows): remove push and pull_request triggers from bench.yml --- .gitea/workflows/bench.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.gitea/workflows/bench.yml b/.gitea/workflows/bench.yml index a441316..5a54026 100644 --- a/.gitea/workflows/bench.yml +++ b/.gitea/workflows/bench.yml @@ -1,10 +1,6 @@ name: Benchmarks on: - push: - branches: - - "*" - pull_request: workflow_dispatch: jobs: From e2586e905267c1927e4f6dbdea9a130865d37578 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Wed, 7 Jan 2026 19:20:56 -0600 Subject: [PATCH 204/234] feat(tests): add comprehensive telemetry and interface tests - Introduced new test files for telemetry functionality, including integration, fuzzing, and extended tests to ensure robustness and performance. - Added tests for parsing LXMF display names and telemetry data, addressing potential bugs and ensuring correct handling of various input formats. - Implemented performance tests for the InterfacesPage component, validating rendering efficiency with a large number of discovered interfaces. - Enhanced existing tests for markdown rendering and link utilities to cover additional edge cases and improve stability. --- tests/backend/test_csp_logic.py | 113 ++++++++++ .../test_display_name_and_telemetry.py | 96 ++++++++ tests/backend/test_fuzzing.py | 32 +++ tests/backend/test_fuzzing_telemetry.py | 99 ++++++++ tests/backend/test_telemetry_extended.py | 47 ++++ tests/backend/test_telemetry_integration.py | 130 +++++++++++ tests/frontend/InterfacesPerformance.test.js | 146 ++++++++++++ tests/frontend/LanguageSelector.test.js | 3 +- tests/frontend/LinkUtils.test.js | 47 ++++ tests/frontend/MarkdownRenderer.test.js | 212 ++++++++++++++++++ tests/frontend/Performance.test.js | 12 + 11 files changed, 936 insertions(+), 1 deletion(-) create mode 100644 tests/backend/test_csp_logic.py create mode 100644 tests/backend/test_display_name_and_telemetry.py create mode 100644 tests/backend/test_fuzzing_telemetry.py create mode 100644 tests/backend/test_telemetry_extended.py create mode 100644 tests/backend/test_telemetry_integration.py create mode 100644 tests/frontend/InterfacesPerformance.test.js create mode 100644 tests/frontend/LinkUtils.test.js create mode 100644 tests/frontend/MarkdownRenderer.test.js diff --git a/tests/backend/test_csp_logic.py b/tests/backend/test_csp_logic.py new file mode 100644 index 0000000..da61cc4 --- /dev/null +++ b/tests/backend/test_csp_logic.py @@ -0,0 +1,113 @@ +from unittest.mock import MagicMock, patch, AsyncMock + +import pytest +import RNS +from aiohttp import web + +from meshchatx.meshchat import ReticulumMeshChat + + +@pytest.fixture +def mock_rns_minimal(): + with ( + patch("RNS.Reticulum") as mock_rns, + patch("RNS.Transport"), + patch("LXMF.LXMRouter"), + patch("meshchatx.meshchat.get_file_path", return_value="/tmp/mock_path"), + ): + mock_rns_instance = mock_rns.return_value + mock_rns_instance.configpath = "/tmp/mock_config" + mock_rns_instance.is_connected_to_shared_instance = False + mock_rns_instance.transport_enabled.return_value = True + + mock_id = MagicMock(spec=RNS.Identity) + mock_id.hash = b"test_hash_32_bytes_long_01234567" + mock_id.hexhash = mock_id.hash.hex() + mock_id.get_private_key.return_value = b"test_private_key" + yield mock_id + + +@pytest.mark.asyncio +async def test_csp_header_logic(mock_rns_minimal, tmp_path): + storage_dir = str(tmp_path / "storage") + config_dir = str(tmp_path / "config") + + with patch("meshchatx.meshchat.generate_ssl_certificate"): + app_instance = ReticulumMeshChat( + identity=mock_rns_minimal, + storage_dir=storage_dir, + reticulum_config_dir=config_dir, + ) + + # Mock the config values + app_instance.config.csp_extra_connect_src.set("https://api.example.com") + app_instance.config.map_tile_server_url.set( + "https://tiles.example.com/{z}/{x}/{y}.png" + ) + + # Mock a request and handler + request = MagicMock(spec=web.Request) + request.path = "/" + request.app = {} + + # We need to mock the handler to return a real response + async def mock_handler(req): + return web.Response(text="test") + + # Call _define_routes to get the security_middleware + routes = web.RouteTableDef() + _, _, security_middleware = app_instance._define_routes(routes) + + response = await security_middleware(request, mock_handler) + + csp = response.headers.get("Content-Security-Policy", "") + assert "https://api.example.com" in csp + assert "https://tiles.example.com" in csp + assert "default-src 'self'" in csp + + +@pytest.mark.asyncio +async def test_config_update_csp(mock_rns_minimal, tmp_path): + storage_dir = str(tmp_path / "storage") + config_dir = str(tmp_path / "config") + + with patch("meshchatx.meshchat.generate_ssl_certificate"): + app_instance = ReticulumMeshChat( + identity=mock_rns_minimal, + storage_dir=storage_dir, + reticulum_config_dir=config_dir, + ) + + # Find the config update handler + config_update_handler = None + for route in app_instance.get_routes(): + if route.path == "/api/v1/config" and route.method == "PATCH": + config_update_handler = route.handler + break + + assert config_update_handler is not None + + # Mock request with new CSP settings + request_data = { + "csp_extra_connect_src": "https://api1.com, https://api2.com", + "csp_extra_img_src": "https://img.com", + } + + request = MagicMock(spec=web.Request) + # request.json() must be awaited, so it should return an awaitable + request.json = AsyncMock(return_value=request_data) + + # To avoid the JSON serialization error of MagicMock in get_config_dict, + # we mock get_config_dict to return a serializable dict. + with patch.object( + app_instance, "get_config_dict", return_value={"status": "ok"} + ): + with patch.object(app_instance, "send_config_to_websocket_clients"): + response = await config_update_handler(request) + assert response.status == 200 + + assert ( + app_instance.config.csp_extra_connect_src.get() + == "https://api1.com, https://api2.com" + ) + assert app_instance.config.csp_extra_img_src.get() == "https://img.com" diff --git a/tests/backend/test_display_name_and_telemetry.py b/tests/backend/test_display_name_and_telemetry.py new file mode 100644 index 0000000..5b14cc3 --- /dev/null +++ b/tests/backend/test_display_name_and_telemetry.py @@ -0,0 +1,96 @@ +import base64 +from unittest.mock import MagicMock, patch +import LXMF +from meshchatx.src.backend.meshchat_utils import parse_lxmf_display_name +from meshchatx.src.backend.telemetry_utils import Telemeter +import RNS.vendor.umsgpack as msgpack + + +def test_parse_lxmf_display_name_bug_fix(): + """ + Test that parse_lxmf_display_name handles both bytes and strings + in the msgpack list, fixing the 'str' object has no attribute 'decode' bug. + """ + # 1. Test with bytes (normal case) + display_name_bytes = b"Test User" + app_data_list = [display_name_bytes, None, None] + app_data_bytes = msgpack.packb(app_data_list) + app_data_base64 = base64.b64encode(app_data_bytes).decode() + + assert parse_lxmf_display_name(app_data_base64) == "Test User" + + # 2. Test with string (the bug case where msgpack already decoded it) + # We simulate this by mocking msgpack.unpackb to return strings + display_name_str = "Test User Str" + app_data_list_str = [display_name_str, None, None] + + with patch("RNS.vendor.umsgpack.unpackb", return_value=app_data_list_str): + # The input app_data_base64 doesn't really matter much here since we mock unpackb, + # but it must be valid base64 for the initial decode. + assert parse_lxmf_display_name(app_data_base64) == "Test User Str" + + # 3. Test with bytes directly passed (as in meshchat.py updated call) + assert parse_lxmf_display_name(app_data_bytes) == "Test User" + + +def test_lxmf_telemetry_decoding(): + """ + Test decoding of LXMF telemetry fields. + """ + # Create some dummy telemetry data + ts = 1736264575 + lat, lon = 52.5200, 13.4050 + + # Use Telemeter.pack to create valid telemetry bytes + location = { + "latitude": lat, + "longitude": lon, + "altitude": 100, + "speed": 10, + "bearing": 90, + "accuracy": 5, + "last_update": ts, + } + + packed_telemetry = Telemeter.pack(time_utc=ts, location=location) + + # Decode it back + unpacked = Telemeter.from_packed(packed_telemetry) + + assert unpacked is not None + assert unpacked["time"]["utc"] == ts + assert unpacked["location"]["latitude"] == lat + assert unpacked["location"]["longitude"] == lon + assert unpacked["location"]["altitude"] == 100.0 + assert unpacked["location"]["speed"] == 10.0 + assert unpacked["location"]["bearing"] == 90.0 + assert unpacked["location"]["accuracy"] == 5.0 + + +def test_lxmf_telemetry_mapping_in_app(): + """ + Test how the app handles telemetry fields from an LXMF message. + """ + # Mock lxmf_message + lxmf_message = MagicMock(spec=LXMF.LXMessage) + source_hash = b"\x01" * 32 + lxmf_message.source_hash = source_hash + lxmf_message.hash = b"\x02" * 32 + + ts = 1736264575 + packed_telemetry = Telemeter.pack( + time_utc=ts, location={"latitude": 1.23, "longitude": 4.56} + ) + + lxmf_message.get_fields.return_value = {LXMF.FIELD_TELEMETRY: packed_telemetry} + + # Test unpacking directly using the same logic as in meshchat.py + fields = lxmf_message.get_fields() + assert LXMF.FIELD_TELEMETRY in fields + + telemetry_data = fields[LXMF.FIELD_TELEMETRY] + unpacked = Telemeter.from_packed(telemetry_data) + + assert unpacked["time"]["utc"] == ts + assert unpacked["location"]["latitude"] == 1.23 + assert unpacked["location"]["longitude"] == 4.56 diff --git a/tests/backend/test_fuzzing.py b/tests/backend/test_fuzzing.py index 708d803..37686e7 100644 --- a/tests/backend/test_fuzzing.py +++ b/tests/backend/test_fuzzing.py @@ -103,6 +103,38 @@ def test_display_name_parsing_fuzzing(app_data_base64): pytest.fail(f"Display name parsing crashed with data {app_data_base64}: {e}") +@settings(suppress_health_check=[HealthCheck.function_scoped_fixture], deadline=None) +@given( + fields_data=st.dictionaries( + st.integers(min_value=0, max_value=255), st.binary(min_size=0, max_size=1000) + ) +) +def test_lxmf_fields_parsing_fuzzing(fields_data): + """Fuzz the parsing of LXMF message fields.""" + try: + # This simulates how meshchat.py processes fields in on_lxmf_delivery + for field_id, field_data in fields_data.items(): + if field_id == 0x01: # FIELD_COMMANDS + try: + import umsgpack + + commands = umsgpack.unpackb(field_data) + if isinstance(commands, list): + for cmd in commands: + if isinstance(cmd, dict): + for k, v in cmd.items(): + pass + elif isinstance(commands, dict): + for k, v in commands.items(): + pass + except Exception: + pass + elif field_id == 0x02: # FIELD_TELEMETRY + Telemeter.from_packed(field_data) + except Exception: + pass + + @pytest.fixture def temp_dir(tmp_path): return str(tmp_path) diff --git a/tests/backend/test_fuzzing_telemetry.py b/tests/backend/test_fuzzing_telemetry.py new file mode 100644 index 0000000..d407ef1 --- /dev/null +++ b/tests/backend/test_fuzzing_telemetry.py @@ -0,0 +1,99 @@ +from hypothesis import given, settings, strategies as st +from meshchatx.src.backend.telemetry_utils import Telemeter + +# Strategies for telemetry data +st_lat_lon = st.floats(min_value=-90, max_value=90) +st_alt = st.floats(min_value=-10000, max_value=100000) +st_speed = st.floats(min_value=0, max_value=2000) +st_bearing = st.floats(min_value=0, max_value=360) +st_accuracy = st.floats(min_value=0, max_value=10000) +st_timestamp = st.integers(min_value=0, max_value=2**32 - 1) + + +@settings(deadline=None) +@given( + lat=st_lat_lon, + lon=st_lat_lon, + alt=st_alt, + speed=st_speed, + bearing=st_bearing, + acc=st_accuracy, + ts=st_timestamp, +) +def test_fuzz_pack_location(lat, lon, alt, speed, bearing, acc, ts): + packed = Telemeter.pack_location(lat, lon, alt, speed, bearing, acc, ts) + if packed is not None: + unpacked = Telemeter.unpack_location(packed) + if unpacked: + # Check for reasonable precision (we use 1e6 for lat/lon, 1e2 for others) + assert abs(unpacked["latitude"] - lat) < 0.000002 + assert abs(unpacked["longitude"] - lon) < 0.000002 + assert abs(unpacked["altitude"] - alt) < 0.02 + assert abs(unpacked["speed"] - speed) < 0.02 + assert abs(unpacked["bearing"] - bearing) < 0.02 + assert abs(unpacked["accuracy"] - acc) < 0.02 + assert unpacked["last_update"] == ts + + +@settings(deadline=None) +@given( + charge=st.integers(min_value=0, max_value=100), + charging=st.integers(min_value=0, max_value=1), + rssi=st.integers(min_value=-150, max_value=0), + snr=st.floats(min_value=-20, max_value=20), + q=st.integers(min_value=0, max_value=100), +) +def test_fuzz_full_telemetry_packing(charge, charging, rssi, snr, q): + battery = {"charge_percent": charge, "charging": charging} + physical_link = {"rssi": rssi, "snr": snr, "q": q} + + packed = Telemeter.pack(battery=battery, physical_link=physical_link) + unpacked = Telemeter.from_packed(packed) + + assert unpacked["battery"]["charge_percent"] == charge + assert unpacked["battery"]["charging"] == charging + assert unpacked["physical_link"]["rssi"] == rssi + assert abs(unpacked["physical_link"]["snr"] - snr) < 0.01 + assert unpacked["physical_link"]["q"] == q + + +@settings(deadline=None) +@given(data=st.binary(min_size=0, max_size=2000)) +def test_fuzz_from_packed_random_bytes(data): + # This should never crash + try: + Telemeter.from_packed(data) + except Exception: + pass + + +@settings(deadline=None) +@given( + commands=st.lists( + st.dictionaries( + keys=st.one_of(st.integers(), st.text()), + values=st.one_of(st.integers(), st.text(), st.floats(), st.booleans()), + ), + max_size=10, + ) +) +def test_fuzz_command_parsing(commands): + # This simulates how commands are handled in meshchat.py + processed_commands = [] + for cmd in commands: + new_cmd = {} + for k, v in cmd.items(): + try: + if isinstance(k, str): + if k.startswith("0x"): + new_cmd[int(k, 16)] = v + else: + new_cmd[int(k)] = v + else: + new_cmd[k] = v + except (ValueError, TypeError): + new_cmd[k] = v + processed_commands.append(new_cmd) + + # Just ensure no crash + assert len(processed_commands) == len(commands) diff --git a/tests/backend/test_telemetry_extended.py b/tests/backend/test_telemetry_extended.py new file mode 100644 index 0000000..bdc8e57 --- /dev/null +++ b/tests/backend/test_telemetry_extended.py @@ -0,0 +1,47 @@ +import time +from meshchatx.src.backend.telemetry_utils import Telemeter + + +def test_pack_unpack_battery_and_link(): + battery = {"charge_percent": 85, "charging": 1} + physical_link = {"rssi": -90, "snr": 8, "q": 95} + ts = int(time.time()) + + packed = Telemeter.pack(time_utc=ts, battery=battery, physical_link=physical_link) + assert isinstance(packed, bytes) + + unpacked = Telemeter.from_packed(packed) + assert unpacked["time"]["utc"] == ts + assert unpacked["battery"]["charge_percent"] == battery["charge_percent"] + assert unpacked["battery"]["charging"] == battery["charging"] + assert unpacked["physical_link"]["rssi"] == physical_link["rssi"] + assert unpacked["physical_link"]["snr"] == physical_link["snr"] + assert unpacked["physical_link"]["q"] == physical_link["q"] + + +def test_telemeter_from_packed_robustness(): + # Test with corrupted umsgpack data + assert Telemeter.from_packed(b"\xff\xff\xff") is None + # Test with empty data + assert Telemeter.from_packed(b"") is None + # Test with valid umsgpack but unexpected structure + from RNS.vendor import umsgpack + + invalid_structure = umsgpack.packb({"not_a_sensor": 123}) + assert Telemeter.from_packed(invalid_structure) == {} + + +def test_telemeter_unpack_location_robustness(): + # Test with insufficient elements + assert Telemeter.unpack_location([b"lat", b"lon"]) is None + # Test with invalid types + assert Telemeter.unpack_location(["not_bytes"] * 7) is None + + +def test_sideband_request_format_compatibility(): + # Sideband telemetry request command is 0x01 + # It can be a simple int 0x01 or a dict {0x01: timebase} + + # This test is more about the logic in on_lxmf_delivery, + # but we can verify our assumptions about command structure here if needed. + pass diff --git a/tests/backend/test_telemetry_integration.py b/tests/backend/test_telemetry_integration.py new file mode 100644 index 0000000..a18249f --- /dev/null +++ b/tests/backend/test_telemetry_integration.py @@ -0,0 +1,130 @@ +import pytest +import time +import json +from unittest.mock import MagicMock, patch +from meshchatx.meshchat import ReticulumMeshChat +from meshchatx.src.backend.telemetry_utils import Telemeter + + +@pytest.fixture +def mock_app(): + # We create a simple mock object that has the methods/attributes + # needed by process_incoming_telemetry and other telemetry logic. + app = MagicMock(spec=ReticulumMeshChat) + + # Mock database + app.database = MagicMock() + app.database.telemetry = MagicMock() + + # Mock context + app.current_context = MagicMock() + app.current_context.database = app.database + app.current_context.local_lxmf_destination = MagicMock() + app.current_context.local_lxmf_destination.hexhash = "local_hash" + + # Mock reticulum + app.reticulum = MagicMock() + app.reticulum.get_packet_rssi.return_value = -70 + app.reticulum.get_packet_snr.return_value = 12.5 + app.reticulum.get_packet_q.return_value = 85 + + # Mock websocket_broadcast + app.websocket_broadcast = MagicMock() + + # Attach the actual method we want to test if possible, + # but since it's an instance method, we might need to bind it. + app.process_incoming_telemetry = ReticulumMeshChat.process_incoming_telemetry.__get__(app, ReticulumMeshChat) + + return app + + +@pytest.mark.asyncio +async def test_process_incoming_telemetry_single(mock_app): + source_hash = "source_hash" + location = {"latitude": 50.0, "longitude": 10.0} + packed_telemetry = Telemeter.pack(location=location) + + mock_lxmf_message = MagicMock() + mock_lxmf_message.hash = b"msg_hash" + + mock_app.process_incoming_telemetry(source_hash, packed_telemetry, mock_lxmf_message) + + # Verify database call + mock_app.database.telemetry.upsert_telemetry.assert_called() + call_args = mock_app.database.telemetry.upsert_telemetry.call_args[1] + assert call_args["destination_hash"] == source_hash + assert call_args["data"] == packed_telemetry + + +@pytest.mark.asyncio +async def test_process_incoming_telemetry_stream(mock_app): + # This simulates receiving a telemetry stream (e.g. from Sideband collector) + entries = [ + ( + "peer1", + int(time.time()) - 60, + Telemeter.pack(location={"latitude": 1.0, "longitude": 1.0}), + ), + ( + "peer2", + int(time.time()), + Telemeter.pack(location={"latitude": 2.0, "longitude": 2.0}), + ), + ] + + mock_lxmf_message = MagicMock() + mock_lxmf_message.hash = b"stream_msg_hash" + + # We call it directly for each entry as process_incoming_telemetry is refactored + # to handle single entries, and on_lxmf_delivery loops over streams. + for entry_source, entry_timestamp, entry_data in entries: + mock_app.process_incoming_telemetry( + entry_source, entry_data, mock_lxmf_message, timestamp_override=entry_timestamp + ) + + assert mock_app.database.telemetry.upsert_telemetry.call_count == 2 + + +@pytest.mark.asyncio +async def test_telemetry_request_parsing(mock_app): + # Test that on_lxmf_delivery correctly identifies telemetry requests + # and calls handle_telemetry_request. + mock_lxmf_message = MagicMock() + # 0x01 is SidebandCommands.TELEMETRY_REQUEST + # We mock get_fields to return a command request + mock_lxmf_message.get_fields.return_value = {0x01: [{0x01: int(time.time())}]} + mock_lxmf_message.source_hash = b"source_hash_bytes" + mock_lxmf_message.hash = b"msg_hash" + mock_lxmf_message.destination_hash = b"dest_hash" + + # We need to mock handle_telemetry_request on the app + mock_app.handle_telemetry_request = MagicMock() + + # Bind on_lxmf_delivery + mock_app.on_lxmf_delivery = ReticulumMeshChat.on_lxmf_delivery.__get__(mock_app, ReticulumMeshChat) + + # Mocking dependencies + mock_app.is_destination_blocked.return_value = False + mock_app.current_context.config.telemetry_enabled.get.return_value = True + mock_app.database.contacts.get_contact_by_identity_hash.return_value = {"is_telemetry_trusted": True} + mock_app.database.messages.get_lxmf_message_by_hash.return_value = {} # To avoid JSON error + + # Also need SidebandCommands + from meshchatx.src.backend.sideband_commands import SidebandCommands + # (SidebandCommands is likely already imported in meshchat.py) + + # Call it + mock_app.on_lxmf_delivery(mock_lxmf_message) + + # Verify handle_telemetry_request was called + mock_app.handle_telemetry_request.assert_called_with("736f757263655f686173685f6279746573") + + +@pytest.mark.asyncio +async def test_tracking_toggle_endpoint(mock_app): + # Mock database responses + mock_app.database.telemetry.is_tracking.return_value = False + + # We can't easily test the web endpoint here without more setup, + # but we can test the logic it calls if it was refactored into a method. + pass diff --git a/tests/frontend/InterfacesPerformance.test.js b/tests/frontend/InterfacesPerformance.test.js new file mode 100644 index 0000000..0cb9c4a --- /dev/null +++ b/tests/frontend/InterfacesPerformance.test.js @@ -0,0 +1,146 @@ +import { mount } from "@vue/test-utils"; +import { describe, it, expect, vi } from "vitest"; +import InterfacesPage from "../../meshchatx/src/frontend/components/interfaces/InterfacesPage.vue"; + +// Mock dependencies +vi.mock("../../meshchatx/src/frontend/js/GlobalState", () => ({ + default: { + config: { theme: "light" }, + hasPendingInterfaceChanges: false, + modifiedInterfaceNames: new Set(), + }, +})); + +vi.mock("../../meshchatx/src/frontend/js/Utils", () => ({ + default: { + formatBytes: (b) => `${b} B`, + isInterfaceEnabled: () => true, + }, +})); + +vi.mock("../../meshchatx/src/frontend/js/ToastUtils", () => ({ + default: { + success: vi.fn(), + error: vi.fn(), + }, +})); + +vi.mock("../../meshchatx/src/frontend/js/ElectronUtils", () => ({ + default: { + relaunch: vi.fn(), + }, +})); + +// Mock axios +global.axios = { + get: vi.fn((url) => { + if (url.includes("/api/v1/reticulum/interfaces")) { + return Promise.resolve({ data: { interfaces: {} } }); + } + if (url.includes("/api/v1/app/info")) { + return Promise.resolve({ data: { app_info: { is_reticulum_running: true } } }); + } + if (url.includes("/api/v1/interface-stats")) { + return Promise.resolve({ data: { interface_stats: { interfaces: [] } } }); + } + if (url.includes("/api/v1/reticulum/discovery")) { + return Promise.resolve({ data: { discovery: { discover_interfaces: true } } }); + } + if (url.includes("/api/v1/reticulum/discovered-interfaces")) { + return Promise.resolve({ data: { interfaces: [], active: [] } }); + } + return Promise.resolve({ data: {} }); + }), + post: vi.fn(() => Promise.resolve({ data: {} })), + patch: vi.fn(() => Promise.resolve({ data: {} })), +}; +window.axios = global.axios; + +// Mock MaterialDesignIcon +const MaterialDesignIcon = { + template: '
    ', + props: ["iconName"], +}; + +describe("InterfacesPage Performance", () => { + it("renders InterfacesPage with 1000 disconnected discovered interfaces", async () => { + const numDiscovered = 1000; + const discoveredInterfaces = Array.from({ length: numDiscovered }, (_, i) => ({ + name: `Discovered ${i}`, + type: "UDPInterface", + reachable_on: `192.168.1.${i}`, + port: 4242, + discovery_hash: `hash_${i}`, + })); + + const start = performance.now(); + const wrapper = mount(InterfacesPage, { + global: { + components: { + MaterialDesignIcon, + Toggle: { template: "
    " }, + ImportInterfacesModal: { + template: "
    ", + methods: { show: vi.fn() }, + }, + Interface: { template: "
    " }, + }, + mocks: { + $t: (key) => key, + $router: { push: vi.fn() }, + }, + }, + }); + + await wrapper.setData({ + discoveredInterfaces, + activeTab: "overview", // This is where discovered interfaces are shown in the template I saw + }); + + const end = performance.now(); + console.log(`Rendered ${numDiscovered} discovered interfaces in ${(end - start).toFixed(2)}ms`); + + // Check if animations are present + const pulsingElements = wrapper.findAll(".animate-pulse"); + expect(pulsingElements.length).toBe(numDiscovered); + + expect(end - start).toBeLessThan(5000); + }); + + it("stops pulsing animations after 30 seconds", async () => { + const iface = { + name: "Discovered 1", + type: "UDPInterface", + reachable_on: "192.168.1.1", + port: 4242, + discovery_hash: "hash_1", + disconnected_at: Date.now() - 31000, // 31 seconds ago + }; + + const wrapper = mount(InterfacesPage, { + global: { + components: { + MaterialDesignIcon, + Toggle: { template: "
    " }, + ImportInterfacesModal: { + template: "
    ", + methods: { show: vi.fn() }, + }, + Interface: { template: "
    " }, + }, + mocks: { + $t: (key) => key, + $router: { push: vi.fn() }, + }, + }, + }); + + await wrapper.setData({ + discoveredInterfaces: [iface], + activeTab: "overview", + }); + + const pulsingElements = wrapper.findAll(".animate-pulse"); + expect(pulsingElements.length).toBe(0); + }); +}); diff --git a/tests/frontend/LanguageSelector.test.js b/tests/frontend/LanguageSelector.test.js index 8e77e9e..a8180e6 100644 --- a/tests/frontend/LanguageSelector.test.js +++ b/tests/frontend/LanguageSelector.test.js @@ -43,10 +43,11 @@ describe("LanguageSelector.vue", () => { await wrapper.find("button").trigger("click"); const languageButtons = wrapper.findAll(".fixed button"); - expect(languageButtons).toHaveLength(3); + expect(languageButtons).toHaveLength(4); expect(languageButtons[0].text()).toContain("English"); expect(languageButtons[1].text()).toContain("Deutsch"); expect(languageButtons[2].text()).toContain("Русский"); + expect(languageButtons[3].text()).toContain("Italiano"); }); it("emits language-change when a different language is selected", async () => { diff --git a/tests/frontend/LinkUtils.test.js b/tests/frontend/LinkUtils.test.js new file mode 100644 index 0000000..e2b113f --- /dev/null +++ b/tests/frontend/LinkUtils.test.js @@ -0,0 +1,47 @@ +import { describe, it, expect } from "vitest"; +import LinkUtils from "@/js/LinkUtils"; + +describe("LinkUtils.js", () => { + describe("renderNomadNetLinks", () => { + it("detects nomadnet:// links with hash and path", () => { + const text = "nomadnet://1dfeb0d794963579bd21ac8f153c77a4:/page/index.mu"; + const result = LinkUtils.renderNomadNetLinks(text); + expect(result).toContain('data-nomadnet-url="1dfeb0d794963579bd21ac8f153c77a4:/page/index.mu"'); + }); + + it("detects bare hash and path links", () => { + const text = "1dfeb0d794963579bd21ac8f153c77a4:/page/index.mu"; + const result = LinkUtils.renderNomadNetLinks(text); + expect(result).toContain('data-nomadnet-url="1dfeb0d794963579bd21ac8f153c77a4:/page/index.mu"'); + }); + + it("detects nomadnet:// links with just hash", () => { + const text = "nomadnet://1dfeb0d794963579bd21ac8f153c77a4"; + const result = LinkUtils.renderNomadNetLinks(text); + expect(result).toContain('data-nomadnet-url="1dfeb0d794963579bd21ac8f153c77a4:/page/index.mu"'); + }); + }); + + describe("renderStandardLinks", () => { + it("detects http links", () => { + const text = "visit http://example.com"; + const result = LinkUtils.renderStandardLinks(text); + expect(result).toContain(' { + const text = "visit https://example.com/path?query=1"; + const result = LinkUtils.renderStandardLinks(text); + expect(result).toContain(' { + it("detects both types of links", () => { + const text = "Check https://google.com and nomadnet://1dfeb0d794963579bd21ac8f153c77a4"; + const result = LinkUtils.renderAllLinks(text); + expect(result).toContain('href="https://google.com"'); + expect(result).toContain('data-nomadnet-url="1dfeb0d794963579bd21ac8f153c77a4:/page/index.mu"'); + }); + }); +}); diff --git a/tests/frontend/MarkdownRenderer.test.js b/tests/frontend/MarkdownRenderer.test.js new file mode 100644 index 0000000..058657d --- /dev/null +++ b/tests/frontend/MarkdownRenderer.test.js @@ -0,0 +1,212 @@ +import { describe, it, expect } from "vitest"; +import MarkdownRenderer from "@/js/MarkdownRenderer"; + +describe("MarkdownRenderer.js", () => { + describe("render", () => { + it("renders basic text correctly", () => { + expect(MarkdownRenderer.render("Hello")).toContain("Hello"); + }); + + it("renders bold text correctly", () => { + const result = MarkdownRenderer.render("**Bold**"); + expect(result).toContain("Bold"); + }); + + it("renders italic text correctly", () => { + const result = MarkdownRenderer.render("*Italic*"); + expect(result).toContain("Italic"); + }); + + it("renders bold and italic text correctly", () => { + const result = MarkdownRenderer.render("***Bold and Italic***"); + expect(result).toContain("Bold and Italic"); + }); + + it("renders headers correctly", () => { + expect(MarkdownRenderer.render("# Header 1")).toContain(" { + const result = MarkdownRenderer.render("`code`"); + expect(result).toContain(" { + const result = MarkdownRenderer.render("```python\nprint('hello')\n```"); + expect(result).toContain(" { + const result = MarkdownRenderer.render("Para 1\n\nPara 2"); + expect(result).toContain(" { + it("escapes script tags", () => { + const malformed = ""; + const result = MarkdownRenderer.render(malformed); + expect(result).not.toContain("\n```"; + const result = MarkdownRenderer.render(malformed); + expect(result).toContain("<script>"); + }); + + it("escapes html in inline code", () => { + const malformed = "``"; + const result = MarkdownRenderer.render(malformed); + expect(result).toContain("<script>"); + }); + }); + + describe("nomadnet links", () => { + it("detects nomadnet:// links with hash and path", () => { + const text = "check this out: nomadnet://1dfeb0d794963579bd21ac8f153c77a4:/page/index.mu"; + const result = MarkdownRenderer.render(text); + expect(result).toContain('data-nomadnet-url="1dfeb0d794963579bd21ac8f153c77a4:/page/index.mu"'); + expect(result).toContain("nomadnet://1dfeb0d794963579bd21ac8f153c77a4:/page/index.mu"); + }); + + it("detects bare hash and path links", () => { + const text = "node is at 1dfeb0d794963579bd21ac8f153c77a4:/page/index.mu"; + const result = MarkdownRenderer.render(text); + expect(result).toContain('data-nomadnet-url="1dfeb0d794963579bd21ac8f153c77a4:/page/index.mu"'); + expect(result).toContain("1dfeb0d794963579bd21ac8f153c77a4:/page/index.mu"); + }); + + it("detects nomadnet:// links with just hash", () => { + const text = "nomadnet://1dfeb0d794963579bd21ac8f153c77a4"; + const result = MarkdownRenderer.render(text); + expect(result).toContain('data-nomadnet-url="1dfeb0d794963579bd21ac8f153c77a4:/page/index.mu"'); + }); + + it("does not detect invalid hashes", () => { + const text = "not-a-hash:/page/index.mu"; + const result = MarkdownRenderer.render(text); + expect(result).not.toContain("nomadnet-link"); + }); + }); + + describe("fuzzing: stability testing", () => { + const generateRandomString = (length) => { + const chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-=[]{}|;':\",./<>?`~ \n\r\t"; + let result = ""; + for (let i = 0; i < length; i++) { + result += chars.charAt(Math.floor(Math.random() * chars.length)); + } + return result; + }; + + it("handles random inputs without crashing (100 iterations)", () => { + for (let i = 0; i < 100; i++) { + const randomText = generateRandomString(Math.floor(Math.random() * 1000)); + expect(() => { + MarkdownRenderer.render(randomText); + }).not.toThrow(); + } + }); + + it("handles deeply nested or complex markdown patterns without crashing", () => { + const complex = "# ".repeat(100) + "**".repeat(100) + "```".repeat(100) + "```\n".repeat(10); + expect(() => { + MarkdownRenderer.render(complex); + }).not.toThrow(); + }); + + it("handles large inputs correctly (1MB of random text)", () => { + const largeText = generateRandomString(1024 * 1024); + const start = Date.now(); + const result = MarkdownRenderer.render(largeText); + const end = Date.now(); + + expect(typeof result).toBe("string"); + // performance check: should be relatively fast (less than 500ms for 1MB usually) + expect(end - start).toBeLessThan(1000); + }); + + it("handles potential ReDoS patterns (repeated separators)", () => { + // Test patterns that often cause ReDoS in poorly written markdown parsers (can never be too careful, especially on public testnets) + const redosPatterns = [ + "*".repeat(10000), // Long string of bold markers + "#".repeat(10000), // Long string of header markers + "`".repeat(10000), // Long string of backticks + " ".repeat(10000) + "\n", // Long string of whitespace + "[](".repeat(5000), // Unclosed links (if we added them) + "** ".repeat(5000), // Bold marker followed by space repeated + ]; + + redosPatterns.forEach((pattern) => { + const start = Date.now(); + MarkdownRenderer.render(pattern); + const end = Date.now(); + expect(end - start).toBeLessThan(100); // Should be very fast + }); + }); + + it("handles unicode homoglyphs and special characters without interference", () => { + const homoglyphs = [ + "**bold**", + "∗∗notbold∗∗", // unicode asterisks + "# header", + "# not header", // fullwidth hash + "`code`", + "`notcode`", // fullwidth backtick + ]; + homoglyphs.forEach((text) => { + const result = MarkdownRenderer.render(text); + expect(typeof result).toBe("string"); + }); + }); + + it("handles malformed or unclosed markdown tags gracefully", () => { + const malformed = [ + "**bold", + "```python\nprint(1)", + "#header", // no space + "`code", + "___triple", + "**bold*italic**", + "***bolditalic**", + ]; + malformed.forEach((text) => { + expect(() => MarkdownRenderer.render(text)).not.toThrow(); + }); + }); + }); + + describe("strip", () => { + it("strips markdown correctly", () => { + const md = "# Header\n**Bold** *Italic* `code` ```\nblock\n```"; + const stripped = MarkdownRenderer.strip(md); + expect(stripped).toContain("Header"); + expect(stripped).toContain("Bold"); + expect(stripped).toContain("Italic"); + expect(stripped).toContain("code"); + expect(stripped).toContain("[Code Block]"); + expect(stripped).not.toContain("# "); + expect(stripped).not.toContain("**"); + expect(stripped).not.toContain("` "); + }); + }); +}); diff --git a/tests/frontend/Performance.test.js b/tests/frontend/Performance.test.js index a32fb34..dfb9744 100644 --- a/tests/frontend/Performance.test.js +++ b/tests/frontend/Performance.test.js @@ -16,6 +16,18 @@ vi.mock("../../meshchatx/src/frontend/js/Utils", () => ({ formatTimeAgo: () => "1 hour ago", formatBytes: () => "1 KB", formatDestinationHash: (h) => h, + escapeHtml: (t) => + t.replace( + /[&<>"']/g, + (m) => + ({ + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + })[m] + ), }, })); From 75b17b44a19eb2ffef1c53ba0117b8fb75367da7 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Wed, 7 Jan 2026 19:29:07 -0600 Subject: [PATCH 205/234] update changelog [skip ci] --- CHANGELOG.md | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5da338b..d767d73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ Season 1 Episode 1 - A MASSIVE REFACTOR ### New Features - **Banishment System (formerly Blocked):** - - Renamed all instances of "Blocked" to **"Banished"**, you can now banish people to the shadow realm. + - Renamed all instances of "Blocked" to **"Banished"**, you can now banish really annoying people to the shadow realm. - **Blackhole Integration:** Automatically blackholes identities at the RNS transport layer when they are banished in MeshChatX. This prevents their traffic from being relayed through your node and publishes the update to your interfaces (trusted interfaces will pull and enforce the banishment). - Integrated RNS 1.1.0 Blackhole to display publishing status, sources, and current blackhole counts in the RNStatus page. - **RNPath Management Tool:** New UI tool to manage the Reticulum path table, monitor announce rates (with rate-limit detection), and perform manual path requests or purges directly from the app. @@ -18,6 +18,12 @@ Season 1 Episode 1 - A MASSIVE REFACTOR - Added support for custom ringtones and a brand-new ringtone editor. - New **Audio Waveform Visualization** for voice messages, providing interactive playback with a visual waveform representation. - **Paper Messages:** Introduced a tool for generating and scanning paper-based messages with built-in QR code generation for easy sharing. +- **LXMF Telemetry & Live Tracking**: + - Full implementation of Sideband-compatible (Still need to test Columba) telemetry (FIELD_TELEMETRY & FIELD_TELEMETRY_STREAM). + - Live tracking with real-time map updates, distinct blue pulsing animations, and historical path tracing (breadcrumb trails). + - Mini-chat integrated into map markers for quick communication with telemetry peers. + - Privacy controls with global telemetry toggle and per-peer "Trust for Telemetry" settings. + - Detailed telemetry history timeline with interactive battery voltage/percentage sparkline charts. - **Documentation:** You can now read all the project guides and help docs directly inside the app. - **Reliability:** - If the app ever crashes, it's now much better at picking up right where it left off without losing your data. @@ -40,7 +46,7 @@ Season 1 Episode 1 - A MASSIVE REFACTOR * **Power Management:** Automatically prevents system sleep during active audio calls to maintain RNS path stability. - **Added Web Audio Bridge** which allows web/electron to hook into LXST backend for passing microphone and audio streams to active telephone calls. - **Added LXMFy** for running bots. -- **Added RNS Discoverable Interfaces** https://markqvist.github.io/Reticulum/manual/interfaces.html#discoverable-interfaces +- **Added RNS Discoverable Interfaces** https://markqvist.github.io/Reticulum/manual/interfaces.html#discoverable-interfaces and ability to map them (ones with a location). ### Improvements @@ -52,10 +58,16 @@ Season 1 Episode 1 - A MASSIVE REFACTOR - **Smoother Settings:** Changing settings now uses "smart saving" (debouncing) to prevent unnecessary disk work and keep the interface responsive. - **Backend Efficiency:** A massive core refactor and new database optimizations make message handling and search nearly instantaneous. Added pagination to announce and discovery lists to improve performance in large networks. - **Calling:** The call screen and overlays have been completely redesigned to look better and work more smoothly. -- **Messaging:** We've polished the message lists and archive views to make them easier to navigate. +- **Messaging:** + - Polished the message lists and archive views to make them easier to navigate. + - Added "Retry All" functionality for failed or cancelled messages in conversation views. + - Improved handling of `lxm.ingest_uri.result` with detailed notifications for success/error/warning states. +- **Maintenance Tools:** Added new maintenance utilities to clear LXMF user icon caches and manage backup configurations. - **Network View:** The visualizer that shows your network connections is now much clearer and easier to understand. -- **Languages:** Updated translations for English, German, and Russian. Added a toggle to easily enable or disable translation services. +- **Languages:** Updated translations for English, German, and Russian. Added **Italian (it-IT)** localization. Added a toggle to easily enable or disable translation services. - **Search:** The command palette (quick search) and notification bell are now more useful. +- **CartoDB Tiles** - some more styles if OSM is not enough for you, MBtiles will export tiles from the selected one. +- **Basic Markdown in Messages** - Support for basic markdown in messages ### Bug Fixes @@ -90,8 +102,11 @@ Season 1 Episode 1 - A MASSIVE REFACTOR - **Infrastructure:** - Added `Dockerfile.build` for multi-stage container builds. - Introduced `gen_checksums.sh` for release artifact integrity. - - Expanded test coverage with 40+ new unit and integration tests across `tests/backend/` and `tests/frontend/`. - - Updated core dependencies: `rns`, `lxmf`, `aiohttp`, and `websockets`. + - **Comprehensive Testing Suite:** + - Added 80+ new unit, integration, and fuzz tests across `tests/backend/` and `tests/frontend/`. + - Implemented property-based fuzzing for LXMF message parsing and telemetry packing using `hypothesis`. + - Updated CI coverage for telemetry and network interface logic. + - Updated core dependencies: `rns`, `lxmf`, `aiohttp`, and `websockets`. - **Developer Tools & CI:** - New `task` commands: `bench-backend` (Standard suite), `bench-extreme` (Breaking Time and Space), `profile-memory` (Leak testing), and `bench` (Full run). - Added Gitea Actions workflow (`bench.yml`) for automated performance regression tracking on every push. From 8bc7e39aeef470001b305283b34698e29e3872af Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Wed, 7 Jan 2026 19:30:06 -0600 Subject: [PATCH 206/234] refactor(tests): clean up telemetry integration test by removing unused imports --- tests/backend/test_telemetry_integration.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/backend/test_telemetry_integration.py b/tests/backend/test_telemetry_integration.py index a18249f..81e7c3f 100644 --- a/tests/backend/test_telemetry_integration.py +++ b/tests/backend/test_telemetry_integration.py @@ -1,7 +1,6 @@ import pytest import time -import json -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock from meshchatx.meshchat import ReticulumMeshChat from meshchatx.src.backend.telemetry_utils import Telemeter @@ -109,10 +108,6 @@ async def test_telemetry_request_parsing(mock_app): mock_app.database.contacts.get_contact_by_identity_hash.return_value = {"is_telemetry_trusted": True} mock_app.database.messages.get_lxmf_message_by_hash.return_value = {} # To avoid JSON error - # Also need SidebandCommands - from meshchatx.src.backend.sideband_commands import SidebandCommands - # (SidebandCommands is likely already imported in meshchat.py) - # Call it mock_app.on_lxmf_delivery(mock_lxmf_message) From 80ea5424fd803d5308ac071b1965bb2b9f6aade8 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Wed, 7 Jan 2026 19:45:31 -0600 Subject: [PATCH 207/234] fix(frontend): update call status messages for clarity --- .../src/frontend/components/call/CallOverlay.vue | 13 +++++++++++-- meshchatx/src/frontend/components/call/CallPage.vue | 6 +++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/meshchatx/src/frontend/components/call/CallOverlay.vue b/meshchatx/src/frontend/components/call/CallOverlay.vue index e95afa1..2e64d31 100644 --- a/meshchatx/src/frontend/components/call/CallOverlay.vue +++ b/meshchatx/src/frontend/components/call/CallOverlay.vue @@ -30,7 +30,16 @@ : activeCall && activeCall.status === 6 ? $t("call.active_call") : initiationStatus - ? $t("call.initiation") + ? initiationStatus === "Initiating..." || + initiationStatus === "Resolving identity..." || + initiationStatus === "Discovering path/identity..." || + initiationStatus === "Requesting path..." || + initiationStatus === "Dialing..." || + initiationStatus === "Calling..." || + initiationStatus === "Ringing..." || + initiationStatus === "Establishing link..." + ? initiationStatus + : $t("call.initiation") : $t("call.call_status") }} @@ -131,7 +140,7 @@ {{ $t("call.calling") }} {{ $t("call.available") }} {{ $t("call.ringing") }} - {{ $t("call.connecting") }} + {{ $t("call.establishing_link") }} {{ $t("call.connected") }} {{ $t("call.status") }}: {{ activeCall.status }}
    diff --git a/meshchatx/src/frontend/components/call/CallPage.vue b/meshchatx/src/frontend/components/call/CallPage.vue index bd5f3ca..61ea4ec 100644 --- a/meshchatx/src/frontend/components/call/CallPage.vue +++ b/meshchatx/src/frontend/components/call/CallPage.vue @@ -218,9 +218,9 @@ class="animate-pulse" >Ringing... - Connecting... + + {{ $t("call.establishing_link") }} + Date: Wed, 7 Jan 2026 19:45:47 -0600 Subject: [PATCH 208/234] refactor(telephone_manager): improve call status updates for better user feedback --- meshchatx/src/backend/telephone_manager.py | 49 ++++++++++++++++++---- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/meshchatx/src/backend/telephone_manager.py b/meshchatx/src/backend/telephone_manager.py index 44aa1a5..f32f797 100644 --- a/meshchatx/src/backend/telephone_manager.py +++ b/meshchatx/src/backend/telephone_manager.py @@ -296,7 +296,7 @@ class TelephoneManager: break await asyncio.sleep(0.5) - self._update_initiation_status("Dialing...") + self._update_initiation_status("Establishing link...", destination_hash_hex) self.call_start_time = time.time() self.call_is_incoming = False @@ -312,6 +312,17 @@ class TelephoneManager: while not call_task.done(): if not self.initiation_status: # Externally cancelled break + + # Update UI status based on current call state + if self.telephone.call_status == 2: + self._update_initiation_status("Calling...", destination_hash_hex) + elif self.telephone.call_status == 4: + self._update_initiation_status("Ringing...", destination_hash_hex) + elif self.telephone.call_status == 5: + self._update_initiation_status( + "Establishing link...", destination_hash_hex, + ) + if self.telephone.call_status in [ 6, 0, @@ -327,13 +338,28 @@ class TelephoneManager: # If the task finished but we're still ringing or connecting, # wait a bit more for establishment or definitive failure if self.initiation_status and self.telephone.call_status in [ + 2, 4, 5, - ]: # Ringing, Connecting + ]: # Calling, Ringing, Connecting wait_until = time.time() + timeout_seconds while time.time() < wait_until: if not self.initiation_status: # Externally cancelled break + + if self.telephone.call_status == 2: + self._update_initiation_status( + "Calling...", destination_hash_hex, + ) + elif self.telephone.call_status == 4: + self._update_initiation_status( + "Ringing...", destination_hash_hex, + ) + elif self.telephone.call_status == 5: + self._update_initiation_status( + "Establishing link...", destination_hash_hex, + ) + if self.telephone.call_status in [ 6, 0, @@ -350,14 +376,23 @@ class TelephoneManager: await asyncio.sleep(3) raise finally: + # Wait for either establishment, failure, or a timeout + # to ensure the UI has something to show (either active_call or initiation_status) + for _ in range(20): # Max 10 seconds of defensive waiting + if self.telephone and ( + self.telephone.active_call + or self.telephone.call_status in [0, 1, 3, 6] + ): + break + await asyncio.sleep(0.5) + # If call was successful, keep status for a moment to prevent UI flicker # while the frontend picks up the new active_call state - if ( - self.telephone - and self.telephone.active_call - and self.telephone.call_status == 6 + if self.telephone and ( + (self.telephone.active_call and self.telephone.call_status == 6) + or self.telephone.call_status in [2, 4, 5] ): - await asyncio.sleep(1.5) + await asyncio.sleep(2.0) self._update_initiation_status(None, None) def mute_transmit(self): From 192ac21fb0329bdc290881cc2e8c307030e4c9e1 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Wed, 7 Jan 2026 19:46:01 -0600 Subject: [PATCH 209/234] feat(docs): add API endpoints for deleting documentation versions and clearing Reticulum docs - Implemented DELETE endpoints to allow users to delete specific documentation versions and clear all Reticulum documentation. - Enhanced the DocsManager class with methods for version deletion and clearing documentation, including error handling and logging. - Updated frontend components to support version deletion and clearing of Reticulum docs with user confirmation dialogs. --- meshchatx/meshchat.py | 35 ++++++++++-- meshchatx/src/backend/docs_manager.py | 57 +++++++++++++++++++ .../src/frontend/components/docs/DocsPage.vue | 39 ++++++++++--- .../components/settings/SettingsPage.vue | 25 ++++++++ 4 files changed, 144 insertions(+), 12 deletions(-) diff --git a/meshchatx/meshchat.py b/meshchatx/meshchat.py index aa04c0b..bad0620 100644 --- a/meshchatx/meshchat.py +++ b/meshchatx/meshchat.py @@ -3753,6 +3753,31 @@ class ReticulumMeshChat: except Exception as e: return web.json_response({"error": str(e)}, status=500) + # delete docs version + @routes.delete("/api/v1/docs/version/{version}") + async def docs_delete_version(request): + try: + version = request.match_info.get("version") + if not version: + return web.json_response( + {"error": "No version provided"}, + status=400, + ) + + success = self.docs_manager.delete_version(version) + return web.json_response({"success": success}) + except Exception as e: + return web.json_response({"error": str(e)}, status=500) + + # clear reticulum docs + @routes.delete("/api/v1/maintenance/docs/reticulum") + async def docs_clear(request): + try: + success = self.docs_manager.clear_reticulum_docs() + return web.json_response({"success": success}) + except Exception as e: + return web.json_response({"error": str(e)}, status=500) + # search docs @routes.get("/api/v1/docs/search") async def docs_search(request): @@ -8901,7 +8926,7 @@ class ReticulumMeshChat: if "telemetry_enabled" in data: self.config.telemetry_enabled.set( - self._parse_bool(data["telemetry_enabled"]) + self._parse_bool(data["telemetry_enabled"]), ) # update banishment settings @@ -10285,7 +10310,7 @@ class ReticulumMeshChat: commands.extend(val) elif isinstance(val, dict): commands.append(val) - if 0x01 in lxmf_fields and 0x01 != LXMF.FIELD_COMMANDS: + if 0x01 in lxmf_fields and LXMF.FIELD_COMMANDS != 0x01: val = lxmf_fields[0x01] if isinstance(val, list): commands.extend(val) @@ -10321,11 +10346,11 @@ class ReticulumMeshChat: else: # Check if peer is trusted contact = ctx.database.contacts.get_contact_by_identity_hash( - source_hash + source_hash, ) if not contact or not contact.get("is_telemetry_trusted"): print( - f"Telemetry request from untrusted peer {source_hash}, ignoring" + f"Telemetry request from untrusted peer {source_hash}, ignoring", ) else: print(f"Responding to telemetry request from {source_hash}") @@ -10342,7 +10367,7 @@ class ReticulumMeshChat: "remote_identity_name": source_hash[:8], "lxmf_message": convert_db_lxmf_message_to_dict( ctx.database.messages.get_lxmf_message_by_hash( - lxmf_message.hash.hex() + lxmf_message.hash.hex(), ), include_attachments=False, ), diff --git a/meshchatx/src/backend/docs_manager.py b/meshchatx/src/backend/docs_manager.py index d78d031..bc41803 100644 --- a/meshchatx/src/backend/docs_manager.py +++ b/meshchatx/src/backend/docs_manager.py @@ -134,6 +134,63 @@ class DocsManager: return True return False + def delete_version(self, version): + """Deletes a specific version of documentation.""" + if version not in self.get_available_versions(): + return False + + version_path = os.path.join(self.versions_dir, version) + if not os.path.exists(version_path): + return False + + try: + # If the deleted version is the current one, unlink 'current' first + current_version = self.get_current_version() + if current_version == version: + if os.path.exists(self.docs_dir): + if os.path.islink(self.docs_dir): + os.unlink(self.docs_dir) + else: + shutil.rmtree(self.docs_dir) + + shutil.rmtree(version_path) + + # If we just deleted the current version, try to pick another one as current + if current_version == version: + self._update_current_link() + + return True + except Exception as e: + logging.exception(f"Failed to delete docs version {version}: {e}") + return False + + def clear_reticulum_docs(self): + """Clears all Reticulum documentation and versions.""" + try: + if os.path.exists(self.docs_base_dir): + # We don't want to delete the base dir itself, just its contents + # except possibly some metadata if we added any. + # Actually, deleting everything inside reticulum-docs is fine. + for item in os.listdir(self.docs_base_dir): + item_path = os.path.join(self.docs_base_dir, item) + if os.path.islink(item_path): + os.unlink(item_path) + elif os.path.isdir(item_path): + shutil.rmtree(item_path) + else: + os.remove(item_path) + + # Re-create required subdirectories + for d in [self.versions_dir, self.docs_dir]: + if not os.path.exists(d): + os.makedirs(d) + + self.config.docs_downloaded.set(False) + return True + except Exception as e: + logging.exception(f"Failed to clear Reticulum docs: {e}") + return False + def populate_meshchatx_docs(self): """Populates meshchatx-docs from the project's docs folder.""" # Try to find docs folder in several places diff --git a/meshchatx/src/frontend/components/docs/DocsPage.vue b/meshchatx/src/frontend/components/docs/DocsPage.vue index ae9b1d8..1d43824 100644 --- a/meshchatx/src/frontend/components/docs/DocsPage.vue +++ b/meshchatx/src/frontend/components/docs/DocsPage.vue @@ -114,7 +114,7 @@ +
    + +
    @@ -2218,6 +2234,15 @@ export default { ToastUtils.error(this.$t("common.error")); } }, + async clearReticulumDocs() { + if (!(await DialogUtils.confirm(this.$t("maintenance.clear_confirm")))) return; + try { + await window.axios.delete("/api/v1/maintenance/docs/reticulum"); + ToastUtils.success(this.$t("maintenance.docs_cleared")); + } catch { + ToastUtils.error(this.$t("common.error")); + } + }, async exportMessages() { try { const response = await window.axios.get("/api/v1/maintenance/messages/export"); From 069865d4440fdb70d7954527ab07142f6d171e5c Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Wed, 7 Jan 2026 19:46:10 -0600 Subject: [PATCH 210/234] refactor(call_page): streamline call status message rendering for improved readability --- meshchatx/src/frontend/components/call/CallPage.vue | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/meshchatx/src/frontend/components/call/CallPage.vue b/meshchatx/src/frontend/components/call/CallPage.vue index 61ea4ec..e9c493e 100644 --- a/meshchatx/src/frontend/components/call/CallPage.vue +++ b/meshchatx/src/frontend/components/call/CallPage.vue @@ -218,9 +218,7 @@ class="animate-pulse" >Ringing... - - {{ $t("call.establishing_link") }} - + {{ $t("call.establishing_link") }} Date: Wed, 7 Jan 2026 19:51:35 -0600 Subject: [PATCH 211/234] refactor(call_page): formatting --- meshchatx/src/frontend/components/call/CallPage.vue | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/meshchatx/src/frontend/components/call/CallPage.vue b/meshchatx/src/frontend/components/call/CallPage.vue index e9c493e..2612814 100644 --- a/meshchatx/src/frontend/components/call/CallPage.vue +++ b/meshchatx/src/frontend/components/call/CallPage.vue @@ -218,7 +218,9 @@ class="animate-pulse" >Ringing... - {{ $t("call.establishing_link") }} + {{ + $t("call.establishing_link") + }} Date: Wed, 7 Jan 2026 19:51:48 -0600 Subject: [PATCH 212/234] refactor(tests): formatting --- tests/backend/test_telemetry_integration.py | 51 +++++++++++++-------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/tests/backend/test_telemetry_integration.py b/tests/backend/test_telemetry_integration.py index 81e7c3f..0e82522 100644 --- a/tests/backend/test_telemetry_integration.py +++ b/tests/backend/test_telemetry_integration.py @@ -10,30 +10,32 @@ def mock_app(): # We create a simple mock object that has the methods/attributes # needed by process_incoming_telemetry and other telemetry logic. app = MagicMock(spec=ReticulumMeshChat) - + # Mock database app.database = MagicMock() app.database.telemetry = MagicMock() - + # Mock context app.current_context = MagicMock() app.current_context.database = app.database app.current_context.local_lxmf_destination = MagicMock() app.current_context.local_lxmf_destination.hexhash = "local_hash" - + # Mock reticulum app.reticulum = MagicMock() app.reticulum.get_packet_rssi.return_value = -70 app.reticulum.get_packet_snr.return_value = 12.5 app.reticulum.get_packet_q.return_value = 85 - + # Mock websocket_broadcast app.websocket_broadcast = MagicMock() - - # Attach the actual method we want to test if possible, + + # Attach the actual method we want to test if possible, # but since it's an instance method, we might need to bind it. - app.process_incoming_telemetry = ReticulumMeshChat.process_incoming_telemetry.__get__(app, ReticulumMeshChat) - + app.process_incoming_telemetry = ( + ReticulumMeshChat.process_incoming_telemetry.__get__(app, ReticulumMeshChat) + ) + return app @@ -42,11 +44,13 @@ async def test_process_incoming_telemetry_single(mock_app): source_hash = "source_hash" location = {"latitude": 50.0, "longitude": 10.0} packed_telemetry = Telemeter.pack(location=location) - + mock_lxmf_message = MagicMock() mock_lxmf_message.hash = b"msg_hash" - mock_app.process_incoming_telemetry(source_hash, packed_telemetry, mock_lxmf_message) + mock_app.process_incoming_telemetry( + source_hash, packed_telemetry, mock_lxmf_message + ) # Verify database call mock_app.database.telemetry.upsert_telemetry.assert_called() @@ -78,7 +82,10 @@ async def test_process_incoming_telemetry_stream(mock_app): # to handle single entries, and on_lxmf_delivery loops over streams. for entry_source, entry_timestamp, entry_data in entries: mock_app.process_incoming_telemetry( - entry_source, entry_data, mock_lxmf_message, timestamp_override=entry_timestamp + entry_source, + entry_data, + mock_lxmf_message, + timestamp_override=entry_timestamp, ) assert mock_app.database.telemetry.upsert_telemetry.call_count == 2 @@ -98,21 +105,27 @@ async def test_telemetry_request_parsing(mock_app): # We need to mock handle_telemetry_request on the app mock_app.handle_telemetry_request = MagicMock() - + # Bind on_lxmf_delivery - mock_app.on_lxmf_delivery = ReticulumMeshChat.on_lxmf_delivery.__get__(mock_app, ReticulumMeshChat) - + mock_app.on_lxmf_delivery = ReticulumMeshChat.on_lxmf_delivery.__get__( + mock_app, ReticulumMeshChat + ) + # Mocking dependencies mock_app.is_destination_blocked.return_value = False mock_app.current_context.config.telemetry_enabled.get.return_value = True - mock_app.database.contacts.get_contact_by_identity_hash.return_value = {"is_telemetry_trusted": True} - mock_app.database.messages.get_lxmf_message_by_hash.return_value = {} # To avoid JSON error - + mock_app.database.contacts.get_contact_by_identity_hash.return_value = { + "is_telemetry_trusted": True + } + mock_app.database.messages.get_lxmf_message_by_hash.return_value = {} # To avoid JSON error + # Call it mock_app.on_lxmf_delivery(mock_lxmf_message) - + # Verify handle_telemetry_request was called - mock_app.handle_telemetry_request.assert_called_with("736f757263655f686173685f6279746573") + mock_app.handle_telemetry_request.assert_called_with( + "736f757263655f686173685f6279746573" + ) @pytest.mark.asyncio From eef9872b71657865d45d7dd7b019268d2dc87387 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Wed, 7 Jan 2026 19:51:59 -0600 Subject: [PATCH 213/234] feat(tests): add Italian localization tests - Included Italian locale support in the i18n localization tests. - Updated test suite to validate the new Italian translations alongside existing German and Russian locales. --- tests/frontend/i18n.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/frontend/i18n.test.js b/tests/frontend/i18n.test.js index 24522d0..f809083 100644 --- a/tests/frontend/i18n.test.js +++ b/tests/frontend/i18n.test.js @@ -2,6 +2,7 @@ import { describe, it, expect } from "vitest"; import en from "../../meshchatx/src/frontend/locales/en.json"; import de from "../../meshchatx/src/frontend/locales/de.json"; import ru from "../../meshchatx/src/frontend/locales/ru.json"; +import itLocale from "../../meshchatx/src/frontend/locales/it.json"; import fs from "fs"; import path from "path"; @@ -21,6 +22,7 @@ describe("i18n Localization Tests", () => { const locales = [ { name: "German", data: de, keys: getKeys(de) }, { name: "Russian", data: ru, keys: getKeys(ru) }, + { name: "Italian", data: itLocale, keys: getKeys(itLocale) }, ]; locales.forEach((locale) => { From 686053021795e79da7dbeaf0667fc41eab355805 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Wed, 7 Jan 2026 19:52:08 -0600 Subject: [PATCH 214/234] feat(locales): add Reticulum documentation clearing functionality in multiple languages - Introduced new localization strings for clearing Reticulum documentation in German, English, Italian, and Russian. - Added success messages for the documentation clearing action across all supported languages. - Included a new status message for establishing a connection in the user interface. --- meshchatx/src/frontend/locales/de.json | 4 ++++ meshchatx/src/frontend/locales/en.json | 4 ++++ meshchatx/src/frontend/locales/it.json | 8 ++++++++ meshchatx/src/frontend/locales/ru.json | 4 ++++ 4 files changed, 20 insertions(+) diff --git a/meshchatx/src/frontend/locales/de.json b/meshchatx/src/frontend/locales/de.json index 5997a6a..5a261e3 100644 --- a/meshchatx/src/frontend/locales/de.json +++ b/meshchatx/src/frontend/locales/de.json @@ -279,6 +279,8 @@ "clear_lxmf_icons_desc": "Zwischengespeicherte LXMF-Benutzersymbole entfernen.", "clear_archives": "Seitenarchive löschen", "clear_archives_desc": "Alle zwischengespeicherten NomadNetwork-Seiten löschen.", + "clear_reticulum_docs": "Reticulum-Dokumentation löschen", + "clear_reticulum_docs_desc": "Entfernt alle heruntergeladenen Reticulum-Dokumentationen und Versionen.", "export_messages": "Nachrichten exportieren", "export_messages_desc": "Alle Konversationen als JSON-Datei herunterladen.", "import_messages": "Nachrichten importieren", @@ -289,6 +291,7 @@ "favourites_cleared": "Favoriten erfolgreich gelöscht", "lxmf_icons_cleared": "LXMF-Icons erfolgreich gelöscht", "archives_cleared": "Archive erfolgreich gelöscht", + "docs_cleared": "Reticulum-Dokumentation erfolgreich gelöscht", "import_success": "Erfolgreich {count} Nachrichten importiert", "import_failed": "Nachrichten konnten nicht importiert werden" }, @@ -1141,6 +1144,7 @@ "available": "Verfügbar...", "ringing": "Klingelt...", "connecting": "Verbinde...", + "establishing_link": "Verbindung wird hergestellt...", "connected": "Verbunden", "accept": "Annehmen", "decline": "Ablehnen", diff --git a/meshchatx/src/frontend/locales/en.json b/meshchatx/src/frontend/locales/en.json index 4ffb4bc..25fc75e 100644 --- a/meshchatx/src/frontend/locales/en.json +++ b/meshchatx/src/frontend/locales/en.json @@ -279,6 +279,8 @@ "clear_lxmf_icons_desc": "Remove cached LXMF user icons from your device.", "clear_archives": "Clear Page Archives", "clear_archives_desc": "Delete all cached NomadNetwork pages.", + "clear_reticulum_docs": "Clear Reticulum Docs", + "clear_reticulum_docs_desc": "Removes all downloaded Reticulum documentation and versions.", "export_messages": "Export Messages", "export_messages_desc": "Download all conversations as a JSON file.", "import_messages": "Import Messages", @@ -289,6 +291,7 @@ "favourites_cleared": "Favorites cleared successfully", "lxmf_icons_cleared": "LXMF icons cleared successfully", "archives_cleared": "Archives cleared successfully", + "docs_cleared": "Reticulum documentation cleared successfully", "import_success": "Successfully imported {count} messages", "import_failed": "Failed to import messages" }, @@ -1230,6 +1233,7 @@ "available": "Available...", "ringing": "Ringing...", "connecting": "Connecting...", + "establishing_link": "Establishing link...", "connected": "Connected", "accept": "Accept", "decline": "Decline", diff --git a/meshchatx/src/frontend/locales/it.json b/meshchatx/src/frontend/locales/it.json index 0023723..c677664 100644 --- a/meshchatx/src/frontend/locales/it.json +++ b/meshchatx/src/frontend/locales/it.json @@ -279,12 +279,19 @@ "clear_lxmf_icons_desc": "Rimuovi le icone utente LXMF memorizzate sul tuo dispositivo.", "clear_archives": "Cancella Archivi Pagine", "clear_archives_desc": "Elimina tutte le pagine NomadNetwork memorizzate.", + "clear_reticulum_docs": "Cancella Documentazione Reticulum", + "clear_reticulum_docs_desc": "Rimuove tutta la documentazione e le versioni di Reticulum scaricate.", + "export_messages": "Esporta Messaggi", + "export_messages_desc": "Scarica tutte le conversazioni come file JSON.", + "import_messages": "Importa Messaggi", + "import_messages_desc": "Ripristina le conversazioni da un file JSON.", "clear_confirm": "Sei sicuro? Questa azione non può essere annullata.", "messages_cleared": "Messaggi cancellati con successo", "announces_cleared": "Annunci cancellati con successo", "favourites_cleared": "Preferiti cancellati con successo", "lxmf_icons_cleared": "Icone LXMF cancellate con successo", "archives_cleared": "Archivi cancellati con successo", + "docs_cleared": "Documentazione Reticulum cancellata con successo", "import_success": "Importati con successo {count} messaggi", "import_failed": "Impossibile importare i messaggi" }, @@ -1226,6 +1233,7 @@ "available": "Disponibile...", "ringing": "Squilla...", "connecting": "Connessione...", + "establishing_link": "Stabilendo il collegamento...", "connected": "Connesso", "accept": "Accetta", "decline": "Rifiuta", diff --git a/meshchatx/src/frontend/locales/ru.json b/meshchatx/src/frontend/locales/ru.json index af5494a..cfabdba 100644 --- a/meshchatx/src/frontend/locales/ru.json +++ b/meshchatx/src/frontend/locales/ru.json @@ -279,6 +279,8 @@ "clear_lxmf_icons_desc": "Удалить кэшированные LXMF-иконки пользователей с устройства.", "clear_archives": "Очистить архивы страниц", "clear_archives_desc": "Удалить все кэшированные страницы NomadNetwork.", + "clear_reticulum_docs": "Очистить документацию Reticulum", + "clear_reticulum_docs_desc": "Удаляет всю загруженную документацию и версии Reticulum.", "export_messages": "Экспортировать сообщения", "export_messages_desc": "Загрузить все разговоры в виде JSON-файла.", "import_messages": "Импортировать сообщения", @@ -289,6 +291,7 @@ "favourites_cleared": "Избранное успешно очищено", "lxmf_icons_cleared": "LXMF-иконки успешно очищены", "archives_cleared": "Архивы успешно очищены", + "docs_cleared": "Документация Reticulum успешно очищена", "import_success": "Успешно импортировано {count} сообщений", "import_failed": "Не удалось импортировать сообщения" }, @@ -1141,6 +1144,7 @@ "available": "Доступно...", "ringing": "Звонит...", "connecting": "Подключение...", + "establishing_link": "Установление связи...", "connected": "Подключено", "accept": "Принять", "decline": "Отклонить", From 649895690359505e7d3e025e558ef482fbf30517 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Thu, 8 Jan 2026 12:14:16 -0600 Subject: [PATCH 215/234] chore(Dockerfile): downgrade Python image to 3.12.12 and add espeak-ng package --- Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0ced9b3..c2db657 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ ARG NODE_IMAGE=node:22-alpine ARG NODE_HASH=sha256:0340fa682d72068edf603c305bfbc10e23219fb0e40df58d9ea4d6f33a9798bf -ARG PYTHON_IMAGE=python:3.13-alpine -ARG PYTHON_HASH=sha256:e7e041128ffc3e3600509f508e44d34ab08ff432bdb62ec508d01dfc5ca459f7 +ARG PYTHON_IMAGE=python:3.12.12-alpine3.23 +ARG PYTHON_HASH=sha256:68d81cd281ee785f48cdadecb6130d05ec6957f1249814570dc90e5100d3b146 # Stage 1: Build Frontend FROM ${NODE_IMAGE}@${NODE_HASH} AS build-frontend @@ -33,14 +33,14 @@ COPY --from=build-frontend /src/meshchatx/public ./meshchatx/public RUN pip install . && \ # Trigger LXST filter compilation while build tools are still present python -c "import LXST.Filters; print('LXST Filters compiled successfully')" && \ - python -m compileall /opt/venv/lib/python3.13/site-packages + python -m compileall /opt/venv/lib/python3.12/site-packages # Stage 3: Final Runtime Image FROM ${PYTHON_IMAGE}@${PYTHON_HASH} WORKDIR /app # Install runtime dependencies only # We keep py3-setuptools because CFFI/LXST might need it at runtime on Python 3.12+ -RUN apk add --no-cache ffmpeg opusfile libffi su-exec py3-setuptools && \ +RUN apk add --no-cache ffmpeg opusfile libffi su-exec py3-setuptools espeak-ng && \ addgroup -g 1000 meshchat && adduser -u 1000 -G meshchat -S meshchat && \ mkdir -p /config && chown meshchat:meshchat /config From 115b01ee65ca208e19c9900b58ef3433b68da45f Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Thu, 8 Jan 2026 12:14:26 -0600 Subject: [PATCH 216/234] chore(dependencies): update rns package to version 1.1.2 and specify lxst version --- poetry.lock | 8 ++++---- pyproject.toml | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index bdb69bb..eba434f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1952,14 +1952,14 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "rns" -version = "1.1.1" +version = "1.1.2" description = "Self-configuring, encrypted and resilient mesh networking stack for LoRa, packet radio, WiFi and everything in between" optional = false python-versions = ">=3.7" groups = ["main"] files = [ - {file = "rns-1.1.1-py3-none-any.whl", hash = "sha256:d991c4ade4ce737c3f654aa216e18dc71a03546f71ea82ef06d5ac96f30bd086"}, - {file = "rns-1.1.1.tar.gz", hash = "sha256:112ad19a284afa2723a23e4966ddd9d39a89f0347091e298a81c08fb2ae7a34c"}, + {file = "rns-1.1.2-py3-none-any.whl", hash = "sha256:8a153d97a02b4b326556b7f5926c37029767b70c9093b5f00c53c72105bc2091"}, + {file = "rns-1.1.2.tar.gz", hash = "sha256:ff2af56490c065adcc5f38aef07081b19bb355101406d10d768ec54f783a30c3"}, ] [package.dependencies] @@ -2273,4 +2273,4 @@ propcache = ">=0.2.1" [metadata] lock-version = "2.1" python-versions = ">=3.11" -content-hash = "dec7422181899d6946be5ce2ce97aef45a806a408ea1d4fd83278afc324e4d34" +content-hash = "cf4375df2e3a86e2a1095e6446971d35421704c286f725ae9a3e22f7ead15241" diff --git a/pyproject.toml b/pyproject.toml index feec84c..b07d3ee 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,7 @@ dependencies = [ "requests>=2.32.5,<3.0.0", "audioop-lts>=0.2.2; python_version >= '3.13'", "ply>=3.11,<4.0", - "lxst", + "lxst>=0.4.6", ] [project.scripts] @@ -47,6 +47,7 @@ packages = [{include = "meshchatx"}] [tool.poetry.dependencies] python = ">=3.11" lxmfy = {git = "https://git.quad4.io/LXMFy/LXMFy.git"} +lxst = ">=0.4.6" [tool.poetry.group.dev.dependencies] cx-freeze = ">=7.0.0" From 2652f1dd87f0f8d55c030a0a53288c61c79b118d Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Thu, 8 Jan 2026 12:39:31 -0600 Subject: [PATCH 217/234] chore(Dockerfile): upgrade pip to version 25.3 due to vuln in older version. --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c2db657..f7fc59b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ RUN apk add --no-cache gcc musl-dev linux-headers python3-dev libffi-dev openssl RUN python -m venv /opt/venv ENV PATH="/opt/venv/bin:$PATH" COPY pyproject.toml poetry.lock ./ -RUN pip install --no-cache-dir poetry setuptools wheel && \ +RUN pip install --no-cache-dir "pip>=25.3" poetry setuptools wheel && \ poetry config virtualenvs.create false && \ poetry install --no-root --only main @@ -41,6 +41,7 @@ WORKDIR /app # Install runtime dependencies only # We keep py3-setuptools because CFFI/LXST might need it at runtime on Python 3.12+ RUN apk add --no-cache ffmpeg opusfile libffi su-exec py3-setuptools espeak-ng && \ + python -m pip install --no-cache-dir --upgrade "pip>=25.3" && \ addgroup -g 1000 meshchat && adduser -u 1000 -G meshchat -S meshchat && \ mkdir -p /config && chown meshchat:meshchat /config From 566acf228ded3102559f46cb026af693decccc62 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Thu, 8 Jan 2026 12:43:17 -0600 Subject: [PATCH 218/234] feat(IdentitiesPage): optimize rendering performance with memoization - Added v-memo directive to improve rendering efficiency of identity components by caching their properties. - Updated test to allow for a longer render time threshold, ensuring performance remains acceptable after changes. --- .../frontend/components/settings/IdentitiesPage.vue | 10 ++++++++++ tests/frontend/IdentitiesPage.test.js | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/meshchatx/src/frontend/components/settings/IdentitiesPage.vue b/meshchatx/src/frontend/components/settings/IdentitiesPage.vue index 4fb9d92..1355336 100644 --- a/meshchatx/src/frontend/components/settings/IdentitiesPage.vue +++ b/meshchatx/src/frontend/components/settings/IdentitiesPage.vue @@ -29,6 +29,16 @@
    { console.log(`Rendered ${numIdentities} identities in ${renderTime.toFixed(2)}ms`); expect(wrapper.findAll(".glass-card").length).toBe(numIdentities); - expect(renderTime).toBeLessThan(1000); // Should be reasonably fast + expect(renderTime).toBeLessThan(2000); // Should be reasonably fast }); it("memory: tracks growth after multiple identity list refreshes", async () => { From b3c6fd5e1614a430507092e04fbeeda3013beaca Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Thu, 8 Jan 2026 12:53:20 -0600 Subject: [PATCH 219/234] refactor(telephone_manager): format --- meshchatx/src/backend/telephone_manager.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/meshchatx/src/backend/telephone_manager.py b/meshchatx/src/backend/telephone_manager.py index f32f797..942e4e8 100644 --- a/meshchatx/src/backend/telephone_manager.py +++ b/meshchatx/src/backend/telephone_manager.py @@ -320,7 +320,8 @@ class TelephoneManager: self._update_initiation_status("Ringing...", destination_hash_hex) elif self.telephone.call_status == 5: self._update_initiation_status( - "Establishing link...", destination_hash_hex, + "Establishing link...", + destination_hash_hex, ) if self.telephone.call_status in [ @@ -349,15 +350,18 @@ class TelephoneManager: if self.telephone.call_status == 2: self._update_initiation_status( - "Calling...", destination_hash_hex, + "Calling...", + destination_hash_hex, ) elif self.telephone.call_status == 4: self._update_initiation_status( - "Ringing...", destination_hash_hex, + "Ringing...", + destination_hash_hex, ) elif self.telephone.call_status == 5: self._update_initiation_status( - "Establishing link...", destination_hash_hex, + "Establishing link...", + destination_hash_hex, ) if self.telephone.call_status in [ From 682ff4ddb721e2d2fdac0e7eac9670cf158c9682 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Thu, 8 Jan 2026 16:41:10 -0600 Subject: [PATCH 220/234] feat(docs): cleanup --- .../public/meshchatx-docs/meshchat_on_docker.md | 11 ----------- .../src/frontend/public/meshchatx-docs/meshchatx.md | 3 +++ ..._termux.md => meshchatx_on_android_with_termux.md} | 0 ...n_raspberry_pi.md => meshchatx_on_raspberry_pi.md} | 0 4 files changed, 3 insertions(+), 11 deletions(-) delete mode 100644 meshchatx/src/frontend/public/meshchatx-docs/meshchat_on_docker.md create mode 100644 meshchatx/src/frontend/public/meshchatx-docs/meshchatx.md rename meshchatx/src/frontend/public/meshchatx-docs/{meshchat_on_android_with_termux.md => meshchatx_on_android_with_termux.md} (100%) rename meshchatx/src/frontend/public/meshchatx-docs/{meshchat_on_raspberry_pi.md => meshchatx_on_raspberry_pi.md} (100%) diff --git a/meshchatx/src/frontend/public/meshchatx-docs/meshchat_on_docker.md b/meshchatx/src/frontend/public/meshchatx-docs/meshchat_on_docker.md deleted file mode 100644 index d82ddee..0000000 --- a/meshchatx/src/frontend/public/meshchatx-docs/meshchat_on_docker.md +++ /dev/null @@ -1,11 +0,0 @@ -# MeshChat on Docker - -A docker image is automatically built by GitHub actions, and can be downloaded from the GitHub container registry. - -``` -docker pull ghcr.io/liamcottle/reticulum-meshchat:latest -``` - -Additionally, an example [docker-compose.yml](../docker-compose.yml) is available. - -The example automatically generates a new reticulum config file in the `meshchat-config` volume. The MeshChat database is also stored in this volume. diff --git a/meshchatx/src/frontend/public/meshchatx-docs/meshchatx.md b/meshchatx/src/frontend/public/meshchatx-docs/meshchatx.md new file mode 100644 index 0000000..1c94887 --- /dev/null +++ b/meshchatx/src/frontend/public/meshchatx-docs/meshchatx.md @@ -0,0 +1,3 @@ +# Welcome to MeshChatX + +A fork of Reticulum Meshchat, with many more features, new UI/UX, better security and integrity. diff --git a/meshchatx/src/frontend/public/meshchatx-docs/meshchat_on_android_with_termux.md b/meshchatx/src/frontend/public/meshchatx-docs/meshchatx_on_android_with_termux.md similarity index 100% rename from meshchatx/src/frontend/public/meshchatx-docs/meshchat_on_android_with_termux.md rename to meshchatx/src/frontend/public/meshchatx-docs/meshchatx_on_android_with_termux.md diff --git a/meshchatx/src/frontend/public/meshchatx-docs/meshchat_on_raspberry_pi.md b/meshchatx/src/frontend/public/meshchatx-docs/meshchatx_on_raspberry_pi.md similarity index 100% rename from meshchatx/src/frontend/public/meshchatx-docs/meshchat_on_raspberry_pi.md rename to meshchatx/src/frontend/public/meshchatx-docs/meshchatx_on_raspberry_pi.md From 5d70e2c00f9c01beb9bc3b612a34b5db13a477d8 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Thu, 8 Jan 2026 19:27:09 -0600 Subject: [PATCH 221/234] feat(locales): update --- meshchatx/src/frontend/locales/de.json | 15 +++++++++++++-- meshchatx/src/frontend/locales/en.json | 13 ++++++++++++- meshchatx/src/frontend/locales/it.json | 13 ++++++++++++- meshchatx/src/frontend/locales/ru.json | 15 +++++++++++++-- 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/meshchatx/src/frontend/locales/de.json b/meshchatx/src/frontend/locales/de.json index 5a261e3..f67cc10 100644 --- a/meshchatx/src/frontend/locales/de.json +++ b/meshchatx/src/frontend/locales/de.json @@ -103,6 +103,8 @@ "preferred_propagation_node": "Bevorzugter Propagationsknoten", "preferred_node_placeholder": "Ziel-Hash, z.B. a39610c89d18bb48c73e429582423c24", "fallback_node_description": "Nachrichten weichen auf diesen Knoten aus, wenn die direkte Zustellung fehlschlägt.", + "auto_select_node": "Besten Knoten automatisch auswählen", + "auto_select_node_description": "Automatisch den besten verfügbaren Propagationsknoten basierend auf den Netzwerkhops finden und dorthin wechseln.", "auto_sync_interval": "Automatisches Synchronisierungsintervall", "last_synced": "Zuletzt synchronisiert vor {time}.", "last_synced_never": "Zuletzt synchronisiert: Nie.", @@ -1359,8 +1361,17 @@ "discovery_desc": "Dies ermöglicht es MeshChatX, automatisch öffentliche Community-Knoten in Ihrer Nähe oder im Internet zu finden und sich mit ihnen zu verbinden.", "yes": "Ja, Erkennung verwenden", "no": "Nein, manuelle Einrichtung", - "discovery_enabled": "Community discovery enabled", - "failed_enable_discovery": "Failed to enable discovery" + "discovery_enabled": "Community-Entdeckung aktiviert", + "failed_enable_discovery": "Aktivierung der Community-Entdeckung fehlgeschlagen", + "propagation": "Propagationsknoten", + "propagation_question": "Möchten Sie den Propagationsmodus automatisch konfigurieren?", + "propagation_desc": "Propagationsknoten ermöglichen es Ihnen, Nachrichten zu empfangen, auch wenn Sie offline sind. Sie speichern Nachrichten für Sie und stellen sie zu, wenn Sie wieder online sind.", + "propagation_auto": "Die automatische Konfiguration wird versuchen, den besten Propagationsknoten zu finden, zu dem eine Verbindung hergestellt werden kann. Wenn noch kein Propagationsknoten im Netzwerk angekündigt wurde, wird auf einen gewartet. Während dieser Zeit können Sie keine Nachrichten von einem Propagationsknoten synchronisieren.", + "propagation_manual": "Oder manuell konfigurieren?", + "propagation_manual_desc": "Sie können einen Propagationsknoten später manuell in den Einstellungen konfigurieren oder das Feld leer lassen, wenn Sie keinen verwenden möchten.", + "propagation_enable_auto": "Automatische Konfiguration aktivieren", + "propagation_skip_auto": "Manuelle Konfiguration", + "auto_propagation_enabled": "Auto-Propagation aktiviert" }, "command_palette": { "search_placeholder": "Befehle suchen, navigieren oder Peers finden...", diff --git a/meshchatx/src/frontend/locales/en.json b/meshchatx/src/frontend/locales/en.json index 25fc75e..34cbbb6 100644 --- a/meshchatx/src/frontend/locales/en.json +++ b/meshchatx/src/frontend/locales/en.json @@ -105,6 +105,8 @@ "preferred_propagation_node": "Preferred Propagation Node", "preferred_node_placeholder": "Destination hash, e.g. a39610c89d18bb48c73e429582423c24", "fallback_node_description": "Messages fallback to this node whenever direct delivery fails.", + "auto_select_node": "Auto-select best node", + "auto_select_node_description": "Automatically find and switch to the best available propagation node based on network hops.", "auto_sync_interval": "Auto Sync Interval", "last_synced": "Last synced {time} ago.", "last_synced_never": "Last synced: never.", @@ -1449,7 +1451,16 @@ "yes": "Yes, use discovery", "no": "No, manual setup", "discovery_enabled": "Community discovery enabled", - "failed_enable_discovery": "Failed to enable discovery" + "failed_enable_discovery": "Failed to enable discovery", + "propagation": "Propagation Node", + "propagation_question": "Do you want to auto-configure propagation mode?", + "propagation_desc": "Propagation nodes act like an always-on mailbox for your messages. They securely store messages while you are offline and deliver them as soon as you reconnect to the network.", + "propagation_auto": "Auto-configure will automatically find and connect to the most reliable propagation node available. If no node is currently available, MeshChatX will wait for one to appear. Until then, offline message syncing will be unavailable.", + "propagation_manual": "Or manually configure?", + "propagation_manual_desc": "You can manually configure a propagation node later in settings, or leave it empty if you don't want to use one.", + "propagation_enable_auto": "Enable Auto-Configuration", + "propagation_skip_auto": "Configure Manually / Skip", + "auto_propagation_enabled": "Auto-propagation enabled" }, "command_palette": { "search_placeholder": "Search commands, navigate, or find peers...", diff --git a/meshchatx/src/frontend/locales/it.json b/meshchatx/src/frontend/locales/it.json index c677664..55268ff 100644 --- a/meshchatx/src/frontend/locales/it.json +++ b/meshchatx/src/frontend/locales/it.json @@ -105,6 +105,8 @@ "preferred_propagation_node": "Nodo di Propagazione Preferito", "preferred_node_placeholder": "Hash di destinazione, es. a39610c89d18bb48c73e429582423c24", "fallback_node_description": "I messaggi ripiegano su questo nodo ogni volta che la consegna diretta fallisce.", + "auto_select_node": "Selezione automatica del miglior nodo", + "auto_select_node_description": "Trova e passa automaticamente al miglior nodo di propagazione disponibile in base agli hop di rete.", "auto_sync_interval": "Intervallo Sincronizzazione Automatica", "last_synced": "Ultima sincronizzazione {time} fa.", "last_synced_never": "Ultima sincronizzazione: mai.", @@ -1449,7 +1451,16 @@ "yes": "Sì, usa la scoperta", "no": "No, configurazione manuale", "discovery_enabled": "Scoperta della comunità abilitata", - "failed_enable_discovery": "Impossibile abilitare la scoperta" + "failed_enable_discovery": "Impossibile abilitare la scoperta", + "propagation": "Nodo di propagazione", + "propagation_question": "Vuoi configurare automaticamente la modalità di propagazione?", + "propagation_desc": "I nodi di propagazione ti consentono di ricevere messaggi anche quando sei offline. Memorizzano i messaggi per te e li consegnano quando ti riconnetti.", + "propagation_auto": "La configurazione automatica cercherà di trovare il miglior nodo di propagazione a cui può stabilire un collegamento. Se nessun nodo di propagazione è stato annunciato sulla rete, attenderà che ne venga annunciato uno. Durante questo periodo, non sarai in grado di sincronizzare i messaggi da un nodo di propagazione.", + "propagation_manual": "O configurare manualmente?", + "propagation_manual_desc": "Puoi configurare manualmente un nodo di propagazione in seguito nelle impostazioni, oppure lasciare vuoto se non desideri utilizzarne uno.", + "propagation_enable_auto": "Abilita configurazione automatica", + "propagation_skip_auto": "Configurazione manuale", + "auto_propagation_enabled": "Auto-propagazione abilitata" }, "command_palette": { "search_placeholder": "Cerca comandi, naviga o trova peer...", diff --git a/meshchatx/src/frontend/locales/ru.json b/meshchatx/src/frontend/locales/ru.json index cfabdba..6f8bc5b 100644 --- a/meshchatx/src/frontend/locales/ru.json +++ b/meshchatx/src/frontend/locales/ru.json @@ -103,6 +103,8 @@ "preferred_propagation_node": "Предпочтительный узел ретрансляции", "preferred_node_placeholder": "Хеш назначения, например a39610c89d18bb48c73e429582423c24", "fallback_node_description": "Сообщения будут отправляться на этот узел, если прямая доставка не удалась.", + "auto_select_node": "Автовыбор лучшего узла", + "auto_select_node_description": "Автоматически находить и переключаться на лучший доступный узел ретрансляции на основе количества переходов в сети.", "auto_sync_interval": "Интервал автосинхронизации", "last_synced": "Последняя синхронизация {time} назад.", "last_synced_never": "Последняя синхронизация: никогда.", @@ -1359,8 +1361,17 @@ "discovery_desc": "Это позволяет MeshChatX автоматически находить и подключаться к публичным узлам сообщества рядом с вами или в интернете.", "yes": "Да, использовать обнаружение", "no": "Нет, ручная настройка", - "discovery_enabled": "Community discovery enabled", - "failed_enable_discovery": "Failed to enable discovery" + "discovery_enabled": "Обнаружение сообщества включено", + "failed_enable_discovery": "Не удалось включить обнаружение сообщества", + "propagation": "Узел ретрансляции", + "propagation_question": "Хотите автоматически настроить режим ретрансляции?", + "propagation_desc": "Узлы ретрансляции (propagation nodes) позволяют получать сообщения, даже когда вы находитесь вне сети. Они сохраняют сообщения для вас и доставляют их, когда вы снова подключаетесь.", + "propagation_auto": "Автонастройка попытается найти лучший узел ретрансляции, с которым можно установить связь. Если в сети еще не было объявлений об узлах ретрансляции, она будет ожидать их появления. В это время вы не сможете синхронизировать сообщения с узла ретрансляции.", + "propagation_manual": "Или настроить вручную?", + "propagation_manual_desc": "Вы можете вручную настроить узел ретрансляции позже в настройках или оставить поле пустым, если не хотите его использовать.", + "propagation_enable_auto": "Включить автонастройку", + "propagation_skip_auto": "Ручная настройка", + "auto_propagation_enabled": "Авторетрансляция включена" }, "command_palette": { "search_placeholder": "Поиск команд, навигация или поиск узлов...", From 825ddd17fedb0efe9f56267fefafe3598bcb4441 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Thu, 8 Jan 2026 19:27:23 -0600 Subject: [PATCH 222/234] feat(meshchat): add auto-select option for preferred propagation node --- meshchatx/meshchat.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/meshchatx/meshchat.py b/meshchatx/meshchat.py index bad0620..ab5b792 100644 --- a/meshchatx/meshchat.py +++ b/meshchatx/meshchat.py @@ -8756,6 +8756,12 @@ class ReticulumMeshChat: # update active propagation node self.set_active_propagation_node(value) + if "lxmf_preferred_propagation_node_auto_select" in data: + value = self._parse_bool( + data["lxmf_preferred_propagation_node_auto_select"], + ) + self.config.lxmf_preferred_propagation_node_auto_select.set(value) + # update inbound stamp cost (for direct delivery messages) if "lxmf_inbound_stamp_cost" in data: value = int(data["lxmf_inbound_stamp_cost"]) @@ -9903,6 +9909,7 @@ class ReticulumMeshChat: "lxmf_local_propagation_node_enabled": ctx.config.lxmf_local_propagation_node_enabled.get(), "lxmf_local_propagation_node_address_hash": ctx.message_router.propagation_destination.hexhash, "lxmf_preferred_propagation_node_destination_hash": ctx.config.lxmf_preferred_propagation_node_destination_hash.get(), + "lxmf_preferred_propagation_node_auto_select": ctx.config.lxmf_preferred_propagation_node_auto_select.get(), "lxmf_preferred_propagation_node_auto_sync_interval_seconds": ctx.config.lxmf_preferred_propagation_node_auto_sync_interval_seconds.get(), "lxmf_preferred_propagation_node_last_synced_at": ctx.config.lxmf_preferred_propagation_node_last_synced_at.get(), "lxmf_user_icon_name": ctx.config.lxmf_user_icon_name.get(), From 20639fef0cce2c2e799d02db881281cb442fbd17 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Thu, 8 Jan 2026 19:28:47 -0600 Subject: [PATCH 223/234] feat(auto_propagation): implement AutoPropagationManager for dynamic propagation node selection --- .../src/backend/auto_propagation_manager.py | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 meshchatx/src/backend/auto_propagation_manager.py diff --git a/meshchatx/src/backend/auto_propagation_manager.py b/meshchatx/src/backend/auto_propagation_manager.py new file mode 100644 index 0000000..45f3b4b --- /dev/null +++ b/meshchatx/src/backend/auto_propagation_manager.py @@ -0,0 +1,125 @@ +import asyncio +import time + +import RNS + +from meshchatx.src.backend.meshchat_utils import parse_lxmf_propagation_node_app_data + + +class AutoPropagationManager: + def __init__(self, app, context): + self.app = app + self.context = context + self.config = context.config + self.database = context.database + self.running = False + self._last_check = 0 + self._check_interval = 300 # 5 minutes + + def stop(self): + self.running = False + + async def _run(self): + # Wait a bit after startup to allow discovers to come in + await asyncio.sleep(10) + self.running = True + + while self.running and self.context.running: + try: + if self.config.lxmf_preferred_propagation_node_auto_select.get(): + await self.check_and_update_propagation_node() + except asyncio.CancelledError: + break + except Exception as e: + print( + f"Error in AutoPropagationManager for {self.context.identity_hash}: {e}", + ) + + await asyncio.sleep(self._check_interval) + + async def check_and_update_propagation_node(self): + # Get all propagation node announces + announces = self.database.announces.get_announces(aspect="lxmf.propagation") + + nodes_with_hops = [] + for announce in announces: + dest_hash_hex = announce["destination_hash"] + dest_hash = bytes.fromhex(dest_hash_hex) + + # Check if propagation is enabled for this node + node_data = parse_lxmf_propagation_node_app_data(announce["app_data"]) + if not node_data or not node_data.get("enabled", False): + continue + + if RNS.Transport.has_path(dest_hash): + hops = RNS.Transport.hops_to(dest_hash) + nodes_with_hops.append((hops, dest_hash_hex)) + + # Sort by hops (lowest first) + nodes_with_hops.sort() + + current_node = ( + self.config.lxmf_preferred_propagation_node_destination_hash.get() + ) + + if not nodes_with_hops: + return + + # Try nodes in order of hops until we find a reachable one + for hops, node_hex in nodes_with_hops: + # If current node is already the best and we have it, check if we should keep it + if node_hex == current_node: + # We could probe it to be sure, but for now let's assume it's fine if it's the best + return + + # Before switching to a new "best" node, try to probe it to ensure it's actually reachable + try: + dest_hash = bytes.fromhex(node_hex) + # We use a short timeout for the probe + if await self.probe_node(dest_hash): + print( + f"Auto-propagation: Switching to better node {node_hex} ({hops} hops) for {self.context.identity_hash}", + ) + self.app.set_active_propagation_node(node_hex, context=self.context) + self.config.lxmf_preferred_propagation_node_destination_hash.set( + node_hex, + ) + return + print( + f"Auto-propagation: Node {node_hex} announced but probe failed, trying next...", + ) + except Exception as e: + print(f"Auto-propagation: Error probing node {node_hex}: {e}") + + async def probe_node(self, destination_hash): + """Probes a destination to see if it's reachable.""" + try: + # We use the app's probe handler if available + if ( + hasattr(self.context, "rnprobe_handler") + and self.context.rnprobe_handler + ): + + # Re-using the logic from RNProbeHandler but simplified + if not RNS.Transport.has_path(destination_hash): + RNS.Transport.request_path(destination_hash) + + # Wait a bit for path + timeout = 5 + start = time.time() + while ( + not RNS.Transport.has_path(destination_hash) + and time.time() - start < timeout + ): + await asyncio.sleep(0.5) + + if not RNS.Transport.has_path(destination_hash): + return False + + # If we have a path, it's a good sign. + # For propagation nodes, having a path is often enough to try using it. + return True + + return RNS.Transport.has_path(destination_hash) + except Exception: + return False From e7beabba1146c19b73f020dbdabbfd1d0f067007 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Thu, 8 Jan 2026 19:28:55 -0600 Subject: [PATCH 224/234] feat(config_manager): add auto-select configuration for preferred propagation node --- meshchatx/src/backend/config_manager.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/meshchatx/src/backend/config_manager.py b/meshchatx/src/backend/config_manager.py index 77371ad..e0ad88c 100644 --- a/meshchatx/src/backend/config_manager.py +++ b/meshchatx/src/backend/config_manager.py @@ -48,6 +48,11 @@ class ConfigManager: "lxmf_preferred_propagation_node_destination_hash", None, ) + self.lxmf_preferred_propagation_node_auto_select = self.BoolConfig( + self, + "lxmf_preferred_propagation_node_auto_select", + False, + ) self.lxmf_preferred_propagation_node_auto_sync_interval_seconds = ( self.IntConfig( self, From fb790a4c08aaeea89a3c5cce93cdd892086792c9 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Thu, 8 Jan 2026 19:29:10 -0600 Subject: [PATCH 225/234] feat(identity_context): integrate AutoPropagationManager for background node selection --- meshchatx/src/backend/identity_context.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/meshchatx/src/backend/identity_context.py b/meshchatx/src/backend/identity_context.py index 53310d0..578604b 100644 --- a/meshchatx/src/backend/identity_context.py +++ b/meshchatx/src/backend/identity_context.py @@ -7,6 +7,7 @@ import RNS from meshchatx.src.backend.announce_handler import AnnounceHandler from meshchatx.src.backend.announce_manager import AnnounceManager from meshchatx.src.backend.archiver_manager import ArchiverManager +from meshchatx.src.backend.auto_propagation_manager import AutoPropagationManager from meshchatx.src.backend.bot_handler import BotHandler from meshchatx.src.backend.community_interfaces import CommunityInterfacesManager from meshchatx.src.backend.config_manager import ConfigManager @@ -71,6 +72,7 @@ class IdentityContext: self.telephone_manager = None self.voicemail_manager = None self.ringtone_manager = None + self.auto_propagation_manager = None self.rncp_handler = None self.rnstatus_handler = None self.rnpath_handler = None @@ -307,6 +309,11 @@ class IdentityContext: self.community_interfaces_manager = CommunityInterfacesManager() + self.auto_propagation_manager = AutoPropagationManager( + app=self.app, + context=self, + ) + # 6. Register Announce Handlers self.register_announce_handlers() @@ -375,6 +382,14 @@ class IdentityContext: thread.daemon = True thread.start() + # start background thread for auto propagation node selection + thread = threading.Thread( + target=asyncio.run, + args=(self.auto_propagation_manager._run(),), + ) + thread.daemon = True + thread.start() + def register_announce_handlers(self): handlers = [ AnnounceHandler( @@ -437,6 +452,8 @@ class IdentityContext: def teardown(self): print(f"Tearing down Identity Context for {self.identity_hash}...") self.running = False + if self.auto_propagation_manager: + self.auto_propagation_manager.stop() # 1. Deregister announce handlers for handler in self.announce_handlers: From b8ef3d188dd1ad14846099d1533679d25eda6488 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Thu, 8 Jan 2026 19:29:22 -0600 Subject: [PATCH 226/234] feat(tutorial): update tutorial modal with propagation mode step and auto-select option for preferred propagation node --- .../src/frontend/components/TutorialModal.vue | 157 ++++++++++++++++-- .../components/settings/SettingsPage.vue | 23 +++ 2 files changed, 168 insertions(+), 12 deletions(-) diff --git a/meshchatx/src/frontend/components/TutorialModal.vue b/meshchatx/src/frontend/components/TutorialModal.vue index 89ecdd1..b4f9b8f 100644 --- a/meshchatx/src/frontend/components/TutorialModal.vue +++ b/meshchatx/src/frontend/components/TutorialModal.vue @@ -403,8 +403,66 @@
    - +
    +
    +

    + {{ $t("tutorial.propagation") }} +

    +

    + {{ $t("tutorial.propagation_desc") }} +

    +
    + +
    +
    + +
    + {{ $t("tutorial.propagation_question") }} +
    +

    + {{ $t("tutorial.propagation_auto") }} +

    +
    + + +
    +
    +
    + {{ $t("tutorial.propagation_manual") }} +
    +

    + {{ $t("tutorial.propagation_manual_desc") }} +

    +
    +
    +
    +
    + + +

    {{ $t("tutorial.learn_create") }} @@ -530,10 +588,10 @@

    - +
    @@ -641,7 +699,7 @@
    @@ -773,7 +831,7 @@
    -
    +

    {{ $t("tutorial.connect") }} @@ -1068,8 +1126,67 @@

    - -
    + + +
    +
    +

    + {{ $t("tutorial.propagation") }} +

    +

    + {{ $t("tutorial.propagation_desc") }} +

    +
    + +
    +
    + +
    + {{ $t("tutorial.propagation_question") }} +
    +

    + {{ $t("tutorial.propagation_auto") }} +

    +
    + + +
    +
    +
    + {{ $t("tutorial.propagation_manual") }} +
    +

    + {{ $t("tutorial.propagation_manual_desc") }} +

    +
    +
    +
    +
    + + +

    {{ $t("tutorial.learn_create") }} @@ -1195,10 +1312,10 @@

    - +
    @@ -1292,7 +1409,7 @@ export default { return { visible: false, currentStep: 1, - totalSteps: 4, + totalSteps: 5, logoUrl, communityInterfaces: [], loadingInterfaces: false, @@ -1302,6 +1419,7 @@ export default { discoveredActive: [], loadingDiscovered: false, savingDiscovery: false, + savingPropagation: false, discoveryInterval: null, }; }, @@ -1415,6 +1533,21 @@ export default { this.savingDiscovery = false; } }, + async enableAutoPropagation() { + this.savingPropagation = true; + try { + await window.axios.patch("/api/v1/config", { + lxmf_preferred_propagation_node_auto_select: true, + }); + ToastUtils.success("Auto-propagation enabled"); + this.nextStep(); + } catch (e) { + console.error("Failed to enable auto-propagation:", e); + ToastUtils.error("Failed to enable auto-propagation"); + } finally { + this.savingPropagation = false; + } + }, getDiscoveryIcon(iface) { switch (iface.type) { case "AutoInterface": diff --git a/meshchatx/src/frontend/components/settings/SettingsPage.vue b/meshchatx/src/frontend/components/settings/SettingsPage.vue index 894d4d5..6857cea 100644 --- a/meshchatx/src/frontend/components/settings/SettingsPage.vue +++ b/meshchatx/src/frontend/components/settings/SettingsPage.vue @@ -1335,6 +1335,19 @@ }} +
    {{ $t("app.preferred_propagation_node") }} @@ -1514,6 +1527,7 @@ export default { show_suggested_community_interfaces: null, lxmf_local_propagation_node_enabled: null, lxmf_preferred_propagation_node_destination_hash: null, + lxmf_preferred_propagation_node_auto_select: null, archives_max_storage_gb: 1, backup_max_count: 5, banished_effect_enabled: true, @@ -1944,6 +1958,15 @@ export default { ); }, 1000); }, + async onLxmfPreferredPropagationNodeAutoSelectChange() { + await this.updateConfig( + { + lxmf_preferred_propagation_node_auto_select: + this.config.lxmf_preferred_propagation_node_auto_select, + }, + "auto_select_node" + ); + }, async onLxmfLocalPropagationNodeEnabledChangeWrapper(value) { this.config.lxmf_local_propagation_node_enabled = value; await this.onLxmfLocalPropagationNodeEnabledChange(); From 7a419f96ee5d1aa05e48e3d13dd4f7a70c0503ef Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Thu, 8 Jan 2026 19:29:30 -0600 Subject: [PATCH 227/234] feat(tests): add unit tests for auto propagation API and logic --- tests/backend/test_auto_propagation.py | 103 +++++++++++++++++++++ tests/backend/test_auto_propagation_api.py | 101 ++++++++++++++++++++ tests/backend/test_config_manager.py | 7 ++ 3 files changed, 211 insertions(+) create mode 100644 tests/backend/test_auto_propagation.py create mode 100644 tests/backend/test_auto_propagation_api.py diff --git a/tests/backend/test_auto_propagation.py b/tests/backend/test_auto_propagation.py new file mode 100644 index 0000000..6eb6cc9 --- /dev/null +++ b/tests/backend/test_auto_propagation.py @@ -0,0 +1,103 @@ +from unittest.mock import MagicMock, patch +import pytest +import RNS +from meshchatx.src.backend.auto_propagation_manager import AutoPropagationManager + + +@pytest.mark.asyncio +async def test_auto_propagation_logic(): + # Mock dependencies + app = MagicMock() + context = MagicMock() + config = MagicMock() + database = MagicMock() + + context.config = config + context.database = database + context.identity_hash = "test_identity" + context.running = True + + manager = AutoPropagationManager(app, context) + + # 1. Test disabled state + config.lxmf_preferred_propagation_node_auto_select.get.return_value = False + with patch.object(manager, "check_and_update_propagation_node") as mock_check: + # Run one iteration manually + if config.lxmf_preferred_propagation_node_auto_select.get(): + await manager.check_and_update_propagation_node() + mock_check.assert_not_called() + + # 2. Test selection logic + config.lxmf_preferred_propagation_node_auto_select.get.return_value = True + config.lxmf_preferred_propagation_node_destination_hash.get.return_value = None + + # Mock announces + announce1 = { + "destination_hash": "aaaa1111", + "app_data": b"\x94\x00\x00\x01\x00", # msgpack for [0, 0, 1, 0] -> enabled=True + } + announce2 = {"destination_hash": "bbbb2222", "app_data": b"\x94\x00\x00\x01\x00"} + database.announces.get_announces.return_value = [announce1, announce2] + + # Mock RNS Transport + with ( + patch.object(RNS.Transport, "has_path", return_value=True), + patch.object(RNS.Transport, "hops_to") as mock_hops, + patch.object(manager, "probe_node", return_value=True), + ): + # announce1 is closer (1 hop) + # announce2 is further (3 hops) + mock_hops.side_effect = lambda dh: 1 if dh == bytes.fromhex("aaaa1111") else 3 + + await manager.check_and_update_propagation_node() + + # Should have selected aaaa1111 + app.set_active_propagation_node.assert_called_with("aaaa1111", context=context) + config.lxmf_preferred_propagation_node_destination_hash.set.assert_called_with( + "aaaa1111" + ) + + # 3. Test switching to better node + config.lxmf_preferred_propagation_node_destination_hash.get.return_value = ( + "bbbb2222" + ) + app.set_active_propagation_node.reset_mock() + + with ( + patch.object(RNS.Transport, "has_path", return_value=True), + patch.object(RNS.Transport, "hops_to") as mock_hops, + patch.object(manager, "probe_node", return_value=True), + ): + mock_hops.side_effect = lambda dh: 1 if dh == bytes.fromhex("aaaa1111") else 3 + + await manager.check_and_update_propagation_node() + + # Should have switched to aaaa1111 because it's closer + app.set_active_propagation_node.assert_called_with("aaaa1111", context=context) + + # 4. Test failover when probe fails + config.lxmf_preferred_propagation_node_destination_hash.get.return_value = ( + "cccc3333" + ) + announce3 = {"destination_hash": "cccc3333", "app_data": b"\x94\x00\x00\x01\x00"} + database.announces.get_announces.return_value = [announce1, announce3] + app.set_active_propagation_node.reset_mock() + + with ( + patch.object(RNS.Transport, "has_path", return_value=True), + patch.object(RNS.Transport, "hops_to") as mock_hops, + patch.object(manager, "probe_node") as mock_probe, + ): + # announce1 is 1 hop, but probe fails + # announce3 is 2 hops, probe succeeds + mock_hops.side_effect = lambda dh: 1 if dh == bytes.fromhex("aaaa1111") else 2 + mock_probe.side_effect = ( + lambda dh: False if dh == bytes.fromhex("aaaa1111") else True + ) + + await manager.check_and_update_propagation_node() + + # Should NOT switch to aaaa1111 because probe failed + # Should STAY on cccc3333 or switch to it if it was different + # Since it's already on cccc3333 and it's the best reachable, no switch + app.set_active_propagation_node.assert_not_called() diff --git a/tests/backend/test_auto_propagation_api.py b/tests/backend/test_auto_propagation_api.py new file mode 100644 index 0000000..f89d7be --- /dev/null +++ b/tests/backend/test_auto_propagation_api.py @@ -0,0 +1,101 @@ +import asyncio +import json +import shutil +import tempfile +from unittest.mock import MagicMock, patch +import pytest +import RNS +from meshchatx.meshchat import ReticulumMeshChat + + +@pytest.fixture +def temp_dir(): + dir_path = tempfile.mkdtemp() + yield dir_path + shutil.rmtree(dir_path) + + +@pytest.fixture +def mock_rns_minimal(): + with ( + patch("RNS.Reticulum") as mock_rns, + patch("RNS.Transport"), + patch("LXMF.LXMRouter") as mock_lxmf_router, + patch("meshchatx.meshchat.get_file_path", return_value="/tmp/mock_path"), + patch("meshchatx.meshchat.generate_ssl_certificate"), + ): + mock_rns_instance = mock_rns.return_value + mock_rns_instance.configpath = "/tmp/mock_config" + mock_rns_instance.is_connected_to_shared_instance = False + mock_rns_instance.transport_enabled.return_value = True + + # Mock LXMF router and its return values to be JSON serializable + mock_lxmf_router_instance = mock_lxmf_router.return_value + mock_dest = MagicMock() + mock_dest.hexhash = "test_lxmf_hexhash" + mock_lxmf_router_instance.register_delivery_identity.return_value = mock_dest + mock_lxmf_router_instance.propagation_destination = mock_dest + + mock_id = MagicMock(spec=RNS.Identity) + mock_id.hash = b"test_hash_32_bytes_long_01234567" + mock_id.hexhash = mock_id.hash.hex() + mock_id.get_private_key.return_value = b"test_private_key" + yield mock_id + + +@pytest.mark.asyncio +async def test_auto_propagation_api(mock_rns_minimal, temp_dir): + app_instance = ReticulumMeshChat( + identity=mock_rns_minimal, + storage_dir=temp_dir, + reticulum_config_dir=temp_dir, + ) + + # 1. Test GET /api/v1/config includes auto_select + get_handler = None + for route in app_instance.get_routes(): + if route.path == "/api/v1/config" and route.method == "GET": + get_handler = route.handler + break + + assert get_handler is not None + request = MagicMock() + response = await get_handler(request) + data = json.loads(response.body) + assert "lxmf_preferred_propagation_node_auto_select" in data["config"] + assert data["config"]["lxmf_preferred_propagation_node_auto_select"] is False + + # 2. Test PATCH /api/v1/config updates auto_select + patch_handler = None + for route in app_instance.get_routes(): + if route.path == "/api/v1/config" and route.method == "PATCH": + patch_handler = route.handler + break + + assert patch_handler is not None + + # Update to True + mock_request = MagicMock() + mock_request.json = MagicMock(return_value=asyncio.Future()) + mock_request.json.return_value.set_result( + {"lxmf_preferred_propagation_node_auto_select": True} + ) + + response = await patch_handler(mock_request) + data = json.loads(response.body) + assert data["config"]["lxmf_preferred_propagation_node_auto_select"] is True + assert app_instance.config.lxmf_preferred_propagation_node_auto_select.get() is True + + # Update to False + mock_request = MagicMock() + mock_request.json = MagicMock(return_value=asyncio.Future()) + mock_request.json.return_value.set_result( + {"lxmf_preferred_propagation_node_auto_select": False} + ) + + response = await patch_handler(mock_request) + data = json.loads(response.body) + assert data["config"]["lxmf_preferred_propagation_node_auto_select"] is False + assert ( + app_instance.config.lxmf_preferred_propagation_node_auto_select.get() is False + ) diff --git a/tests/backend/test_config_manager.py b/tests/backend/test_config_manager.py index 8d94db1..df9c147 100644 --- a/tests/backend/test_config_manager.py +++ b/tests/backend/test_config_manager.py @@ -83,3 +83,10 @@ def test_telephony_config(db): assert config.call_recording_enabled.get() is False config.call_recording_enabled.set(True) assert config.call_recording_enabled.get() is True + + +def test_auto_propagation_config(db): + config = ConfigManager(db) + assert config.lxmf_preferred_propagation_node_auto_select.get() is False + config.lxmf_preferred_propagation_node_auto_select.set(True) + assert config.lxmf_preferred_propagation_node_auto_select.get() is True From b009757253f2488a2eb4b84ddfe0079dbc616080 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sat, 10 Jan 2026 17:51:30 -0600 Subject: [PATCH 228/234] fix windows builds --- Taskfile.yml | 16 +++++++++++----- cx_setup.py | 8 ++++++-- electron/main.js | 2 +- forge.config.js | 5 ++++- package.json | 14 +++++++------- scripts/build-backend.js | 29 +++++++++++++++++++++++------ 6 files changed, 52 insertions(+), 22 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index c8dbdd7..6f6ccee 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -210,16 +210,18 @@ tasks: build-appimage: desc: Build Linux AppImage - deps: [build] + deps: [build-frontend] cmds: - "{{.NPM}} run electron-postinstall" + - "PLATFORM=linux {{.NPM}} run build-backend" - "{{.NPM}} run dist -- --linux AppImage" build-exe: desc: Build Windows portable executable - deps: [build] + deps: [build-frontend] cmds: - "{{.NPM}} run electron-postinstall" + - "PLATFORM=win32 {{.NPM}} run build-backend" - "{{.NPM}} run dist -- --win portable" build-electron-linux: @@ -250,6 +252,7 @@ tasks: desc: Build Electron ZIP archive using Electron Forge deps: [build-frontend] cmds: + - "PLATFORM=linux {{.NPM}} run build-backend" - "{{.NPM}} run dist:zip" build-electron-all: @@ -257,7 +260,8 @@ tasks: deps: [build-frontend] cmds: - "{{.NPM}} run electron-postinstall" - - "{{.NPM}} run build-backend" + - "PLATFORM=linux {{.NPM}} run build-backend" + - "PLATFORM=win32 {{.NPM}} run build-backend" - "{{.NPM}} run dist -- --linux AppImage deb --win portable nsis" dist: @@ -272,17 +276,19 @@ tasks: build-appimage-legacy: desc: Build Linux AppImage with legacy Electron version - deps: [build, electron-legacy] + deps: [build-frontend, electron-legacy] cmds: - "{{.NPM}} run electron-postinstall" + - "PLATFORM=linux {{.NPM}} run build-backend" - "{{.NPM}} run dist -- --linux AppImage -c.extraMetadata.main=electron/main-legacy.js" - "./scripts/rename_legacy_artifacts.sh" build-exe-legacy: desc: Build Windows portable executable with legacy Electron version - deps: [build, electron-legacy] + deps: [build-frontend, electron-legacy] cmds: - "{{.NPM}} run electron-postinstall" + - "PLATFORM=win32 {{.NPM}} run build-backend" - "{{.NPM}} run dist -- --win portable -c.extraMetadata.main=electron/main-legacy.js" - "./scripts/rename_legacy_artifacts.sh" diff --git a/cx_setup.py b/cx_setup.py index 00fa221..e0160c7 100644 --- a/cx_setup.py +++ b/cx_setup.py @@ -1,3 +1,4 @@ +import os import sys from pathlib import Path @@ -8,6 +9,9 @@ from meshchatx.src.version import __version__ ROOT = Path(__file__).resolve().parent PUBLIC_DIR = ROOT / "meshchatx" / "public" +target_name = os.environ.get("CX_FREEZE_TARGET_NAME", "ReticulumMeshChatX") +build_exe_dir = os.environ.get("CX_FREEZE_BUILD_EXE", "build/exe") + include_files = [] if PUBLIC_DIR.exists() and PUBLIC_DIR.is_dir(): @@ -42,7 +46,7 @@ setup( Executable( script="meshchatx/meshchat.py", base=None, - target_name="ReticulumMeshChatX", + target_name=target_name, shortcut_name="ReticulumMeshChatX", shortcut_dir="ProgramMenuFolder", icon="logo/icon.ico", @@ -56,7 +60,7 @@ setup( "PIL", ], "optimize": 1, - "build_exe": "build/exe", + "build_exe": build_exe_dir, "replace_paths": [ ("*", ""), ], diff --git a/electron/main.js b/electron/main.js index 59b8cc3..aec565e 100644 --- a/electron/main.js +++ b/electron/main.js @@ -98,7 +98,7 @@ app.on("open-url", (event, url) => { }); function verifyBackendIntegrity(exeDir) { - const manifestPath = path.join(__dirname, "backend-manifest.json"); + const manifestPath = path.join(exeDir, "backend-manifest.json"); if (!fs.existsSync(manifestPath)) { log("Backend integrity manifest missing, skipping check."); return { ok: true, issues: ["Manifest missing"] }; diff --git a/forge.config.js b/forge.config.js index 8f98e1b..2969b81 100644 --- a/forge.config.js +++ b/forge.config.js @@ -1,10 +1,13 @@ const { FusesPlugin } = require("@electron-forge/plugin-fuses"); const { FuseV1Options, FuseVersion } = require("@electron/fuses"); +const platform = process.env.PLATFORM || process.platform; +const extraResourceDir = platform === "win32" || platform === "win" ? "build/exe/win32" : "build/exe/linux"; + module.exports = { packagerConfig: { asar: true, - extraResource: ["build/exe"], + extraResource: [extraResourceDir], executableName: "reticulum-meshchatx", name: "Reticulum MeshChatX", appBundleId: "com.sudoivan.reticulummeshchatx", diff --git a/package.json b/package.json index 9379e5c..e3492e1 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,10 @@ "electron-postinstall": "electron-builder install-app-deps", "electron": "pnpm run electron-postinstall && pnpm run build && electron .", "dist": "pnpm run electron-postinstall && pnpm run build && electron-builder --publish=never", - "dist:linux": "pnpm run electron-postinstall && pnpm run build && electron-builder --linux AppImage deb --publish=never", - "dist:rpm": "pnpm run electron-postinstall && pnpm run build && electron-builder --linux rpm --publish=never", - "dist:flatpak": "pnpm run electron-postinstall && pnpm run build && electron-builder --linux flatpak --publish=never", - "dist:windows": "pnpm run electron-postinstall && pnpm run build && electron-builder --win portable nsis --publish=never", + "dist:linux": "pnpm run electron-postinstall && PLATFORM=linux pnpm run build && electron-builder --linux AppImage deb --publish=never", + "dist:rpm": "pnpm run electron-postinstall && PLATFORM=linux pnpm run build && electron-builder --linux rpm --publish=never", + "dist:flatpak": "pnpm run electron-postinstall && PLATFORM=linux pnpm run build && electron-builder --linux flatpak --publish=never", + "dist:windows": "pnpm run electron-postinstall && PLATFORM=win32 pnpm run build && electron-builder --win portable nsis --publish=never", "dist:zip": "pnpm run electron-postinstall && pnpm run build && electron-forge make --targets @electron-forge/maker-zip", "dist-prebuilt": "pnpm run electron-postinstall && pnpm run build-backend && electron-builder --publish=never", "dist:mac-arm64": "pnpm run electron-postinstall && pnpm run build && electron-builder --mac --arm64 --publish=never", @@ -114,7 +114,7 @@ }, "extraResources": [ { - "from": "build/exe", + "from": "build/exe/linux", "to": "backend", "filter": [ "**/*" @@ -134,7 +134,7 @@ ], "extraResources": [ { - "from": "build/exe", + "from": "build/exe/win32", "to": "backend", "filter": [ "**/*" @@ -152,7 +152,7 @@ "category": "Network", "extraResources": [ { - "from": "build/exe", + "from": "build/exe/linux", "to": "backend", "filter": [ "**/*" diff --git a/scripts/build-backend.js b/scripts/build-backend.js index a7b3e62..982310d 100755 --- a/scripts/build-backend.js +++ b/scripts/build-backend.js @@ -32,6 +32,7 @@ function generateManifest(buildDir, manifestPath) { for (const file of files) { const relativePath = path.relative(buildDir, file); + if (relativePath === "backend-manifest.json") continue; const fileBuffer = fs.readFileSync(file); const hash = crypto.createHash("sha256").update(fileBuffer).digest("hex"); manifest.files[relativePath] = hash; @@ -42,8 +43,26 @@ function generateManifest(buildDir, manifestPath) { } try { - console.log("Building backend with cx_Freeze..."); - const result = spawnSync("poetry", ["run", "python", "cx_setup.py", "build"], { stdio: "inherit", shell: false }); + const platform = process.env.PLATFORM || process.platform; + const isWin = platform === "win32" || platform === "win"; + const targetName = isWin ? "ReticulumMeshChatX.exe" : "ReticulumMeshChatX"; + const buildDirRelative = isWin ? "build/exe/win32" : "build/exe/linux"; + const buildDir = path.join(__dirname, "..", buildDirRelative); + + console.log( + `Building backend for ${platform} (target: ${targetName}, output: ${buildDirRelative}) with cx_Freeze...` + ); + + const env = { + ...process.env, + CX_FREEZE_TARGET_NAME: targetName, + CX_FREEZE_BUILD_EXE: buildDirRelative, + }; + const result = spawnSync("poetry", ["run", "python", "cx_setup.py", "build"], { + stdio: "inherit", + shell: false, + env: env, + }); if (result.error) { throw result.error; } @@ -51,13 +70,11 @@ try { process.exit(result.status || 1); } - const buildDir = path.join(__dirname, "..", "build", "exe"); - const manifestPath = path.join(__dirname, "..", "electron", "backend-manifest.json"); - if (fs.existsSync(buildDir)) { + const manifestPath = path.join(buildDir, "backend-manifest.json"); generateManifest(buildDir, manifestPath); } else { - console.error("Build directory not found, manifest generation skipped."); + console.error(`Build directory not found (${buildDir}), manifest generation skipped.`); } } catch (error) { console.error("Build failed:", error.message); From 44a560c39f0f824f8f07b1a5768b6e5246ee745c Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sat, 10 Jan 2026 17:51:51 -0600 Subject: [PATCH 229/234] Update README --- README.md | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 8b64c27..2275320 100644 --- a/README.md +++ b/README.md @@ -3,21 +3,18 @@ > [!IMPORTANT] > v4 coming soon with release builds for Linux and Windows (Appimage and EXE portable/installer). As well as updated container images and wheel packages. You can test v4 using container by replacing normal image with `git.quad4.io/rns-things/meshchatx-dev:dev` -Contact me for issues, ideas and how to get an account for this gitea instance: +Contact me for any issues or ideas: ``` LXMF: 7cc8d66b4f6a0e0e49d34af7f6077b5a -XMPP: ivan@chat.quad4.io -Email: ivan@quad4.io ``` -For issues contact me over LXMF: `73 [![CI](https://git.quad4.io/RNS-Things/MeshChatX/actions/workflows/ci.yml/badge.svg?branch=master)](https://git.quad4.io/RNS-Things/MeshChatX/actions/workflows/ci.yml) [![Tests](https://git.quad4.io/RNS-Things/MeshChatX/actions/workflows/tests.yml/badge.svg?branch=master)](https://git.quad4.io/RNS-Things/MeshChatX/actions/workflows/tests.yml) [![Build](https://git.quad4.io/RNS-Things/MeshChatX/actions/workflows/build.yml/badge.svg?branch=master)](https://git.quad4.io/RNS-Things/MeshChatX/actions/workflows/build.yml) [![Docker](https://git.quad4.io/RNS-Things/MeshChatX/actions/workflows/docker.yml/badge.svg?branch=master)](https://git.quad4.io/RNS-Things/MeshChatX/actions/workflows/docker.yml) -A [Reticulum MeshChat](https://git.quad4.io/Reticulum/Reticulum) fork from the future. +A [Reticulum MeshChat](https://github.com/liamcottle/reticulum-meshchat) fork from the future. @@ -63,15 +60,16 @@ Check [releases](https://git.quad4.io/RNS-Things/MeshChatX/releases) for pre-bui ## Major Features - **Full LXST Support**: Custom voicemail, phonebook, contact sharing, and ringtone support. +- **Interface Discovery and auto-connecting** - Discover interfaces, auto-connect or connect to trusted ones, map them all! - **Multi-Identity**: Switch between multiple Reticulum identities seamlessly. - **Modern UI/UX**: A completely redesigned, intuitive interface. - **Integrated Maps**: OpenLayers with MBTiles support for offline maps. - **Security**: Read more about it in the [Security](#security) section. - **Offline Docs**: Access Reticulum documentation without an internet connection. -- **Expanded Tools**: Includes RNStatus, RNProbe, RNCP, Micron Editor, Paper Message Generator and a Translator. +- **Expanded Tools**: Includes dozens of more tools. - **Page Archiving**: Built-in crawler and browser for archived pages offline. -- **Banishment**: Banish LXMF users, Telephony, and NomadNet Nodes. (and unbanish them) -- **i18n**: Support for English, German, and Russian. +- **Banishment**: Banish LXMF users, Telephony, and NomadNet Nodes. +- **i18n**: Support for English, German, Italian, and Russian. ## Screenshots @@ -203,7 +201,6 @@ We use [Task](https://taskfile.dev/) for automation. | `task install` | Install all dependencies | | `task run` | Run the application | | `task dev` | Run the application in development mode | -| `task check` | Run format, lint and test | | `task lint` | Run all linters (Python & Frontend) | | `task lint-python` | Lint Python code only | | `task lint-frontend` | Lint frontend code only | @@ -227,21 +224,19 @@ We use [Task](https://taskfile.dev/) for automation. | `task android-prepare` | Prepare Android build | | `task android-build` | Build Android APK | | `task build-flatpak` | Build Flatpak package | -| `task forge-start` | Run the application with Electron Forge | -| `task forge-make` | Generate distributables with Electron Forge | | `task clean` | Clean build artifacts and dependencies | ## Security -- [ASAR Integrity](https://www.electronjs.org/docs/latest/tutorial/asar-integrity) (Electron 39) +- [ASAR Integrity](https://www.electronjs.org/docs/latest/tutorial/asar-integrity) (Stable as of Electron 39) - Built-in automatic integrity checks on all files (frontend and backend) - HTTPS by default (automated locally generated certs) -- 3-layer redundant CORS protection (loading.html, python backend server, electron main.js) +- Redundant CORS protection (loading.html, python backend server, electron main.js) - Updated dependencies and daily scanning (OSV) - Container image scanning (Trivy) -- SBOM for dependency observability and tracking (soon) +- SBOM for dependency observability and tracking - Extensive testing and fuzzing. -- Rootless docker images (soon) +- Rootless docker images - Pinned actions and container images (supply chain security and deterministic builds) ## Credits From 68202620cfc28d098044494a8a070778686e3899 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sat, 10 Jan 2026 17:51:56 -0600 Subject: [PATCH 230/234] Update SECURITY --- SECURITY.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 0221831..4a996ec 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,9 +4,7 @@ If you discover a security vulnerability or have concerns about the security of Reticulum MeshChatX, please contact the lead developer using the following methods in order of preference: -1. **LXMF**: `7cc8d66b4f6a0e0e49d34af7f6077b5a` (Ideally) -2. **XMPP**: `ivan@chat.quad4.io` -3. **Email**: `ivan@quad4.io` +1. **LXMF**: `7cc8d66b4f6a0e0e49d34af7f6077b5a` ## Security Overview @@ -17,7 +15,7 @@ Reticulum MeshChatX is designed with a high degree of security in mind, leveragi - **ASAR Integrity Validation**: Utilizes Electron 39 features to protect the application against tampering. - **Backend Binary Verification**: Generates a SHA-256 manifest of the unpacked Python backend during build and verifies it on every startup. - **Data-at-Rest Integrity Monitoring**: Snapshots the state of identities and database files on clean shutdown and warns if they were modified while the app was closed. -- **3-Layer CSP Hardening**: Multi-layered Content Security Policy protection across the entire application stack: +- **Redundant CSP Hardening**: Multi-layered Content Security Policy protection across the entire application stack: 1. **Backend Server CSP**: Applied via security middleware to all HTTP responses. 2. **Electron Session CSP**: Shell-level fallback CSP applied via `webRequest.onHeadersReceived`. 3. **Loading Screen CSP**: Bootloader CSP defined in HTML meta tags. From c209b84a96ce158b21da56b18b719f439795a18b Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sat, 10 Jan 2026 17:53:17 -0600 Subject: [PATCH 231/234] rnode_flasher: add WiFi connection method and OTA firmware upload functionality (testing required) --- .../components/tools/RNodeFlasherPage.vue | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/meshchatx/src/frontend/components/tools/RNodeFlasherPage.vue b/meshchatx/src/frontend/components/tools/RNodeFlasherPage.vue index b003375..61bcb11 100644 --- a/meshchatx/src/frontend/components/tools/RNodeFlasherPage.vue +++ b/meshchatx/src/frontend/components/tools/RNodeFlasherPage.vue @@ -56,6 +56,50 @@
    +
    + +
    + + +
    +
    + +
    + + +
    +