diff --git a/.htaccess b/.htaccess index 724604c..da3148f 100644 --- a/.htaccess +++ b/.htaccess @@ -197,59 +197,13 @@ # (see CLOUDFLARE_SETUP.md documentation) # ============================================ -# SPA FALLBACK +# NOT-FOUND HANDLING # ============================================ -# If file not found, redirect to index.html (for SPA routing) - - # Locale shells first: a deep link under /de/ must fall back to the German page, - # not the English one. Rewritten by scripts/build-i18n.js from locales/site.json. - # BEGIN generated locale shells - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule ^de(/.*)?$ /de/index.html [L] - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule ^fr(/.*)?$ /fr/index.html [L] - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule ^es(/.*)?$ /es/index.html [L] - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule ^uk(/.*)?$ /uk/index.html [L] - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule ^ru(/.*)?$ /ru/index.html [L] - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule ^zh(/.*)?$ /zh/index.html [L] - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule ^ko(/.*)?$ /ko/index.html [L] - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule ^hi(/.*)?$ /hi/index.html [L] - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule ^ar(/.*)?$ /ar/index.html [L] - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule ^he(/.*)?$ /he/index.html [L] - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule ^fa(/.*)?$ /fa/index.html [L] - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule ^ur(/.*)?$ /ur/index.html [L] - # END generated locale shells - - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteCond %{REQUEST_URI} !^/meta\.json$ - RewriteCond %{REQUEST_URI} !^/sw\.js$ - RewriteCond %{REQUEST_URI} !^/manifest\.json$ - RewriteRule ^(.*)$ /index.html [L] - +# There is no client-side routing, so an address that is not a file and not a +# directory is a mistake rather than a route. Rewriting those to index.html answered +# every typo with 200 OK and turned an infinite URL space into indexable pages. +ErrorDocument 404 /404.html # ============================================ # LOGGING (optional) diff --git a/404.html b/404.html new file mode 100644 index 0000000..e0c46ea --- /dev/null +++ b/404.html @@ -0,0 +1,65 @@ + + + + + + + + Page not found - SecureBit.chat + + + +
+

404

+

There is no page at this address.

+

The link may be mistyped, or it pointed at something that has since moved. Nothing was lost on our side — the app keeps no server-side state to lose.

+ Open SecureBit.chat +
+ + diff --git a/CHANGELOG.md b/CHANGELOG.md index 899a737..e76e1ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,35 @@ # Changelog +## v6.7.3 — Faster loading, and pages search engines can actually read + +Loading got a lot lighter. The bundles used to carry all thirteen translations at once, +and a page fetched them a third time as raw source; now each page loads only its own +language. On top of that the JavaScript is minified, the eight stylesheets are served as +one file, the QR scanner is fetched only once the app is up rather than on every visit, +and the fonts and icons ship at the size they are actually used at — Inter was shipping +the same file five times over, and Font Awesome was sending 2468 icons for the 82 this +app draws. + +The page went from 1.85 MB across 43 requests to under 700 KB across 33. On a mobile +connection it now starts drawing in 1.6 s instead of 6.3 s and is usable in 4.5 s +instead of 11 s. + +Pages also arrive with their text already in the HTML. Everything used to be drawn by +JavaScript into an empty div, so a search engine saw correct metadata wrapped around +nothing — which is why twelve of the thirteen language pages had never been shown to +anyone. Each page now carries its own headline, features and roadmap in the markup, +visible to crawlers and to anyone without JavaScript, and replaced by the app the moment +it loads. The documentation is published as real pages under `/docs/` with a new FAQ, +and an address that does not exist returns a proper 404 instead of the app. + +One fix worth calling out: the localized pages were being served with a year-long cache +header meant for static assets. Anyone who opened `/de/` or `/ru/` was pinned to that +build and could not receive an update. The header is corrected, and the service worker +now refreshes what it cached, so affected browsers recover on their next visit. + +Three unused components were removed along the way, and the placeholder testimonials +that were never wired into the site are gone from the repository. + ## v6.7.2 — Desktop 1.0.1 Download links point at desktop 1.0.1, which is the first build that works on diff --git a/README.md b/README.md index 1f3d262..cdbdcab 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ No accounts. No servers storing your messages. No installation required. [![License: MIT](https://img.shields.io/badge/License-MIT-f0892a.svg)](LICENSE) -[![Version](https://img.shields.io/badge/version-6.7.2-3ecf8e.svg)](CHANGELOG.md) +[![Version](https://img.shields.io/badge/version-6.7.3-3ecf8e.svg)](CHANGELOG.md) [![Get it from the Snap Store](https://snapcraft.io/securebit-chat/badge.svg)](https://snapcraft.io/securebit-chat) [![PWA](https://img.shields.io/badge/PWA-installable-3ecf8e.svg)](#install-as-an-app) [![Encryption](https://img.shields.io/badge/crypto-ECDH%20P--384%20%C2%B7%20AES--256--GCM-blue.svg)](#security-model) diff --git a/ar/index.html b/ar/index.html index 30500b5..5471e04 100644 --- a/ar/index.html +++ b/ar/index.html @@ -30,7 +30,7 @@ - + @@ -96,7 +96,7 @@ - + @@ -105,7 +105,7 @@ - + @@ -121,8 +121,7 @@ SecureBit.chat - مراسلة خاصة ومشفّرة - - + @@ -179,13 +178,27 @@ { "@context": "https://schema.org", "@graph": [ + { + "@type": "Organization", + "@id": "https://securebit.chat/#organization", + "name": "SecureBit.chat", + "url": "https://securebit.chat/", + "logo": "https://securebit.chat/logo/icon-512x512.png", + "sameAs": [ + "https://github.com/SecureBitChat/securebit-chat", + "https://snapcraft.io/securebit-chat" + ] + }, { "@type": "WebSite", "@id": "https://securebit.chat/#website", "name": "SecureBit.chat", "url": "https://securebit.chat/", "description": "دردشة ندٌّ لندّ مشفّرة من الطرف إلى الطرف، تعمل بالكامل داخل متصفحك.", - "inLanguage": "ar" + "inLanguage": "ar", + "publisher": { + "@id": "https://securebit.chat/#organization" + } }, { "@type": "WebApplication", @@ -222,55 +235,235 @@ - + - - - - - - - - - - - - - - - + + + + + + - + - + + + - - - - + + + -
- - +
+ + + + +
+
+
+

SecureBit.chat

+

خطٌّ مباشر
لا يقرأه إلّا أنتما.

+

تُولَّد المفاتيح على جهازك وتُتبادَل ندّاً لندّ. بلا حسابات وبلا خوادم تحفظ رسائلك.

+
+
+

ما الذي يميّزنا

+

لماذا SecureBit فريد

+
    +
  • +

    نواة تشفير متعدّدة الطبقات

    +

    تبادل مفاتيح ECDH P-384، وحمولات AES-256-GCM، وتواقيع ECDSA، وتحقّق ASN.1 كامل - مجموعة في خطّ واحد مُحصَّن.

    +
    • ECDH P-384
    • AES-256-GCM
    • ECDSA
    • ASN.1
    +
  • +
  • +

    ندٌّ لندّ خالص عبر WebRTC

    +

    تنتقل الرسائل مباشرةً بين الأجهزة عبر WebRTC. لا مُرحِّل يحتفظ ببياناتك - الخادم يساعد الطرفين على إيجاد بعضهما فقط.

    +
    • DTLS 1.3
    • بلا مُرحِّل
    +
  • +
  • +

    سرّية تامّة إلى الأمام

    +

    تتبدّل مفاتيح الجلسة باستمرار وتُتلَف بعد الاستعمال، فلا يفتح مفتاح واحد مسروق أيّ محادثة ماضية.

    +
    • مفاتيح عابرة
    • تبديل تلقائي
    +
  • +
  • +

    تمويه حركة البيانات

    +

    تُحشى أحجام الحزم وتوقيتاتها وتُعشوَأ، فتختفي أنماط البيانات الوصفية عن أعين من يراقب الخطّ.

    +
    • حشو الحزم
    • تشويش التوقيت
    +
  • +
  • +

    صفر جمعٍ للبيانات

    +

    لا حسابات ولا سجلّات ولا تخزين للرسائل. لا شيء على خادم يمكن أن يتسرّب أو يُطلَب قضائياً أو يُباع.

    +
    • بلا حسابات
    • بلا سجلّات
    +
  • +
+
+
+

خارطة طريق التطوير

+

تطوّر SecureBit

+

من أوّل نموذج أوّلي إلى شبكة لامركزية مقاومة للحوسبة الكمّية - مع تحقّق ASN.1 كامل في كلّ طبقة.

+
    +
  1. +

    بداية التطوير

    + أوائل 2025 +

    الفكرة والنموذج الأوّلي وتهيئة البنية التحتية

    +
  2. +
  3. +

    إصدار ألفا

    + ربيع 2025 +

    أوّل ألفا علنية: دردشة أساسية وتبادل مفاتيح

    +
  4. +
  5. +

    تحصين أمني

    + صيف 2025 +

    تعزيز الأمان وإطلاق فرع مستقرّ

    +
  6. +
  7. +

    التوسّع والاستقرار

    + خريف 2025 +

    توسيع الشبكة وتحسين الاستقرار

    +
  8. +
  9. +

    إصدار الخصوصية أوّلاً

    + شتاء 2025 +

    التركيز على الخصوصية: تقليل البيانات الوصفية

    +
  10. +
  11. +

    إصدار الأمان المعزَّز

    + أواخر 2025 +

    تعمية بمستوى عسكري من 18 طبقة مع تحقّق ASN.1 كامل

    +
  12. +
  13. +

    إصدار سطح المكتب

    + أوائل 2026 +

    تطبيقات أصلية لويندوز وماك ولينكس

    +
  14. +
  15. +

    الصوت والمكالمات الآمنة

    + أوائل 2026 +

    رسائل صوتية ومكالمات صوتية ومرئية مشفّرة

    +
  16. +
  17. +

    المحادثات الجماعية

    + الآن +

    دردشات جماعية مع الحفاظ على الخصوصية

    +
  18. +
  19. +

    إصدار الهواتف

    + الربع الثاني 2027 +

    تطبيقات أصلية لـ iOS وأندرويد

    +
  20. +
  21. +

    إصدار مقاوم للكمّ

    + الربع الرابع 2027 +

    حماية من الحواسيب الكمّية

    +
  22. +
  23. +

    شبكة لامركزية

    + 2028 +

    شبكة لامركزية بالكامل

    +
  24. +
  25. +

    مساعد خصوصية بالذكاء الاصطناعي

    + 2028 وما بعدها +

    ذكاء اصطناعي للخصوصية والأمان

    +
  26. +
+
+
+

Documentation

+ +
+
+

انضمّ إلى مستقبل الخصوصية

+

ينمو SecureBit بفضل مجتمعه. أفكاركم وملاحظاتكم هي ما يصوغ مستقبل التواصل الآمن - مبنيّ في العلن، مع تحقّق ASN.1 كامل من طرف إلى طرف.

+

مستودع GitHub

+
+
+
+
+ + - - - - - + + + + \ No newline at end of file diff --git a/assets/app.css b/assets/app.css new file mode 100644 index 0000000..a25a7a2 --- /dev/null +++ b/assets/app.css @@ -0,0 +1 @@ +*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--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;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--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: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--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;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--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: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.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}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#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]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media(min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media(min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media(min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media(min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media(min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.bottom-4{bottom:1rem}.end-0{inset-inline-end:0}.end-4{inset-inline-end:1rem}.left-1\/2{left:50%}.left-4{left:1rem}.right-4{right:1rem}.top-0{top:0}.top-1\/2{top:50%}.top-4{top:1rem}.isolate{isolation:isolate}.z-10{z-index:10}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-top:.25rem}.mb-1,.my-1{margin-bottom:.25rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.me-1{margin-inline-end:.25rem}.me-2{margin-inline-end:.5rem}.me-3{margin-inline-end:.75rem}.me-4{margin-inline-end:1rem}.ms-2{margin-inline-start:.5rem}.ms-6{margin-inline-start:1.5rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-20{margin-top:5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-10{height:2.5rem}.h-12{height:3rem}.h-28{height:7rem}.h-8{height:2rem}.h-80{height:20rem}.h-9{height:2.25rem}.max-h-\[80vh\]{max-height:80vh}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-12{width:3rem}.w-28{width:7rem}.w-4{width:1rem}.w-8{width:2rem}.w-full{width:100%}.min-w-\[180px\]{min-width:180px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-7xl{max-width:80rem}.max-w-\[78vw\]{max-width:78vw}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-x-full{--tw-translate-x:100%}.transform,.translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-6{gap:1.5rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.self-center{align-self:center}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-blue-500\/20{border-color:#3b82f633}.border-gray-500\/20{border-color:#6b728033}.border-gray-600\/30{border-color:#4b55634d}.border-green-500\/20{border-color:#22c55e33}.border-orange-500\/20{border-color:#f9731633}.border-purple-500\/20{border-color:#a855f733}.border-purple-500\/30{border-color:#a855f74d}.border-red-500\/20{border-color:#ef444433}.border-yellow-500\/20{border-color:#eab30833}.bg-black\/20{background-color:#0003}.bg-black\/30{background-color:#0000004d}.bg-black\/50{background-color:#00000080}.bg-black\/80{background-color:#000c}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-blue-500\/10{background-color:#3b82f61a}.bg-blue-500\/90{background-color:#3b82f6e6}.bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity,1))}.bg-gray-500\/10{background-color:#6b72801a}.bg-gray-500\/20{background-color:#6b728033}.bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.bg-gray-700\/50{background-color:#37415180}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.bg-gray-800\/50{background-color:#1f293780}.bg-gray-900\/30{background-color:#1118274d}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.bg-green-500\/10{background-color:#22c55e1a}.bg-green-500\/90{background-color:#22c55ee6}.bg-orange-500\/10{background-color:#f973161a}.bg-purple-500\/10{background-color:#a855f71a}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-red-500\/10{background-color:#ef44441a}.bg-red-500\/20{background-color:#ef444433}.bg-red-900\/50{background-color:#7f1d1d80}.bg-white\/20{background-color:#fff3}.bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(234 179 8/var(--tw-bg-opacity,1))}.bg-yellow-500\/10{background-color:#eab3081a}.bg-yellow-500\/90{background-color:#eab308e6}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.text-center{text-align:center}.text-start{text-align:start}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-\[3rem\]{font-size:3rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.italic{font-style:italic}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-\[0\.3em\]{letter-spacing:.3em}.tracking-wide{letter-spacing:.025em}.text-amber-300{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}.text-blue-200{--tw-text-opacity:1;color:rgb(191 219 254/var(--tw-text-opacity,1))}.text-blue-300{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-gray-200{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity,1))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-green-400{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.text-orange-200{--tw-text-opacity:1;color:rgb(254 215 170/var(--tw-text-opacity,1))}.text-orange-300{--tw-text-opacity:1;color:rgb(253 186 116/var(--tw-text-opacity,1))}.text-orange-400{--tw-text-opacity:1;color:rgb(251 146 60/var(--tw-text-opacity,1))}.text-orange-500{--tw-text-opacity:1;color:rgb(249 115 22/var(--tw-text-opacity,1))}.text-purple-300{--tw-text-opacity:1;color:rgb(216 180 254/var(--tw-text-opacity,1))}.text-purple-400{--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-sky-300{--tw-text-opacity:1;color:rgb(125 211 252/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/10{color:#ffffff1a}.text-yellow-400{--tw-text-opacity:1;color:rgb(250 204 21/var(--tw-text-opacity,1))}.text-yellow-600{--tw-text-opacity:1;color:rgb(202 138 4/var(--tw-text-opacity,1))}.line-through{text-decoration-line:line-through}.placeholder-gray-500::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(107 114 128/var(--tw-placeholder-opacity,1))}.placeholder-gray-500::placeholder{--tw-placeholder-opacity:1;color:rgb(107 114 128/var(--tw-placeholder-opacity,1))}.opacity-0{opacity:0}.opacity-90{opacity:.9}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-2xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.ring{--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(3px + 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)}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px)}.backdrop-blur-md,.backdrop-blur-sm{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-150,.transition-transform{transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.\[checksum\:4\]{checksum:4}.\[data\:variable\]{data:variable}.\[name\:4\]{name:4}.\[size\:4\]{size:4}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.hover\:bg-emerald-600:hover{--tw-bg-opacity:1;background-color:rgb(5 150 105/var(--tw-bg-opacity,1))}.hover\:bg-gray-500:hover{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity,1))}.hover\:bg-gray-700\/40:hover{background-color:#37415166}.hover\:bg-gray-700\/50:hover{background-color:#37415180}.hover\:bg-red-500\/20:hover{background-color:#ef444433}.hover\:bg-red-500\/30:hover{background-color:#ef44444d}.hover\:bg-white\/30:hover{background-color:#ffffff4d}.hover\:text-gray-200:hover{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity,1))}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.hover\:text-green-300:hover{--tw-text-opacity:1;color:rgb(134 239 172/var(--tw-text-opacity,1))}.hover\:text-green-400:hover{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.hover\:text-red-300:hover{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.focus\:border-purple-400:focus{--tw-border-opacity:1;border-color:rgb(192 132 252/var(--tw-border-opacity,1))}.focus\:border-purple-500\/40:focus{border-color:#a855f766}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.active\:bg-gray-700\/60:active{background-color:#37415199}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-60:disabled{opacity:.6}.group:hover .group-hover\:scale-105{--tw-scale-x:1.05;--tw-scale-y:1.05;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:opacity-100{opacity:1}@media(min-width:640px){.sm\:block{display:block}.sm\:inline{display:inline}.sm\:flex{display:flex}.sm\:py-2\.5{padding-top:.625rem;padding-bottom:.625rem}}@media(min-width:768px){.md\:h-\[32rem\]{height:32rem}}.fa{font-family:var(--fa-style-family,"Font Awesome 6 Free");font-weight:var(--fa-style,900)}.fa,.fa-brands,.fa-regular,.fa-solid,.fab,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:var(--fa-display,inline-block);font-style:normal;font-variant:normal;line-height:1;text-rendering:auto}.fa-regular,.fa-solid,.far,.fas{font-family:"Font Awesome 6 Free"}.fa-brands,.fab{font-family:"Font Awesome 6 Brands"}.fa-solid,.fas{font-weight:900}.fa-regular,.far,.fa-brands,.fab{font-weight:400}.fa-spin{animation-name:fa-spin;animation-duration:var(--fa-animation-duration,2s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,linear)}.fa-pulse,.fa-spin-pulse{animation-name:fa-spin;animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,steps(8))}@keyframes fa-spin{0%{transform:rotate(0)}to{transform:rotate(1turn)}}@media(prefers-reduced-motion:reduce){.fa-pulse,.fa-spin,.fa-spin-pulse{animation-delay:-1ms;animation-duration:1ms;animation-iteration-count:1}}@font-face{font-family:"Font Awesome 6 Brands";font-style:normal;font-weight:400;font-display:block;src:url(/assets/fontawesome/webfonts/fa-brands-400.subset.woff2) format("woff2")}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:400;font-display:block;src:url(/assets/fontawesome/webfonts/fa-regular-400.subset.woff2) format("woff2")}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(/assets/fontawesome/webfonts/fa-solid-900.subset.woff2) format("woff2")}@font-face{font-family:"Font Awesome 5 Brands";font-display:block;font-weight:400;src:url(/assets/fontawesome/webfonts/fa-brands-400.subset.woff2) format("woff2")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:900;src:url(/assets/fontawesome/webfonts/fa-solid-900.subset.woff2) format("woff2")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:400;src:url(/assets/fontawesome/webfonts/fa-regular-400.subset.woff2) format("woff2")}@font-face{font-family:FontAwesome;font-display:block;src:url(/assets/fontawesome/webfonts/fa-solid-900.subset.woff2) format("woff2")}@font-face{font-family:FontAwesome;font-display:block;src:url(/assets/fontawesome/webfonts/fa-brands-400.subset.woff2) format("woff2")}@font-face{font-family:FontAwesome;font-display:block;src:url(/assets/fontawesome/webfonts/fa-regular-400.subset.woff2) format("woff2");unicode-range:u+f003,u+f006,u+f014,u+f016-f017,u+f01a-f01b,u+f01d,u+f022,u+f03e,u+f044,u+f046,u+f05c-f05d,u+f06e,u+f070,u+f087-f088,u+f08a,u+f094,u+f096-f097,u+f09d,u+f0a0,u+f0a2,u+f0a4-f0a7,u+f0c5,u+f0c7,u+f0e5-f0e6,u+f0eb,u+f0f6-f0f8,u+f10c,u+f114-f115,u+f118-f11a,u+f11c-f11d,u+f133,u+f147,u+f14e,u+f150-f152,u+f185-f186,u+f18e,u+f190-f192,u+f196,u+f1c1-f1c9,u+f1d9,u+f1db,u+f1e3,u+f1ea,u+f1f7,u+f1f9,u+f20a,u+f247-f248,u+f24a,u+f24d,u+f255-f25b,u+f25d,u+f271-f274,u+f278,u+f27b,u+f28c,u+f28e,u+f29c,u+f2b5,u+f2b7,u+f2ba,u+f2bc,u+f2be,u+f2c0-f2c1,u+f2c3,u+f2d0,u+f2d2,u+f2d4,u+f2dc}.fa-android:before{content:"\f17b"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-apple:before{content:"\f179"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-up-from-bracket:before{content:"\e09a"}.fa-ban:before{content:"\f05e"}.fa-bolt:before{content:"\f0e7"}.fa-camera:before{content:"\f030"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chrome:before{content:"\f268"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-clock:before{content:"\f017"}.fa-code:before{content:"\f121"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-copy:before{content:"\f0c5"}.fa-download:before{content:"\f019"}.fa-edge:before{content:"\f282"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation-triangle:before{content:"\f071"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-file-arrow-down:before{content:"\f56d"}.fa-fingerprint:before{content:"\f577"}.fa-firefox-browser:before{content:"\e007"}.fa-folder-open:before{content:"\f07c"}.fa-globe:before{content:"\f0ac"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-key:before{content:"\f084"}.fa-lightbulb:before{content:"\f0eb"}.fa-link:before{content:"\f0c1"}.fa-linux:before{content:"\f17c"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-microphone-slash:before{content:"\f131"}.fa-network-wired:before{content:"\f6ff"}.fa-opera:before{content:"\f26a"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-paste:before{content:"\f0ea"}.fa-pen:before{content:"\f304"}.fa-play-circle:before{content:"\f144"}.fa-plus:before{content:"+"}.fa-power-off:before{content:"\f011"}.fa-puzzle-piece:before{content:"\f12e"}.fa-qrcode:before{content:"\f029"}.fa-question-circle:before{content:"\f059"}.fa-reply:before{content:"\f3e5"}.fa-right-left:before{content:"\f362"}.fa-rocket:before{content:"\f135"}.fa-safari:before{content:"\f267"}.fa-share:before{content:"\f064"}.fa-shield-alt:before{content:"\f3ed"}.fa-shield-halved:before{content:"\f3ed"}.fa-signature:before{content:"\f5b7"}.fa-sliders-h:before{content:"\f1de"}.fa-spinner:before{content:"\f110"}.fa-stopwatch:before{content:"\f2f2"}.fa-sync-alt:before{content:"\f2f1"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-trash-can:before{content:"\f2ed"}.fa-triangle-exclamation:before{content:"\f071"}.fa-unlock-alt:before{content:"\f13e"}.fa-user:before{content:"\f007"}.fa-vial:before{content:"\f492"}.fa-windows:before{content:"\f17a"}.fa-xmark:before{content:"\f00d"}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/fonts/inter/files/inter-latin-ext.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/fonts/inter/files/inter-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}*{font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif}body{background:#2a2b2a;overflow-x:hidden}.bg-custom-bg{background-color:#252625!important}.bg-my{background-color:#1a1a1a}.bg-header{background-color:#232323!important}.minimal-bg{background:linear-gradient(135deg,#1a1a1a,#2a2b2a);position:relative;min-height:100vh}.card-minimal.rounded-xl.p-6.cursor-pointer.group.flex-1.create{background-color:#60a5fa08}.card-minimal.rounded-xl.p-6.cursor-pointer.group.flex-1.join{background-color:#34d39908}tr.bg-black-table{background-color:#1c1c1c}.text-primary{color:#f1f5f9}.text-secondary{color:#b6b6b6}.text-muted{color:#818080}.accent-orange{color:#fb923c}.accent-green{color:#34d399}.accent-red{color:#f87171}.accent-yellow{color:#fbbf24}.accent-purple{color:#a78bfa}.accent-blue{color:#60a5fa}.accent-gray{color:#9ca3af}.accent-cyan{color:#22d3ee}.custom-scrollbar::-webkit-scrollbar-track{background:#2a2b2a4d;border-radius:3px}.custom-scrollbar::-webkit-scrollbar-thumb{background:#4b556380;border-radius:3px}.custom-scrollbar::-webkit-scrollbar-thumb:hover{background:#4b5563b3}.scroll-smooth{scroll-behavior:smooth}.messages-container,.chat-messages-area{scroll-behavior:smooth;scroll-padding-bottom:20px}.chat-messages-area>div:first-child{scroll-behavior:smooth;scroll-padding-bottom:20px}[class*=chat]{scroll-behavior:smooth}@media(max-width:640px){.header-minimal{padding:0 8px}.icon-container{min-width:32px;min-height:32px}.verification-code{font-size:.875rem;padding:6px 8px}.header-minimal .max-w-7xl{padding-inline:8px}.header-minimal button{min-width:32px;min-height:32px}}@media(min-width:641px)and (max-width:1024px){.header-minimal .max-w-7xl{padding-inline:16px}}.card{position:relative;border-radius:12px;overflow:hidden;transition:transform .3s ease}.card:before{content:"";position:absolute;inset:0;border-radius:12px;padding:2px;background:radial-gradient(circle at var(--x, 50%) var(--y, 50%),var(--color),transparent 80%);opacity:0;transition:opacity .4s;-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude}.card.active-glow:before{opacity:1}.card:after{content:"";position:absolute;inset:3px;border-radius:10px;z-index:1}:root{--gap: 1.25rem;--speed: .55s cubic-bezier(.25, .46, .45, .94);--closed: 5rem;--open: 30rem;--accent: #fb923c}*{margin:0;padding:0;box-sizing:border-box}body{font-family:Inter,sans-serif;background:#07090d;color:#c5c7ce}.head{max-width:1400px;margin:auto;padding:70px 20px 40px;display:flex;justify-content:space-between;align-items:flex-end;gap:2rem}.nav-btn{width:2.5rem;height:2.5rem;border:none;border-radius:50%;background:#ffffff1f;color:#fff;font-size:1.5rem;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:.3s}.nav-btn:hover{background:var(--accent)}.nav-btn:disabled{opacity:.3;cursor:default}.slider{max-width:1400px;margin:auto;overflow:hidden}.controls{display:flex;flex-direction:row;gap:.5rem}.track{display:flex;gap:var(--gap);align-items:flex-start;justify-content:center;scroll-behavior:smooth;scroll-snap-type:x mandatory;padding-bottom:40px}.track::-webkit-scrollbar{display:none}.project-card{position:relative;flex:0 0 var(--closed);height:26rem;border-radius:1rem;overflow:hidden;cursor:pointer;transition:flex-basis var(--speed),transform var(--speed)}.project-card[active]{flex-basis:var(--open);transform:translateY(-6px);box-shadow:0 15px 12px #00000040}.project-card__bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;filter:brightness(.75) saturate(75%);transition:filter .3s,transform var(--speed)}.project-card:hover .project-card__bg{filter:brightness(.9) saturate(100%);transform:scale(1.06)}.project-card__content{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;align-items:center;gap:.7rem;padding:0;background:linear-gradient(transparent 40%,#00000059);z-index:2}.project-card__title{color:#fff;font-weight:700;font-size:1.35rem;writing-mode:vertical-rl;transform:rotate(180deg)}.project-card__thumb,.project-card__desc,.project-card__btn{display:none}.project-card[active] .project-card__content{flex-direction:row;align-items:center;padding:1.2rem 2rem;gap:1.1rem}.project-card[active] .project-card__title{writing-mode:horizontal-tb;transform:none;font-size:2.4rem}.project-card[active] .project-card__thumb,.project-card[active] .project-card__desc,.project-card[active] .project-card__btn{display:block}.project-card__thumb{width:133px;height:269px;border-radius:.45rem;object-fit:cover;box-shadow:0 4px 10px #0006}.project-card__desc{color:#b6b6b6;font-size:1rem;line-height:1.4;max-width:16rem}@media(max-width:767px){:root{--closed: 4rem;--open: 22rem}.head{padding:50px 20px 30px}.track{flex-direction:column;scroll-snap-type:y mandatory;align-items:center;justify-content:flex-start;padding-bottom:0}.project-card{height:20rem}.project-card__title{font-size:1.1rem;writing-mode:horizontal-tb;transform:none;text-align:center;padding-inline:.3rem}.nav-btn{width:2rem;height:2rem;font-size:1.2rem}}@media(max-width:767px){:root{--closed: 100%;--open: 100%;--gap: .8rem}.head{padding:30px 15px 20px;flex-direction:column;align-items:flex-start;gap:1rem}.slider{padding:0 15px}.track{flex-direction:column;scroll-snap-type:y mandatory;gap:.8rem;padding-bottom:20px}.project-card{height:auto;min-height:80px;flex:0 0 auto;width:100%;scroll-snap-align:start}.project-card[active]{min-height:300px;transform:none;box-shadow:0 8px 25px #0000004d}.project-card__content{flex-direction:row;justify-content:flex-start;padding:1rem;align-items:center;gap:1rem}.project-card__title{writing-mode:horizontal-tb;transform:none;font-size:1.2rem;margin-inline-end:auto}.project-card__thumb,.project-card__desc,.project-card__btn{display:none}.project-card[active] .project-card__content{align-items:flex-start;padding:1.5rem}.project-card[active] .project-card__title{font-size:1.8rem;margin-bottom:1rem;margin-top:2rem}.project-card[active] .project-card__thumb{width:200px;height:267px;border-radius:.35rem;margin-bottom:1rem}.project-card[active] .project-card__desc{font-size:.95rem;max-width:100%;margin-bottom:1rem}.project-card[active] .project-card__btn{align-self:center;width:100%;text-align:center;padding:.7rem}.dots{display:none}.controls{width:100%;justify-content:space-between;padding:0 15px 20px}.nav-btn{position:static;transform:none}}@keyframes pulse{0%,to{transform:scale(1)}50%{transform:scale(1.05)}}@keyframes vmRec{0%,to{opacity:1;transform:scale(1)}50%{opacity:.35;transform:scale(.82)}}@keyframes vmRing{0%{transform:scale(1);opacity:.5}to{transform:scale(2.1);opacity:0}}@keyframes sbCallPulse{0%{transform:scale(1);opacity:.5}to{transform:scale(1.85);opacity:0}}@keyframes sbLiveBg{0%,to{background-position:0% 50%}50%{background-position:100% 50%}}.minimal-bg{min-height:100vh;display:flex;flex-direction:column}.hide-scrollbar{-ms-overflow-style:none;scrollbar-width:none}.hide-scrollbar::-webkit-scrollbar{display:none}.file-transfer-component{margin-top:1rem}@media(max-width:768px){.mobile-chat-height{height:calc(100dvh - 64px)!important}.scroll-to-bottom-mobile{bottom:140px!important;inset-inline-end:16px!important;width:40px!important;height:40px!important}}@media(max-width:480px){.header-minimal{height:56px}.mobile-chat-height{height:calc(100dvh - 56px)!important}}.file-drop-zone{border:2px dashed #4b5563;border-radius:12px;padding:2rem;text-align:center;cursor:pointer;transition:all .3s ease;background:#3741511a}.file-drop-zone:hover{border-color:#3b82f6;background:#3b82f61a}.file-drop-zone.drag-over{border-color:#10b981;background:#10b9811a;transform:scale(1.02)}.drop-content{pointer-events:none}.active-transfers{max-height:300px;overflow-y:auto}.transfer-item{transition:all .2s ease}.transfer-item:hover{transform:translateY(-1px)}.progress-bar{position:relative;height:6px;background:#4b55634d;border-radius:3px;overflow:hidden}.progress-fill{height:100%;transition:width .3s ease;border-radius:3px}.progress-text{position:absolute;top:-20px;inset-inline-end:0;color:#9ca3af}.file-transfer-section{border-top:1px solid rgba(75,85,99,.1)}@media(max-width:640px){.file-drop-zone{padding:1.5rem}.transfer-item{padding:.75rem}.progress-text{font-size:.75rem}}.header-minimal{background:#23242321;backdrop-filter:blur(5px);-webkit-backdrop-filter:blur(5px);flex-shrink:0;height:64px;position:sticky;top:0;z-index:40}.header-minimal .cursor-pointer:hover{transform:scale(1.05);transition:transform .2s ease}.header-minimal .cursor-pointer:active{transform:scale(.95)}.chat-container{flex-direction:column;height:calc(100vh - 64px);min-height:0}.chat-messages-area{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column}.chat-input-area{flex-shrink:0;position:sticky;bottom:0;background:#2a2b2af2;backdrop-filter:blur(10px);border-top:1px solid rgba(75,85,99,.2)}.chat-messages-area>div:first-child{height:100%;overflow-y:auto;padding:1rem;scroll-behavior:smooth;scroll-padding-bottom:20px;scroll-margin-bottom:20px}@media(max-width:768px){.chat-container{height:calc(100vh - 64px);height:calc(100dvh - 64px)}}main{flex:1;display:flex;flex-direction:column;min-height:0}.card-minimal{background:#2a2b2acc;backdrop-filter:blur(16px);border:1px solid rgba(75,85,99,.2);box-shadow:0 4px 16px #0000001a}.card-minimal--selected{background:#f9731626!important;border-color:#f97316!important;box-shadow:0 0 0 2px #f973164d!important}.status-dot{width:8px;height:8px;border-radius:50%;display:inline-block;margin-inline-end:8px}.status-connected{background:#10b981}.status-connecting{background:#6b7280}.status-failed{background:#ef4444}.status-disconnected{background:#6b7280}.status-verifying{background:#9ca3af}.security-shield{background:linear-gradient(135deg,#2a2b2a,#3a3b3a);border:1px solid rgba(75,85,99,.3)}.verification-code{background:#2a2b2acc;border:1px solid rgba(75,85,99,.3);color:#f1f5f9;font-family:Monaco,Menlo,monospace;letter-spacing:.1em;font-size:1.2em;padding:8px 12px;border-radius:8px;text-align:center}.icon-container{width:40px;height:40px;background:#2a2b2acc;border:1px solid rgba(75,85,99,.3);border-radius:8px;display:flex;align-items:center;justify-content:center}.icon-container i{font-size:1.25rem;line-height:1}.icon-sm{font-size:.875rem}.icon-md{font-size:1rem}.icon-lg{font-size:1.125rem}.icon-xl{font-size:1.25rem}.icon-2xl{font-size:1.5rem}.step-number{width:32px;height:32px;background:linear-gradient(135deg,#f97316,#ea580c);color:#fff;border-radius:8px;display:flex;align-items:center;justify-content:center;font-weight:600;font-size:14px}.icon-fallback{display:inline-block;width:1em;height:1em;background-size:contain;background-repeat:no-repeat;background-position:center}.fas,.far,.fab{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;vertical-align:middle}.fas:before,.far:before,.fab:before{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.icon-loading{opacity:.7;animation:iconPulse 1.5s ease-in-out infinite}.fa-fallback .fas.fa-shield-halved:before{content:"\1f6e1\fe0f"}.fa-fallback .fas.fa-shield-alt:before{content:"\1f6e1\fe0f"}.fa-fallback .fas.fa-lock:before{content:"\1f512"}.fa-fallback .fas.fa-unlock-alt:before{content:"\1f513"}.fa-fallback .fas.fa-key:before{content:"\1f511"}.fa-fallback .fas.fa-fingerprint:before{content:"\1f446"}.fa-fallback .fas.fa-exchange-alt:before{content:"\1f504"}.fa-fallback .fas.fa-plus:before{content:"\2795"}.fa-fallback .fas.fa-link:before{content:"\1f517"}.fa-fallback .fas.fa-paste:before{content:"\1f4cb"}.fa-fallback .fas.fa-check-circle:before{content:"\2705"}.fa-fallback .fas.fa-cogs:before{content:"\2699\fe0f"}.fa-fallback .fas.fa-rocket:before{content:"\1f680"}.fa-fallback .fas.fa-copy:before{content:"\1f4c4"}.fa-fallback .fas.fa-check:before{content:"\2713"}.fa-fallback .fas.fa-times:before{content:"\2717"}.fa-fallback .fas.fa-exclamation-triangle:before{content:"\26a0\fe0f"}.fa-fallback .fas.fa-info-circle:before{content:"\2139\fe0f"}.fa-fallback .fas.fa-circle:before{content:"\25cf"}.fa-fallback .fas.fa-paper-plane:before{content:"\1f4e4"}.fa-fallback .fas.fa-comments:before{content:"\1f4ac"}.fa-fallback .fas.fa-signature:before{content:"\270d\fe0f"}.fa-fallback .fas.fa-power-off:before{content:"\23fb"}.fa-fallback .fas.fa-arrow-left:before{content:"\2190"}.fa-fallback .fas.fa-chevron-down:before{content:"\2193"}.fa-fallback .fas:before{font-family:"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-size:inherit}button i{vertical-align:middle;margin-inline-end:.5rem}.lightning-button{background:linear-gradient(135deg,#f59e0b,#d97706);border:1px solid rgba(245,158,11,.3);transition:all .3s ease}.lightning-button:hover{background:linear-gradient(135deg,#d97706,#b45309);transform:translateY(-2px)}.btn-primary{background:linear-gradient(135deg,#f97316,#ea580c);border:1px solid rgba(249,115,22,.3)}.btn-primary:hover{background:linear-gradient(135deg,#ea580c,#dc2626);transform:translateY(-1px)}.btn-secondary{background:linear-gradient(135deg,#2a2b2a,#3a3b3a);border:1px solid rgba(75,85,99,.3)}.btn-secondary:hover{background:linear-gradient(135deg,#3a3b3a,#4a4b4a);transform:translateY(-1px)}.btn-verify{background:linear-gradient(135deg,#2a2b2a,#3a3b3a);border:1px solid rgba(75,85,99,.3)}.btn-verify:hover{background:linear-gradient(135deg,#3a3b3a,#4a4b4a);transform:translateY(-1px)}.wallet-logos-container{display:flex;align-items:center;overflow:hidden;position:relative;height:64px;margin:20px 0;width:100%}.wallet-logos-track{display:flex;align-items:center;gap:20px;animation:walletLogosScroll 30s linear infinite;width:max-content}.wallet-logo{display:flex;align-items:center;justify-content:center;width:100px;height:48px;background:#2a2b2acc;border:1px solid rgba(75,85,99,.3);border-radius:8px;font-size:14px;font-weight:600;color:#f1f5f9;flex-shrink:0;transition:all .3s ease}.wallet-logo:hover{border-color:#f973164d;background:#f973161a;transform:translateY(-2px) scale(1.05);box-shadow:0 4px 10px #0003}.wallet-logo.bitcoin-lightning{background:transparent;padding:4px}.wallet-logo.bitcoin-lightning img{width:48px;height:48px;filter:brightness(0) saturate(100%) invert(43%) sepia(8%) saturate(670%) hue-rotate(202deg) brightness(97%) contrast(86%)}.wallet-logo.impervious{background:transparent;padding:4px}.wallet-logo.impervious img{width:48px;height:48px;filter:brightness(0) saturate(100%) invert(43%) sepia(8%) saturate(670%) hue-rotate(202deg) brightness(97%) contrast(86%)}.wallet-logo.strike{background:transparent;padding:4px}.wallet-logo.strike img{width:48px;height:48px;filter:brightness(0) saturate(100%) invert(43%) sepia(8%) saturate(670%) hue-rotate(202deg) brightness(97%) contrast(86%)}.wallet-logo.lnbits{background:transparent;padding:4px}.wallet-logo.lnbits img{width:48px;height:48px;filter:brightness(0) saturate(100%) invert(43%) sepia(8%) saturate(670%) hue-rotate(202deg) brightness(97%) contrast(86%)}.wallet-logo.lightning-labs{background:transparent;padding:4px}.wallet-logo.lightning-labs img{width:48px;height:48px;filter:brightness(0) saturate(100%) invert(43%) sepia(8%) saturate(670%) hue-rotate(202deg) brightness(97%) contrast(86%)}.wallet-logo.atomic{background:transparent;padding:4px}.wallet-logo.atomic img{width:48px;height:48px;filter:brightness(0) saturate(100%) invert(43%) sepia(8%) saturate(670%) hue-rotate(202deg) brightness(97%) contrast(86%)}.wallet-logo.breez{background:transparent;padding:4px}.wallet-logo.breez img{width:48px;height:48px;filter:brightness(0) saturate(100%) invert(43%) sepia(8%) saturate(670%) hue-rotate(202deg) brightness(97%) contrast(86%)}.wallet-logo.alby{background:transparent;padding:4px}.wallet-logo.alby img{width:48px;height:48px;filter:brightness(0) saturate(100%) invert(43%) sepia(8%) saturate(670%) hue-rotate(202deg) brightness(97%) contrast(86%)}.wallet-logo.phoenix,.wallet-logo.blixt{background:transparent}.wallet-logo.zeus{background:transparent;padding:4px}.wallet-logo.zeus img{width:48px;height:48px;filter:brightness(0) saturate(100%) invert(43%) sepia(8%) saturate(670%) hue-rotate(202deg) brightness(97%) contrast(86%)}.wallet-logo.wos{background:transparent;padding:4px}.wallet-logo.wos img{width:80px;height:48px;filter:brightness(0) saturate(100%) invert(43%) sepia(8%) saturate(670%) hue-rotate(202deg) brightness(97%) contrast(86%)}.wallet-logo.muun{background:transparent;padding:4px}.wallet-logo.muun img{width:48px;height:48px;filter:brightness(0) saturate(100%) invert(43%) sepia(8%) saturate(670%) hue-rotate(202deg) brightness(97%) contrast(86%)}.wallet-logos-container:hover .wallet-logos-track{animation-play-state:paused}.message-slide{animation:messageSlideIn .3s ease-out}.chat-messages-area .message:last-child{scroll-margin-bottom:20px}.message{word-wrap:break-word;overflow-wrap:break-word;white-space:normal;max-width:100%}.message span{word-wrap:break-word;overflow-wrap:break-word;white-space:normal;display:inline-block;max-width:100%}.chat-messages-area{scroll-behavior:smooth;scroll-padding-bottom:20px}@keyframes iconPulse{0%,to{opacity:.7}50%{opacity:1}}@keyframes messageSlideIn{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes walletLogosScroll{0%{transform:translate(0)}to{transform:translate(-50%)}}@keyframes pulse{0%,to{opacity:1}50%{opacity:.7}}@keyframes shimmer{0%{transform:translate(-100%) skew(-15deg)}to{transform:translate(200%) skew(-15deg)}}.btn-partner-modern{position:relative;background:linear-gradient(135deg,#f97316,#ea580c,#dc2626);background-size:200% 200%;background-position:0% 0;box-shadow:0 4px 15px #f973164d;transition:all .3s cubic-bezier(.4,0,.2,1);overflow:hidden}.btn-partner-modern:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.2) 50%,transparent 100%);transition:left .5s}.btn-partner-modern:hover{background-position:100% 0;transform:translateY(-2px) scale(1.02);box-shadow:0 8px 25px #f9731680,0 0 30px #f973164d}.btn-partner-modern:hover:before{left:100%;animation:shimmer 1.5s ease-in-out}.btn-partner-modern:active{transform:translateY(0) scale(.98);box-shadow:0 2px 10px #f9731666}.custom-scrollbar{scrollbar-width:thin;scrollbar-color:rgba(156,163,175,.5) transparent}.custom-scrollbar::-webkit-scrollbar{width:6px}.custom-scrollbar::-webkit-scrollbar-track{background:transparent}.custom-scrollbar::-webkit-scrollbar-thumb{background-color:#9ca3af80;border-radius:3px}.custom-scrollbar::-webkit-scrollbar-thumb:hover{background-color:#9ca3afb3}.accent-orange{color:#fb923c!important}.accent-green{color:#34d399!important}.accent-red{color:#f87171!important}.accent-yellow{color:#fbbf24!important}.accent-purple{color:#a78bfa!important}.accent-gray{color:#9ca3af!important}.accent-cyan{color:#22d3ee!important}.accent-blue{color:#60a5fa!important}.text-secondary i{opacity:.8}.button-container{perspective:1000px}.button{width:200px;height:60px;border-radius:30px;background:linear-gradient(to bottom,#ffffff26,#ffffff0d);box-shadow:inset 0 1px 2px #fff6,inset 0 -1px 2px #0003,0 4px 8px #0003,0 0 20px #ffffff1a;transform:rotateX(15deg) translateZ(0);transition:all .3s cubic-bezier(.68,-.55,.27,1.55);position:relative;cursor:pointer;animation:pulse 2s infinite ease-in-out;overflow:hidden;text-decoration:none;display:block}.button:before{content:"";position:absolute;top:0;left:-50px;width:50px;height:100%;background:linear-gradient(to right,transparent,rgba(255,255,255,.1),rgba(255,255,255,.2),rgba(255,255,255,.1),transparent);transform:skew(-25deg);animation:shine 3s infinite linear;pointer-events:none;z-index:1}.button:after{content:"";position:absolute;bottom:-10px;left:10%;width:80%;height:10px;background:radial-gradient(ellipse at center,rgba(0,0,0,.3) 0%,transparent 70%);z-index:-1}.button span{position:relative;z-index:2;color:#fff;font-size:18px;font-family:Arial,sans-serif;text-shadow:0 1px 2px rgba(0,0,0,.5);display:block;line-height:60px;text-align:center}.button:hover{transform:rotateX(0) translateZ(15px) scale(1.05);box-shadow:inset 0 1px 2px #fff6,inset 0 -1px 2px #0003,0 8px 16px #0000004d,0 0 40px #ffffff40}.button:active{transform:rotateX(0) translateZ(-5px) scale(.95);box-shadow:inset 0 1px 2px #fff6,inset 0 -1px 2px #0003,0 2px 4px #0003,0 0 10px #ffffff1a}@keyframes pulse{0%,to{box-shadow:inset 0 1px 2px #fff6,inset 0 -1px 2px #0003,0 4px 8px #0003,0 0 20px #ffffff1a}50%{box-shadow:inset 0 1px 2px #fff6,inset 0 -1px 2px #0003,0 4px 8px #0003,0 0 30px #fff3}}@keyframes shine{0%{left:-50px}to{left:250px}}.sb-scroll{scrollbar-gutter:auto;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.13) transparent}.sb-scroll::-webkit-scrollbar{width:9px}.sb-scroll::-webkit-scrollbar-track{background:transparent}.sb-scroll::-webkit-scrollbar-thumb{background:#ffffff12;border-radius:99px;border:2px solid transparent;background-clip:padding-box}.sb-scroll::-webkit-scrollbar-thumb:hover{background:#ffffff21;background-clip:padding-box}.sb-textarea::placeholder{color:#56565e}.sb-chip:hover{border-color:#ffffff29!important;color:#e8e8eb!important}.sb-send:hover:not(:disabled){filter:brightness(1.06)}.sb-unsend:hover{color:#e5727a!important}.sb-link:hover{color:#e8e8eb!important}.sb-disconnect:hover{border-color:#e5727a66!important;color:#e5727a!important;background:#e5727a0f!important}@media(max-width:560px){.sb-hide-sm{display:none}}.sb-secpill:hover{border-color:#ffffff29!important;background:#ffffff0d!important}@keyframes sbFlowR{0%{left:4%;opacity:0}12%{opacity:1}88%{opacity:1}to{left:96%;opacity:0}}@keyframes sbFlowL{0%{left:96%;opacity:0}12%{opacity:1}88%{opacity:1}to{left:4%;opacity:0}}@keyframes sbPulse{0%,to{transform:translate(-50%,-50%) scale(1);opacity:.5}50%{transform:translate(-50%,-50%) scale(1.5);opacity:0}}@keyframes sbSpin{to{transform:rotate(360deg)}}@keyframes sbUp{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes sbNode{0%,to{box-shadow:0 0 #3ecf8e00}50%{box-shadow:0 0 0 6px #3ecf8e0f}}@keyframes sbScan{0%{top:8%}to{top:88%}}@keyframes sbSlideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}#qr-reader{width:100%;height:100%;border:none!important}#qr-reader video{width:100%!important;height:100%!important;object-fit:cover!important;display:block}#qr-reader img,#qr-reader__dashboard,#qr-reader__status_span{display:none!important}@media(max-width:1024px){.sb-conn-footer{flex-direction:column!important;align-items:stretch!important}.sb-conn-footer>button{width:100%!important;justify-content:center!important}.sb-conn-footer>.sb-platforms-menu{width:100%!important}}.sb-start textarea::placeholder,.sb-start input::placeholder{color:#56565e}.sb-start .sb-sc::-webkit-scrollbar{width:8px}.sb-start .sb-sc::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:99px}.sb-seg-btn{transition:color .2s}.sb-soft-btn{transition:all .15s}.sb-soft-btn:hover{border-color:#ffffff2e!important;color:#e8e8eb!important}.sb-scan-btn:hover{border-color:#3ecf8e80!important;background:#3ecf8e1a!important}.sb-gen-btn:hover{background:#ff9637!important}.sb-start-card{transition:transform .26s cubic-bezier(.3,.8,.3,1)}@media(max-width:900px){.sb-start-left{border-inline-end:none!important}}@media(max-width:560px){.sb-start-left{padding:30px 22px!important}}body.sb-in-chat #pwa-install-button{display:none!important}body.sb-in-chat #pwa-connection-status{top:calc(var(--sb-bar-h, 64px) + 12px + var(--sb-safe-top, 0px) + var(--sb-bar-extra, 0px))!important}.sb-start button i,.sb-ice-overlay button i{margin-inline-end:0;vertical-align:baseline}:root{--sb-press: .11s cubic-bezier(.2, 0, 0, 1);--sb-settle: .24s cubic-bezier(.2, .7, .3, 1)}button,[role=button],a,label,summary,input[type=checkbox],input[type=radio],.cursor-pointer{touch-action:manipulation;-webkit-tap-highlight-color:transparent}button:not(:disabled):active,[role=button]:not([aria-disabled=true]):active,.cursor-pointer:active{transform:scale(.97);transition:transform var(--sb-press)}button,[role=button]{transition:transform var(--sb-settle)}button:disabled,[aria-disabled=true]{cursor:not-allowed}@media(hover:none){.card-minimal:hover,.wallet-logo:hover,.btn-primary:hover,.btn-secondary:hover,.btn-verify:hover,.lightning-button:hover,.btn-partner-modern:hover,.transfer-item:hover,.file-drop-zone:hover,.project-card:hover .project-card__bg{transform:none;box-shadow:none}}:focus-visible{outline:2px solid rgba(249,115,22,.75);outline-offset:2px}.header-minimal{box-shadow:inset 0 1px #ffffff0d}.card-minimal{backdrop-filter:blur(14px) saturate(140%);-webkit-backdrop-filter:blur(14px) saturate(140%)}html{font-optical-sizing:auto}h1,.text-6xl,.text-5xl{letter-spacing:-.024em;line-height:1.05}h2,.text-4xl{letter-spacing:-.021em;line-height:1.1}h3,.text-3xl{letter-spacing:-.018em;line-height:1.15}.text-2xl{letter-spacing:-.014em}.text-xl{letter-spacing:-.011em}.text-lg{letter-spacing:-.006em}.text-base,p{letter-spacing:0}.text-sm{letter-spacing:.004em}.text-xs{letter-spacing:.012em}.header-minimal .text-secondary,.chat-input-area .text-secondary,.card-minimal .text-muted{color:#c3c3c9;letter-spacing:.01em}@media(prefers-reduced-motion:reduce){.wallet-logos-track,.button,.button:before,.icon-loading,[style*=sbPulse],[style*=sbFlow],[style*=sbNode],[style*=sbScan],[style*=sbTrav],[style*=sbRing],[style*=sbLiveBg],[style*=sbCallPulse],[style*=rmPulse],[style*=vmRing]{animation:none!important}@keyframes sbFadeInPlace{0%{opacity:0}to{opacity:1}}.message-slide,[style*=sbUp],[style*=sbSlideUp],[style*=sbExpand],[style*=ccUp],[style*=ptUp],[style*=wuUp],[style*=rmExp],[style*=sbRow],[style*=sbIn1],[style*=sbIn2]{animation:sbFadeInPlace .16s ease-out both!important;transform:none!important}[style*=vmRec]{animation:vmRecSoft 1.4s ease-in-out infinite!important;transform:none!important}@keyframes vmRecSoft{0%,to{opacity:1}50%{opacity:.4}}.card-minimal:hover,.wallet-logo:hover,.btn-primary:hover,.btn-secondary:hover,.btn-verify:hover,.lightning-button:hover,.btn-partner-modern:hover,.transfer-item:hover,.file-drop-zone:hover,.project-card:hover,.project-card:hover .project-card__bg,.header-minimal .cursor-pointer:hover{transform:none!important}button:not(:disabled):active,[role=button]:active,.cursor-pointer:active{transform:none!important;opacity:.7}.sb-drawer-overlay{transition:opacity .16s ease!important}html,body,.scroll-smooth,.messages-container,.chat-messages-area,.sb-scroll,.track{scroll-behavior:auto!important}}@media(prefers-reduced-transparency:reduce){.header-minimal,.card-minimal,.sb-chat-header{backdrop-filter:none!important;-webkit-backdrop-filter:none!important}.header-minimal{background:#18181a!important}.card-minimal{background:#202022!important}}@media(prefers-contrast:more){.card-minimal,.icon-container,.verification-code,.security-shield{background:#141416!important;border-color:#ffffff6b!important}.text-secondary{color:#e4e4e8!important}.text-muted{color:#c8c8cf!important}:focus-visible{outline-width:3px}}[lang=ar],[lang=fa],[lang=ur]{font-family:Inter,SF Arabic,Geeza Pro,Segoe UI,Tahoma,Noto Naskh Arabic,Noto Sans Arabic,Droid Arabic Naskh,sans-serif}[lang=ur]{font-family:Noto Nastaliq Urdu,Jameel Noori Nastaleeq,Urdu Typesetting,Inter,SF Arabic,Segoe UI,Tahoma,Noto Naskh Arabic,sans-serif;line-height:2}[lang=he]{font-family:Inter,SF Hebrew,Arial Hebrew,Segoe UI,Noto Sans Hebrew,sans-serif}[dir=rtl] code,[dir=rtl] pre,[dir=rtl] .sb-sc{direction:ltr;unicode-bidi:isolate;text-align:start}[dir=rtl] .fa-chevron-left,[dir=rtl] .fa-chevron-right,[dir=rtl] .fa-angle-left,[dir=rtl] .fa-angle-right,[dir=rtl] .fa-arrow-left,[dir=rtl] .fa-arrow-right,[dir=rtl] .fa-caret-left,[dir=rtl] .fa-caret-right,[dir=rtl] .fa-reply,[dir=rtl] .sb-mirror-rtl{transform:scaleX(-1)}[dir=rtl] .translate-x-full{--tw-translate-x: -100%}[dir=rtl] .-translate-x-full{--tw-translate-x: 100%}#pwa-update-banner{backdrop-filter:blur(10px);border-bottom:1px solid rgba(255,255,255,.1);animation:slideDown .3s ease-out}@keyframes slideDown{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}.pwa-notification{backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.1)}:root{--sb-safe-top: 0px;--sb-bar-extra: 0px;--sb-bar-h: 64px}@media(display-mode:standalone){:root{--sb-safe-top: min(env(safe-area-inset-top, 0px), max(20px, env(safe-area-inset-top, 0px) - 3px));--sb-bar-h: 56px;--sb-bar-extra: 7px}.header-minimal{height:auto}}body.pwa-installed{--sb-safe-top: min(env(safe-area-inset-top, 0px), max(20px, env(safe-area-inset-top, 0px) - 3px));--sb-bar-h: 56px;--sb-bar-extra: 7px}body.pwa-installed .header-minimal{height:auto}.pwa-splash{position:fixed;top:0;left:0;width:100%;height:100%;background:linear-gradient(135deg,#1a1a1a,#2d2d2d);display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:9999;transition:opacity .5s ease-out,visibility .5s ease-out}.pwa-splash.hidden{opacity:0;visibility:hidden}.pwa-splash .logo{width:120px;height:120px;background:linear-gradient(135deg,#ff6b35,#f7941d);border-radius:24px;display:flex;align-items:center;justify-content:center;margin-bottom:24px;animation:pulse-logo 2s infinite}.pwa-splash .logo i{font-size:48px;color:#fff}@keyframes pulse-logo{0%,to{transform:scale(1);box-shadow:0 0 #ff6b3566}50%{transform:scale(1.05);box-shadow:0 0 0 20px #ff6b3500}}.pwa-splash .title{color:#ff6b35;font-size:24px;font-weight:600;margin-bottom:8px}.pwa-splash .subtitle{color:#9ca3af;font-size:14px;margin-bottom:32px}.pwa-splash .loading{width:200px;height:4px;background:#ff6b3533;border-radius:2px;overflow:hidden}.pwa-splash .loading:after{content:"";display:block;width:50%;height:100%;background:linear-gradient(90deg,#ff6b35,#f7941d);border-radius:2px;animation:loading-bar 1.5s ease-in-out infinite}@keyframes loading-bar{0%{transform:translate(-100%)}to{transform:translate(300%)}}.pwa-offline-indicator{position:fixed;bottom:20px;left:50%;transform:translate(-50%);background:#ef4444e6;color:#fff;padding:8px 16px;border-radius:20px;font-size:14px;font-weight:500;backdrop-filter:blur(10px);border:1px solid rgba(239,68,68,.3);animation:fadeInUp .3s ease-out;z-index:1000}.pwa-online-indicator{position:fixed;bottom:20px;left:50%;transform:translate(-50%);background:#22c55ee6;color:#fff;padding:8px 16px;border-radius:20px;font-size:14px;font-weight:500;backdrop-filter:blur(10px);border:1px solid rgba(34,197,94,.3);animation:fadeInUp .3s ease-out;z-index:1000}@keyframes fadeInUp{0%{opacity:0;transform:translate(-50%,20px)}to{opacity:1;transform:translate(-50%)}}@supports (padding: max(0px)){.pwa-safe-area{padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right));padding-bottom:max(16px,env(safe-area-inset-bottom))}.pwa-safe-area-top{padding-top:max(16px,env(safe-area-inset-top))}}@media(prefers-color-scheme:dark){.pwa-notification{border-color:#ffffff1a}}.pwa-fade-in{animation:fadeIn .3s ease-out}.pwa-slide-up{animation:slideUp .3s ease-out}.pwa-scale-in{animation:scaleIn .3s ease-out}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes scaleIn{0%{opacity:0;transform:scale(.9)}to{opacity:1;transform:scale(1)}} diff --git a/assets/fontawesome/css/subset.css b/assets/fontawesome/css/subset.css new file mode 100644 index 0000000..c15f6ba --- /dev/null +++ b/assets/fontawesome/css/subset.css @@ -0,0 +1,4 @@ +/* Generated by scripts/subset-icons.py — do not edit by hand. + Font Awesome Free 6.5.1 (CC BY 4.0 icons, SIL OFL 1.1 fonts, MIT code). + The families and animations this app uses, plus only the icons it draws. */ +.fa{font-family:var(--fa-style-family,"Font Awesome 6 Free");font-weight:var(--fa-style,900)}.fa,.fa-brands,.fa-regular,.fa-solid,.fab,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:var(--fa-display,inline-block);font-style:normal;font-variant:normal;line-height:1;text-rendering:auto}.fa-regular,.fa-solid,.far,.fas{font-family:"Font Awesome 6 Free"}.fa-brands,.fab{font-family:"Font Awesome 6 Brands"}.fa-solid,.fas{font-weight:900}.fa-regular,.far{font-weight:400}.fa-brands,.fab{font-weight:400}.fa-spin{animation-name:fa-spin;animation-duration:var(--fa-animation-duration,2s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,linear)}.fa-pulse,.fa-spin-pulse{animation-name:fa-spin;animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,steps(8))}@keyframes fa-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@media (prefers-reduced-motion:reduce){.fa-pulse,.fa-spin,.fa-spin-pulse{animation-delay:-1ms;animation-duration:1ms;animation-iteration-count:1}}@font-face{font-family:"Font Awesome 6 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.subset.woff2) format("woff2")}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.subset.woff2) format("woff2")}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.subset.woff2) format("woff2")}@font-face{font-family:"Font Awesome 5 Brands";font-display:block;font-weight:400;src:url(../webfonts/fa-brands-400.subset.woff2) format("woff2")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:900;src:url(../webfonts/fa-solid-900.subset.woff2) format("woff2")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:400;src:url(../webfonts/fa-regular-400.subset.woff2) format("woff2")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-solid-900.subset.woff2) format("woff2")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-brands-400.subset.woff2) format("woff2")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-regular-400.subset.woff2) format("woff2");unicode-range:u+f003,u+f006,u+f014,u+f016-f017,u+f01a-f01b,u+f01d,u+f022,u+f03e,u+f044,u+f046,u+f05c-f05d,u+f06e,u+f070,u+f087-f088,u+f08a,u+f094,u+f096-f097,u+f09d,u+f0a0,u+f0a2,u+f0a4-f0a7,u+f0c5,u+f0c7,u+f0e5-f0e6,u+f0eb,u+f0f6-f0f8,u+f10c,u+f114-f115,u+f118-f11a,u+f11c-f11d,u+f133,u+f147,u+f14e,u+f150-f152,u+f185-f186,u+f18e,u+f190-f192,u+f196,u+f1c1-f1c9,u+f1d9,u+f1db,u+f1e3,u+f1ea,u+f1f7,u+f1f9,u+f20a,u+f247-f248,u+f24a,u+f24d,u+f255-f25b,u+f25d,u+f271-f274,u+f278,u+f27b,u+f28c,u+f28e,u+f29c,u+f2b5,u+f2b7,u+f2ba,u+f2bc,u+f2be,u+f2c0-f2c1,u+f2c3,u+f2d0,u+f2d2,u+f2d4,u+f2dc}.fa-android:before{content:"\f17b"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-apple:before{content:"\f179"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-up-from-bracket:before{content:"\e09a"}.fa-ban:before{content:"\f05e"}.fa-bolt:before{content:"\f0e7"}.fa-camera:before{content:"\f030"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chrome:before{content:"\f268"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-clock:before{content:"\f017"}.fa-code:before{content:"\f121"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-copy:before{content:"\f0c5"}.fa-download:before{content:"\f019"}.fa-edge:before{content:"\f282"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation-triangle:before{content:"\f071"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-file-arrow-down:before{content:"\f56d"}.fa-fingerprint:before{content:"\f577"}.fa-firefox-browser:before{content:"\e007"}.fa-folder-open:before{content:"\f07c"}.fa-globe:before{content:"\f0ac"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-key:before{content:"\f084"}.fa-lightbulb:before{content:"\f0eb"}.fa-link:before{content:"\f0c1"}.fa-linux:before{content:"\f17c"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-microphone-slash:before{content:"\f131"}.fa-network-wired:before{content:"\f6ff"}.fa-opera:before{content:"\f26a"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-paste:before{content:"\f0ea"}.fa-pen:before{content:"\f304"}.fa-play-circle:before{content:"\f144"}.fa-plus:before{content:"\2b"}.fa-power-off:before{content:"\f011"}.fa-puzzle-piece:before{content:"\f12e"}.fa-qrcode:before{content:"\f029"}.fa-question-circle:before{content:"\f059"}.fa-reply:before{content:"\f3e5"}.fa-right-left:before{content:"\f362"}.fa-rocket:before{content:"\f135"}.fa-safari:before{content:"\f267"}.fa-share:before{content:"\f064"}.fa-shield-alt:before{content:"\f3ed"}.fa-shield-halved:before{content:"\f3ed"}.fa-signature:before{content:"\f5b7"}.fa-sliders-h:before{content:"\f1de"}.fa-spinner:before{content:"\f110"}.fa-stopwatch:before{content:"\f2f2"}.fa-sync-alt:before{content:"\f2f1"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-trash-can:before{content:"\f2ed"}.fa-triangle-exclamation:before{content:"\f071"}.fa-unlock-alt:before{content:"\f13e"}.fa-user:before{content:"\f007"}.fa-vial:before{content:"\f492"}.fa-windows:before{content:"\f17a"}.fa-xmark:before{content:"\f00d"} \ No newline at end of file diff --git a/assets/fontawesome/subset-icons.json b/assets/fontawesome/subset-icons.json new file mode 100644 index 0000000..f39a509 --- /dev/null +++ b/assets/fontawesome/subset-icons.json @@ -0,0 +1,116 @@ +{ + "icons": [ + "android", + "angle-left", + "angle-right", + "apple", + "arrow-down", + "arrow-left", + "arrow-right", + "arrow-up", + "arrow-up-from-bracket", + "ban", + "bolt", + "camera", + "caret-left", + "caret-right", + "check", + "check-circle", + "check-double", + "chevron-down", + "chevron-left", + "chevron-right", + "chrome", + "circle", + "circle-notch", + "clock", + "code", + "cog", + "cogs", + "comments", + "copy", + "download", + "edge", + "exchange-alt", + "exclamation-triangle", + "eye", + "eye-slash", + "file-arrow-down", + "fingerprint", + "firefox-browser", + "folder-open", + "globe", + "info", + "info-circle", + "key", + "lightbulb", + "link", + "linux", + "lock", + "lock-open", + "microphone-slash", + "network-wired", + "opera", + "paper-plane", + "paperclip", + "paste", + "pen", + "play-circle", + "plus", + "power-off", + "puzzle-piece", + "qrcode", + "question-circle", + "reply", + "right-left", + "rocket", + "safari", + "share", + "shield-alt", + "shield-halved", + "signature", + "sliders-h", + "spinner", + "stopwatch", + "sync-alt", + "times", + "times-circle", + "trash-can", + "triangle-exclamation", + "unlock-alt", + "user", + "vial", + "windows", + "xmark" + ], + "notIcons": [ + "beat", + "border", + "bounce", + "brands", + "duotone", + "fade", + "fallback", + "flip", + "fw", + "inverse", + "lg", + "li", + "light", + "pull-left", + "pull-right", + "pulse", + "regular", + "rotate", + "shake", + "sharp", + "sm", + "solid", + "solid-900", + "spin", + "stack", + "thin", + "ul", + "xs" + ] +} diff --git a/assets/fontawesome/webfonts/fa-brands-400.subset.woff2 b/assets/fontawesome/webfonts/fa-brands-400.subset.woff2 new file mode 100644 index 0000000..5573a0a Binary files /dev/null and b/assets/fontawesome/webfonts/fa-brands-400.subset.woff2 differ diff --git a/assets/fontawesome/webfonts/fa-regular-400.subset.woff2 b/assets/fontawesome/webfonts/fa-regular-400.subset.woff2 new file mode 100644 index 0000000..cd79039 Binary files /dev/null and b/assets/fontawesome/webfonts/fa-regular-400.subset.woff2 differ diff --git a/assets/fontawesome/webfonts/fa-solid-900.subset.woff2 b/assets/fontawesome/webfonts/fa-solid-900.subset.woff2 new file mode 100644 index 0000000..7ec4b7f Binary files /dev/null and b/assets/fontawesome/webfonts/fa-solid-900.subset.woff2 differ diff --git a/assets/fonts/inter/files/inter-latin-500.woff2 b/assets/fonts/inter/files/inter-latin-500.woff2 deleted file mode 100644 index d15208d..0000000 Binary files a/assets/fonts/inter/files/inter-latin-500.woff2 and /dev/null differ diff --git a/assets/fonts/inter/files/inter-latin-600.woff2 b/assets/fonts/inter/files/inter-latin-600.woff2 deleted file mode 100644 index d15208d..0000000 Binary files a/assets/fonts/inter/files/inter-latin-600.woff2 and /dev/null differ diff --git a/assets/fonts/inter/files/inter-latin-700.woff2 b/assets/fonts/inter/files/inter-latin-700.woff2 deleted file mode 100644 index d15208d..0000000 Binary files a/assets/fonts/inter/files/inter-latin-700.woff2 and /dev/null differ diff --git a/assets/fonts/inter/files/inter-latin-800.woff2 b/assets/fonts/inter/files/inter-latin-800.woff2 deleted file mode 100644 index d15208d..0000000 Binary files a/assets/fonts/inter/files/inter-latin-800.woff2 and /dev/null differ diff --git a/assets/fonts/inter/files/inter-latin-ext-500.woff2 b/assets/fonts/inter/files/inter-latin-ext-500.woff2 deleted file mode 100644 index 479d010..0000000 Binary files a/assets/fonts/inter/files/inter-latin-ext-500.woff2 and /dev/null differ diff --git a/assets/fonts/inter/files/inter-latin-ext-600.woff2 b/assets/fonts/inter/files/inter-latin-ext-600.woff2 deleted file mode 100644 index 479d010..0000000 Binary files a/assets/fonts/inter/files/inter-latin-ext-600.woff2 and /dev/null differ diff --git a/assets/fonts/inter/files/inter-latin-ext-700.woff2 b/assets/fonts/inter/files/inter-latin-ext-700.woff2 deleted file mode 100644 index 479d010..0000000 Binary files a/assets/fonts/inter/files/inter-latin-ext-700.woff2 and /dev/null differ diff --git a/assets/fonts/inter/files/inter-latin-ext-800.woff2 b/assets/fonts/inter/files/inter-latin-ext-800.woff2 deleted file mode 100644 index 479d010..0000000 Binary files a/assets/fonts/inter/files/inter-latin-ext-800.woff2 and /dev/null differ diff --git a/assets/fonts/inter/files/inter-latin-ext-400.woff2 b/assets/fonts/inter/files/inter-latin-ext.woff2 similarity index 100% rename from assets/fonts/inter/files/inter-latin-ext-400.woff2 rename to assets/fonts/inter/files/inter-latin-ext.woff2 diff --git a/assets/fonts/inter/files/inter-latin-400.woff2 b/assets/fonts/inter/files/inter-latin.woff2 similarity index 100% rename from assets/fonts/inter/files/inter-latin-400.woff2 rename to assets/fonts/inter/files/inter-latin.woff2 diff --git a/assets/fonts/inter/inter.css b/assets/fonts/inter/inter.css index 256e8c7..32baa84 100644 --- a/assets/fonts/inter/inter.css +++ b/assets/fonts/inter/inter.css @@ -1,93 +1,33 @@ -/* Inter — self-hosted (latin + latin-ext subsets, weights 400/500/600/700/800). - Generated from Google Fonts css2 to remove the third-party fonts.gstatic.com - dependency (privacy) and ship compact woff2 instead of full TTF. */ +/* Inter — self-hosted (latin + latin-ext subsets), served from this origin so the page + makes no request to fonts.gstatic.com. + + Two files, not ten. This used to declare five weights per subset — 400, 500, 600, 700, + 800 — each pointing at its own URL, and the browser dutifully fetched five of them: + 245 KB, the second largest thing on the page after the app bundle. All five were the + same file. Inter here is a variable font with a wght axis from 100 to 900, so one file + answers for every weight; the five names were copies of it. + + Declaring the range instead of a single value is what says so. Rendering is unchanged: + measured at 100px, "Handgloves" comes out 559.7 / 581.6 / 590.5 px at weights 400 / 700 + / 800 under either spelling, because the axis was already being applied — the five + files were never five weights, only five downloads. */ + /* latin-ext */ @font-face { font-family: 'Inter'; font-style: normal; - font-weight: 400; + font-weight: 100 900; font-display: swap; - src: url(files/inter-latin-ext-400.woff2) format('woff2'); + src: url(files/inter-latin-ext.woff2) format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; } + /* latin */ @font-face { font-family: 'Inter'; font-style: normal; - font-weight: 400; + font-weight: 100 900; font-display: swap; - src: url(files/inter-latin-400.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} -/* latin-ext */ -@font-face { - font-family: 'Inter'; - font-style: normal; - font-weight: 500; - font-display: swap; - src: url(files/inter-latin-ext-500.woff2) format('woff2'); - unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; -} -/* latin */ -@font-face { - font-family: 'Inter'; - font-style: normal; - font-weight: 500; - font-display: swap; - src: url(files/inter-latin-500.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} -/* latin-ext */ -@font-face { - font-family: 'Inter'; - font-style: normal; - font-weight: 600; - font-display: swap; - src: url(files/inter-latin-ext-600.woff2) format('woff2'); - unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; -} -/* latin */ -@font-face { - font-family: 'Inter'; - font-style: normal; - font-weight: 600; - font-display: swap; - src: url(files/inter-latin-600.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} -/* latin-ext */ -@font-face { - font-family: 'Inter'; - font-style: normal; - font-weight: 700; - font-display: swap; - src: url(files/inter-latin-ext-700.woff2) format('woff2'); - unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; -} -/* latin */ -@font-face { - font-family: 'Inter'; - font-style: normal; - font-weight: 700; - font-display: swap; - src: url(files/inter-latin-700.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} -/* latin-ext */ -@font-face { - font-family: 'Inter'; - font-style: normal; - font-weight: 800; - font-display: swap; - src: url(files/inter-latin-ext-800.woff2) format('woff2'); - unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; -} -/* latin */ -@font-face { - font-family: 'Inter'; - font-style: normal; - font-weight: 800; - font-display: swap; - src: url(files/inter-latin-800.woff2) format('woff2'); + src: url(files/inter-latin.woff2) format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } diff --git a/assets/tailwind.css b/assets/tailwind.css index 7718fec..6f2f5b0 100644 --- a/assets/tailwind.css +++ b/assets/tailwind.css @@ -1 +1 @@ -*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--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;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--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: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--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;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--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: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.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}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#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]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media (min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media (min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media (min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media (min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media (min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.bottom-0{bottom:0}.bottom-4{bottom:1rem}.end-0{inset-inline-end:0}.end-4{inset-inline-end:1rem}.left-1\/2{left:50%}.left-4{left:1rem}.right-4{right:1rem}.start-0{inset-inline-start:0}.top-0{top:0}.top-1\/2{top:50%}.top-4{top:1rem}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-top:.25rem}.mb-1,.my-1{margin-bottom:.25rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.me-1{margin-inline-end:.25rem}.me-2{margin-inline-end:.5rem}.me-3{margin-inline-end:.75rem}.me-4{margin-inline-end:1rem}.ms-2{margin-inline-start:.5rem}.ms-6{margin-inline-start:1.5rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-16{margin-top:4rem}.mt-20{margin-top:5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-10{height:2.5rem}.h-12{height:3rem}.h-16{height:4rem}.h-28{height:7rem}.h-8{height:2rem}.h-80{height:20rem}.h-9{height:2.25rem}.h-\[420px\]{height:420px}.max-h-\[80vh\]{max-height:80vh}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-12{width:3rem}.w-28{width:7rem}.w-4{width:1rem}.w-72{width:18rem}.w-8{width:2rem}.w-full{width:100%}.min-w-\[160px\]{min-width:160px}.min-w-\[180px\]{min-width:180px}.min-w-\[240px\]{min-width:240px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.max-w-6xl{max-width:72rem}.max-w-7xl{max-width:80rem}.max-w-\[78vw\]{max-width:78vw}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.grow{flex-grow:1}.border-collapse{border-collapse:collapse}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform: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))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-x-full{--tw-translate-x:100%}.transform,.translate-x-full{transform: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))}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-12{gap:3rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.self-center{align-self:center}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-blue-500\/20{border-color:rgba(59,130,246,.2)}.border-gray-500\/20{border-color:hsla(220,9%,46%,.2)}.border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity,1))}.border-gray-600\/30{border-color:rgba(75,85,99,.3)}.border-gray-700\/30{border-color:rgba(55,65,81,.3)}.border-green-500\/20{border-color:rgba(34,197,94,.2)}.border-orange-500\/20{border-color:rgba(249,115,22,.2)}.border-purple-500\/20{border-color:rgba(168,85,247,.2)}.border-purple-500\/30{border-color:rgba(168,85,247,.3)}.border-red-500\/20{border-color:rgba(239,68,68,.2)}.border-yellow-500\/20{border-color:rgba(234,179,8,.2)}.bg-\[rgb\(20_20_20_\/50\%\)\]{background-color:hsla(0,0%,8%,.5)}.bg-black\/20{background-color:rgba(0,0,0,.2)}.bg-black\/30{background-color:rgba(0,0,0,.3)}.bg-black\/50{background-color:rgba(0,0,0,.5)}.bg-black\/80{background-color:rgba(0,0,0,.8)}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-blue-500\/10{background-color:rgba(59,130,246,.1)}.bg-blue-500\/90{background-color:rgba(59,130,246,.9)}.bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity,1))}.bg-gray-500\/10{background-color:hsla(220,9%,46%,.1)}.bg-gray-500\/20{background-color:hsla(220,9%,46%,.2)}.bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.bg-gray-700\/50{background-color:rgba(55,65,81,.5)}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.bg-gray-800\/50{background-color:rgba(31,41,55,.5)}.bg-gray-900\/30{background-color:rgba(17,24,39,.3)}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.bg-green-500\/10{background-color:rgba(34,197,94,.1)}.bg-green-500\/90{background-color:rgba(34,197,94,.9)}.bg-neutral-900{--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity,1))}.bg-orange-500\/10{background-color:rgba(249,115,22,.1)}.bg-purple-500\/10{background-color:rgba(168,85,247,.1)}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-red-500\/10{background-color:rgba(239,68,68,.1)}.bg-red-500\/20{background-color:rgba(239,68,68,.2)}.bg-red-900\/50{background-color:rgba(127,29,29,.5)}.bg-transparent{background-color:transparent}.bg-white\/20{background-color:hsla(0,0%,100%,.2)}.bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(234 179 8/var(--tw-bg-opacity,1))}.bg-yellow-500\/10{background-color:rgba(234,179,8,.1)}.bg-yellow-500\/90{background-color:rgba(234,179,8,.9)}.bg-gradient-to-b{background-image:linear-gradient(to bottom,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.bg-gradient-to-t{background-image:linear-gradient(to top,var(--tw-gradient-stops))}.from-\[\#1f1f1f\]\/90{--tw-gradient-from:rgba(31,31,31,.9) var(--tw-gradient-from-position);--tw-gradient-to:rgba(31,31,31,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-gray-800\/20{--tw-gradient-from:rgba(31,41,55,.2) var(--tw-gradient-from-position);--tw-gradient-to:rgba(31,41,55,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.to-gray-900\/20{--tw-gradient-to:rgba(17,24,39,.2) var(--tw-gradient-to-position)}.to-transparent{--tw-gradient-to:transparent var(--tw-gradient-to-position)}.fill-blue-500{fill:#3b82f6}.fill-white{fill:#fff}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-14{padding-top:3.5rem;padding-bottom:3.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.text-center{text-align:center}.text-start{text-align:start}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-\[3rem\]{font-size:3rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.italic{font-style:italic}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.leading-tight{line-height:1.25}.tracking-\[0\.3em\]{letter-spacing:.3em}.tracking-wide{letter-spacing:.025em}.text-amber-300{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}.text-blue-200{--tw-text-opacity:1;color:rgb(191 219 254/var(--tw-text-opacity,1))}.text-blue-300{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-cyan-300{--tw-text-opacity:1;color:rgb(103 232 249/var(--tw-text-opacity,1))}.text-cyan-400{--tw-text-opacity:1;color:rgb(34 211 238/var(--tw-text-opacity,1))}.text-gray-200{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity,1))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-green-200{--tw-text-opacity:1;color:rgb(187 247 208/var(--tw-text-opacity,1))}.text-green-300{--tw-text-opacity:1;color:rgb(134 239 172/var(--tw-text-opacity,1))}.text-green-400{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.text-orange-200{--tw-text-opacity:1;color:rgb(254 215 170/var(--tw-text-opacity,1))}.text-orange-300{--tw-text-opacity:1;color:rgb(253 186 116/var(--tw-text-opacity,1))}.text-orange-400{--tw-text-opacity:1;color:rgb(251 146 60/var(--tw-text-opacity,1))}.text-orange-500{--tw-text-opacity:1;color:rgb(249 115 22/var(--tw-text-opacity,1))}.text-purple-300{--tw-text-opacity:1;color:rgb(216 180 254/var(--tw-text-opacity,1))}.text-purple-400{--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity,1))}.text-red-200{--tw-text-opacity:1;color:rgb(254 202 202/var(--tw-text-opacity,1))}.text-red-300{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-sky-300{--tw-text-opacity:1;color:rgb(125 211 252/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/10{color:hsla(0,0%,100%,.1)}.text-yellow-200{--tw-text-opacity:1;color:rgb(254 240 138/var(--tw-text-opacity,1))}.text-yellow-300{--tw-text-opacity:1;color:rgb(253 224 71/var(--tw-text-opacity,1))}.text-yellow-400{--tw-text-opacity:1;color:rgb(250 204 21/var(--tw-text-opacity,1))}.text-yellow-600{--tw-text-opacity:1;color:rgb(202 138 4/var(--tw-text-opacity,1))}.line-through{text-decoration-line:line-through}.placeholder-gray-500::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(107 114 128/var(--tw-placeholder-opacity,1))}.placeholder-gray-500::placeholder{--tw-placeholder-opacity:1;color:rgb(107 114 128/var(--tw-placeholder-opacity,1))}.opacity-0{opacity:0}.opacity-60{opacity:.6}.opacity-90{opacity:.9}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-2xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.outline{outline-style:solid}.ring{--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(3px + 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)}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px)}.backdrop-blur-md,.backdrop-blur-sm{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-150,.transition-transform{transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.\[checksum\:4\]{checksum:4}.\[data\:variable\]{data:variable}.\[name\:4\]{name:4}.\[size\:4\]{size:4}.hover\:bg-\[rgb\(20_20_20_\/30\%\)\]:hover{background-color:hsla(0,0%,8%,.3)}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.hover\:bg-emerald-600:hover{--tw-bg-opacity:1;background-color:rgb(5 150 105/var(--tw-bg-opacity,1))}.hover\:bg-gray-500:hover{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity,1))}.hover\:bg-gray-700\/40:hover{background-color:rgba(55,65,81,.4)}.hover\:bg-gray-700\/50:hover{background-color:rgba(55,65,81,.5)}.hover\:bg-green-600\/40:hover{background-color:rgba(22,163,74,.4)}.hover\:bg-orange-500\/40:hover{background-color:rgba(249,115,22,.4)}.hover\:bg-red-500\/20:hover{background-color:rgba(239,68,68,.2)}.hover\:bg-red-500\/30:hover{background-color:rgba(239,68,68,.3)}.hover\:bg-red-600\/40:hover{background-color:rgba(220,38,38,.4)}.hover\:bg-white\/30:hover{background-color:hsla(0,0%,100%,.3)}.hover\:bg-yellow-600\/40:hover{background-color:rgba(202,138,4,.4)}.hover\:text-gray-200:hover{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity,1))}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.hover\:text-green-300:hover{--tw-text-opacity:1;color:rgb(134 239 172/var(--tw-text-opacity,1))}.hover\:text-green-400:hover{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.hover\:text-red-300:hover{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.focus\:border-purple-400:focus{--tw-border-opacity:1;border-color:rgb(192 132 252/var(--tw-border-opacity,1))}.focus\:border-purple-500\/40:focus{border-color:rgba(168,85,247,.4)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.active\:bg-gray-700\/60:active{background-color:rgba(55,65,81,.6)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-60:disabled{opacity:.6}.group:hover .group-hover\:scale-105{--tw-scale-x:1.05;--tw-scale-y:1.05;transform: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))}.group:hover .group-hover\:opacity-100{opacity:1}@media (min-width:640px){.sm\:mb-3{margin-bottom:.75rem}.sm\:block{display:block}.sm\:inline{display:inline}.sm\:flex{display:flex}.sm\:h-12{height:3rem}.sm\:w-12{width:3rem}.sm\:gap-4{gap:1rem}.sm\:p-4{padding:1rem}.sm\:py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width:768px){.md\:hidden{display:none}.md\:h-\[32rem\]{height:32rem}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width:1024px){.lg\:col-span-2{grid-column:span 2/span 2}.lg\:col-span-3{grid-column:span 3/span 3}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}} \ No newline at end of file +*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--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;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--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: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--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;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--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: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.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}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#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]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media (min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media (min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media (min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media (min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media (min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.bottom-4{bottom:1rem}.end-0{inset-inline-end:0}.end-4{inset-inline-end:1rem}.left-1\/2{left:50%}.left-4{left:1rem}.right-4{right:1rem}.top-0{top:0}.top-1\/2{top:50%}.top-4{top:1rem}.isolate{isolation:isolate}.z-10{z-index:10}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-top:.25rem}.mb-1,.my-1{margin-bottom:.25rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.me-1{margin-inline-end:.25rem}.me-2{margin-inline-end:.5rem}.me-3{margin-inline-end:.75rem}.me-4{margin-inline-end:1rem}.ms-2{margin-inline-start:.5rem}.ms-6{margin-inline-start:1.5rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-20{margin-top:5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-10{height:2.5rem}.h-12{height:3rem}.h-28{height:7rem}.h-8{height:2rem}.h-80{height:20rem}.h-9{height:2.25rem}.max-h-\[80vh\]{max-height:80vh}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-12{width:3rem}.w-28{width:7rem}.w-4{width:1rem}.w-8{width:2rem}.w-full{width:100%}.min-w-\[180px\]{min-width:180px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-7xl{max-width:80rem}.max-w-\[78vw\]{max-width:78vw}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform: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))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-x-full{--tw-translate-x:100%}.transform,.translate-x-full{transform: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))}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-6{gap:1.5rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.self-center{align-self:center}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-blue-500\/20{border-color:rgba(59,130,246,.2)}.border-gray-500\/20{border-color:hsla(220,9%,46%,.2)}.border-gray-600\/30{border-color:rgba(75,85,99,.3)}.border-green-500\/20{border-color:rgba(34,197,94,.2)}.border-orange-500\/20{border-color:rgba(249,115,22,.2)}.border-purple-500\/20{border-color:rgba(168,85,247,.2)}.border-purple-500\/30{border-color:rgba(168,85,247,.3)}.border-red-500\/20{border-color:rgba(239,68,68,.2)}.border-yellow-500\/20{border-color:rgba(234,179,8,.2)}.bg-black\/20{background-color:rgba(0,0,0,.2)}.bg-black\/30{background-color:rgba(0,0,0,.3)}.bg-black\/50{background-color:rgba(0,0,0,.5)}.bg-black\/80{background-color:rgba(0,0,0,.8)}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-blue-500\/10{background-color:rgba(59,130,246,.1)}.bg-blue-500\/90{background-color:rgba(59,130,246,.9)}.bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity,1))}.bg-gray-500\/10{background-color:hsla(220,9%,46%,.1)}.bg-gray-500\/20{background-color:hsla(220,9%,46%,.2)}.bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.bg-gray-700\/50{background-color:rgba(55,65,81,.5)}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.bg-gray-800\/50{background-color:rgba(31,41,55,.5)}.bg-gray-900\/30{background-color:rgba(17,24,39,.3)}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.bg-green-500\/10{background-color:rgba(34,197,94,.1)}.bg-green-500\/90{background-color:rgba(34,197,94,.9)}.bg-orange-500\/10{background-color:rgba(249,115,22,.1)}.bg-purple-500\/10{background-color:rgba(168,85,247,.1)}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-red-500\/10{background-color:rgba(239,68,68,.1)}.bg-red-500\/20{background-color:rgba(239,68,68,.2)}.bg-red-900\/50{background-color:rgba(127,29,29,.5)}.bg-white\/20{background-color:hsla(0,0%,100%,.2)}.bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(234 179 8/var(--tw-bg-opacity,1))}.bg-yellow-500\/10{background-color:rgba(234,179,8,.1)}.bg-yellow-500\/90{background-color:rgba(234,179,8,.9)}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.text-center{text-align:center}.text-start{text-align:start}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-\[3rem\]{font-size:3rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.italic{font-style:italic}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-\[0\.3em\]{letter-spacing:.3em}.tracking-wide{letter-spacing:.025em}.text-amber-300{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}.text-blue-200{--tw-text-opacity:1;color:rgb(191 219 254/var(--tw-text-opacity,1))}.text-blue-300{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-gray-200{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity,1))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-green-400{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.text-orange-200{--tw-text-opacity:1;color:rgb(254 215 170/var(--tw-text-opacity,1))}.text-orange-300{--tw-text-opacity:1;color:rgb(253 186 116/var(--tw-text-opacity,1))}.text-orange-400{--tw-text-opacity:1;color:rgb(251 146 60/var(--tw-text-opacity,1))}.text-orange-500{--tw-text-opacity:1;color:rgb(249 115 22/var(--tw-text-opacity,1))}.text-purple-300{--tw-text-opacity:1;color:rgb(216 180 254/var(--tw-text-opacity,1))}.text-purple-400{--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-sky-300{--tw-text-opacity:1;color:rgb(125 211 252/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/10{color:hsla(0,0%,100%,.1)}.text-yellow-400{--tw-text-opacity:1;color:rgb(250 204 21/var(--tw-text-opacity,1))}.text-yellow-600{--tw-text-opacity:1;color:rgb(202 138 4/var(--tw-text-opacity,1))}.line-through{text-decoration-line:line-through}.placeholder-gray-500::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(107 114 128/var(--tw-placeholder-opacity,1))}.placeholder-gray-500::placeholder{--tw-placeholder-opacity:1;color:rgb(107 114 128/var(--tw-placeholder-opacity,1))}.opacity-0{opacity:0}.opacity-90{opacity:.9}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-2xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.ring{--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(3px + 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)}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px)}.backdrop-blur-md,.backdrop-blur-sm{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-150,.transition-transform{transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.\[checksum\:4\]{checksum:4}.\[data\:variable\]{data:variable}.\[name\:4\]{name:4}.\[size\:4\]{size:4}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.hover\:bg-emerald-600:hover{--tw-bg-opacity:1;background-color:rgb(5 150 105/var(--tw-bg-opacity,1))}.hover\:bg-gray-500:hover{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity,1))}.hover\:bg-gray-700\/40:hover{background-color:rgba(55,65,81,.4)}.hover\:bg-gray-700\/50:hover{background-color:rgba(55,65,81,.5)}.hover\:bg-red-500\/20:hover{background-color:rgba(239,68,68,.2)}.hover\:bg-red-500\/30:hover{background-color:rgba(239,68,68,.3)}.hover\:bg-white\/30:hover{background-color:hsla(0,0%,100%,.3)}.hover\:text-gray-200:hover{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity,1))}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.hover\:text-green-300:hover{--tw-text-opacity:1;color:rgb(134 239 172/var(--tw-text-opacity,1))}.hover\:text-green-400:hover{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.hover\:text-red-300:hover{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.focus\:border-purple-400:focus{--tw-border-opacity:1;border-color:rgb(192 132 252/var(--tw-border-opacity,1))}.focus\:border-purple-500\/40:focus{border-color:rgba(168,85,247,.4)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.active\:bg-gray-700\/60:active{background-color:rgba(55,65,81,.6)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-60:disabled{opacity:.6}.group:hover .group-hover\:scale-105{--tw-scale-x:1.05;--tw-scale-y:1.05;transform: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))}.group:hover .group-hover\:opacity-100{opacity:1}@media (min-width:640px){.sm\:block{display:block}.sm\:inline{display:inline}.sm\:flex{display:flex}.sm\:py-2\.5{padding-top:.625rem;padding-bottom:.625rem}}@media (min-width:768px){.md\:h-\[32rem\]{height:32rem}} \ No newline at end of file diff --git a/de/index.html b/de/index.html index 533e6d1..49c288a 100644 --- a/de/index.html +++ b/de/index.html @@ -30,7 +30,7 @@ - + @@ -96,7 +96,7 @@ - + @@ -105,7 +105,7 @@ - + @@ -121,8 +121,7 @@ SecureBit.chat - Privater, verschlüsselter Messenger - - + @@ -179,13 +178,27 @@ { "@context": "https://schema.org", "@graph": [ + { + "@type": "Organization", + "@id": "https://securebit.chat/#organization", + "name": "SecureBit.chat", + "url": "https://securebit.chat/", + "logo": "https://securebit.chat/logo/icon-512x512.png", + "sameAs": [ + "https://github.com/SecureBitChat/securebit-chat", + "https://snapcraft.io/securebit-chat" + ] + }, { "@type": "WebSite", "@id": "https://securebit.chat/#website", "name": "SecureBit.chat", "url": "https://securebit.chat/", "description": "Ende-zu-Ende-verschlüsselter Peer-to-Peer-Chat, der vollständig im Browser läuft.", - "inLanguage": "de" + "inLanguage": "de", + "publisher": { + "@id": "https://securebit.chat/#organization" + } }, { "@type": "WebApplication", @@ -222,55 +235,235 @@ - + - - - - - - - - - - - - - - - + + + + + + - + - + + + - - - - + + + -
- - +
+ + + + +
+
+
+

SecureBit.chat

+

Eine direkte Leitung,
die nur Sie beide lesen können.

+

Die Schlüssel entstehen auf Ihrem Gerät und werden direkt zwischen den Geräten ausgetauscht. Keine Konten, keine Server, die Ihre Nachrichten speichern.

+
+
+

Was uns unterscheidet

+

Warum SecureBit einzigartig ist

+
    +
  • +

    Mehrschichtiger Verschlüsselungskern

    +

    ECDH-P-384-Schlüsselaustausch, AES-256-GCM-Nutzdaten, ECDSA-Signaturen und vollständige ASN.1-Validierung - zu einer gehärteten Pipeline verbunden.

    +
    • ECDH P-384
    • AES-256-GCM
    • ECDSA
    • ASN.1
    +
  • +
  • +

    Reines P2P über WebRTC

    +

    Nachrichten laufen über WebRTC direkt von Gerät zu Gerät. Kein Relay hält Ihre Daten - der Server hilft zwei Teilnehmern nur, sich zu finden.

    +
    • DTLS 1.3
    • Kein Relay
    +
  • +
  • +

    Perfekte Forward Secrecy

    +

    Sitzungsschlüssel wechseln fortlaufend und werden nach Gebrauch verworfen. Ein einzelner kompromittierter Schlüssel öffnet damit niemals frühere Gespräche.

    +
    • Ephemere Schlüssel
    • Automatischer Wechsel
    +
  • +
  • +

    Verschleierung des Datenverkehrs

    +

    Paketgrößen und Zeitabstände werden aufgefüllt und zufällig verändert. Metadatenmuster bleiben damit verborgen, auch für jemanden, der die Leitung beobachtet.

    +
    • Paket-Padding
    • Zeit-Jitter
    +
  • +
  • +

    Keinerlei Datenerfassung

    +

    Keine Konten, keine Protokolle, keine gespeicherten Nachrichten. Auf einem Server liegt nichts, was durchsickern, beschlagnahmt oder verkauft werden könnte.

    +
    • Keine Konten
    • Keine Protokolle
    +
  • +
+
+
+

Entwicklungs-Roadmap

+

Die Entwicklung von SecureBit

+

Vom ersten Prototyp zu einem quantensicheren, dezentralen Netzwerk - mit vollständiger ASN.1-Validierung auf jeder Ebene.

+
    +
  1. +

    Entwicklungsbeginn

    + Anfang 2025 +

    Idee, Prototyp und Aufbau der Infrastruktur

    +
  2. +
  3. +

    Alpha-Release

    + Frühjahr 2025 +

    Erste öffentliche Alpha: einfacher Chat und Schlüsselaustausch

    +
  4. +
  5. +

    Sicherheit gehärtet

    + Sommer 2025 +

    Sicherheit gestärkt, stabiler Zweig veröffentlicht

    +
  6. +
  7. +

    Skalierung & Stabilität

    + Herbst 2025 +

    Skalierung des Netzwerks und mehr Stabilität

    +
  8. +
  9. +

    Privatsphäre zuerst

    + Winter 2025 +

    Schwerpunkt Privatsphäre: Metadaten minimieren

    +
  10. +
  11. +

    Enhanced Security Edition

    + Ende 2025 +

    18-schichtige Kryptografie auf militärischem Niveau mit vollständiger ASN.1-Validierung

    +
  12. +
  13. +

    Desktop Edition

    + Anfang 2026 +

    Native Desktop-Apps für Windows, macOS und Linux

    +
  14. +
  15. +

    Sichere Sprache & Anrufe

    + Anfang 2026 +

    Verschlüsselte Sprachnachrichten, Audio- und Videoanrufe

    +
  16. +
  17. +

    Gruppenkommunikation

    + Jetzt +

    Gruppenchats ohne Verlust der Privatsphäre

    +
  18. +
  19. +

    Mobile Edition

    + Q2 2027 +

    Native Apps für iOS und Android

    +
  20. +
  21. +

    Quantensichere Edition

    + Q4 2027 +

    Schutz vor Quantencomputern

    +
  22. +
  23. +

    Dezentrales Netzwerk

    + 2028 +

    Vollständig dezentrales Netzwerk

    +
  24. +
  25. +

    KI-Assistent für Privatsphäre

    + 2028+ +

    KI für Privatsphäre und Sicherheit

    +
  26. +
+
+
+

Documentation

+ +
+
+

Gestalten Sie die Zukunft der Privatsphäre mit

+

SecureBit wächst durch seine Community. Ihre Ideen und Ihr Feedback prägen die Zukunft sicherer Kommunikation - offen entwickelt, mit vollständiger ASN.1-Validierung von Ende zu Ende.

+

GitHub-Repository

+
+
+
+
+ + - - - - - + + + + \ No newline at end of file diff --git a/deploy/nginx.conf b/deploy/nginx.conf index 70390c1..0cfee26 100644 --- a/deploy/nginx.conf +++ b/deploy/nginx.conf @@ -1,7 +1,7 @@ # nginx config for serving SecureBit.chat (static PWA) on Fly.io. # Mirrors the behavior of the Apache .htaccess: correct JS MIME for ES modules # (.jsx/.mjs), no-cache for the app shell / service worker / versioning files, -# long-immutable cache for hashed/static assets, security headers, SPA fallback. +# long-immutable cache for hashed/static assets, security headers, honest 404s. worker_processes auto; events { worker_connections 1024; } @@ -40,10 +40,16 @@ http { # one level avoids nginx's header-inheritance reset between blocks. map $uri $sb_cache { default "public, max-age=31536000, immutable"; - ~^/index\.html$ "no-cache, no-store, must-revalidate"; - ~^/$ "no-cache, no-store, must-revalidate"; + # Quoted because nginx reads a bare { as the start of a block: an unquoted + # regex with a repetition count fails the config at boot, not at request time. + # Both anchors matter. These patterns used to be ~^/index\.html$ and ~^/$, + # which match the English shell and nothing else — so /de/, /ru/index.html and + # every other localized page fell through to the one-year immutable default + # below. A visitor who opened a localized page kept that exact HTML, and the + # ?v= stamps inside it, for a year: no release could reach them. + "~^/([a-z]{2}/)?(index\.html)?$" "no-cache, no-store, must-revalidate"; + "~^/([a-z]{2}/)?manifest\.json$" "no-cache, no-store, must-revalidate"; ~^/sw\.js$ "no-cache, no-store, must-revalidate"; - ~^/manifest\.json$ "no-cache, no-store, must-revalidate"; ~^/meta\.json$ "no-cache, no-store, must-revalidate"; # Operator ICE/TURN config: must never be cached long, or the browser # locks onto a stale server list (default was max-age=1y immutable). @@ -65,28 +71,6 @@ http { ~^/sitemap\.xml$ "public, max-age=3600"; } - # Which app shell an unmatched navigation falls back to. A request under /de/ must - # land on /de/index.html, not the English one — otherwise every deep link into a - # localized page silently switches language. The entries between the markers are - # rewritten by scripts/build-i18n.js from locales/site.json. - map $uri $sb_shell { - default /index.html; - # BEGIN generated locale shells - ~^/de/ /de/index.html; - ~^/fr/ /fr/index.html; - ~^/es/ /es/index.html; - ~^/uk/ /uk/index.html; - ~^/ru/ /ru/index.html; - ~^/zh/ /zh/index.html; - ~^/ko/ /ko/index.html; - ~^/hi/ /hi/index.html; - ~^/ar/ /ar/index.html; - ~^/he/ /he/index.html; - ~^/fa/ /fa/index.html; - ~^/ur/ /ur/index.html; - # END generated locale shells - } - # CDN-Cache-Control is read by Cloudflare (and other CDNs) *independently* of the # browser Cache-Control above, and takes precedence at the edge. We force "no-store" # for the app shell, service worker and version files so a CDN can never serve a @@ -95,10 +79,11 @@ http { # so immutable hashed assets keep being edge-cached normally for performance. map $uri $sb_cdn_cache { default ""; - ~^/index\.html$ "no-store"; - ~^/$ "no-store"; + # Same anchoring fix as above: Cloudflare was edge-caching the localized + # shells for a year too. + "~^/([a-z]{2}/)?(index\.html)?$" "no-store"; + "~^/([a-z]{2}/)?manifest\.json$" "no-store"; ~^/sw\.js$ "no-store"; - ~^/manifest\.json$ "no-store"; ~^/meta\.json$ "no-store"; ~^/config/ice-servers\.js$ "no-store"; ~^/dist/ "no-store"; @@ -135,10 +120,19 @@ http { try_files $uri =404; } - # SPA-style fallback so unknown navigation routes still load the app shell. + # The app has no client-side routes: every real address is either a file, the + # root, or a locale directory, and $uri/ resolves /de/ through the index + # directive. So an unknown path is a typo or a scanner probe, not a route. + # Answering those with the app shell under 200 OK made every one of them an + # indexable "page" — an infinite URL space that Search Console reports as soft + # 404s and duplicates, spending crawl budget on addresses that do not exist. location / { - try_files $uri $uri/ $sb_shell; + try_files $uri $uri/ =404; } + + # A real page for a real 404, rather than nginx's own. Served from the root, so + # the block above resolves it as an ordinary file; the 404 status is preserved. + error_page 404 /404.html; } # One canonical hostname. www.securebit.chat has its own Fly certificate (so diff --git a/dist/app-boot.js b/dist/app-boot.js index 5f511bc..c8dc610 100644 --- a/dist/app-boot.js +++ b/dist/app-boot.js @@ -1,20109 +1,12 @@ -var __create = Object.create; -var __defProp = Object.defineProperty; -var __getOwnPropDesc = Object.getOwnPropertyDescriptor; -var __getOwnPropNames = Object.getOwnPropertyNames; -var __getProtoOf = Object.getPrototypeOf; -var __hasOwnProp = Object.prototype.hasOwnProperty; -var __commonJS = (cb, mod) => function __require() { - try { - return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; - } catch (e) { - throw mod = 0, e; - } -}; -var __copyProps = (to, from, except, desc) => { - if (from && typeof from === "object" || typeof from === "function") { - for (let key of __getOwnPropNames(from)) - if (!__hasOwnProp.call(to, key) && key !== except) - __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); - } - return to; -}; -var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( - // If the importer is in node compatibility mode or this is not an ESM - // file that has been converted to a CommonJS file using a Babel- - // compatible transform (i.e. "__esModule" has not been set), then set - // "default" to the CommonJS "module.exports" for node compatibility. - isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, - mod -)); - -// src/notifications/SecureNotificationManager.js -var require_SecureNotificationManager = __commonJS({ - "src/notifications/SecureNotificationManager.js"(exports, module) { - var SecureChatNotificationManager = class { - constructor(config = {}) { - this.permission = typeof Notification !== "undefined" && Notification && typeof Notification.permission === "string" ? Notification.permission : "denied"; - this.isTabActive = this.checkTabActive(); - this.unreadCount = 0; - this.originalTitle = document.title; - this.notificationQueue = []; - this.maxQueueSize = config.maxQueueSize || 5; - this.rateLimitMs = config.rateLimitMs || 2e3; - this.lastNotificationTime = 0; - this.trustedOrigins = config.trustedOrigins || []; - this.isSecureContext = window.isSecureContext; - this.hidden = this.getHiddenProperty(); - this.visibilityChange = this.getVisibilityChangeEvent(); - this.initVisibilityTracking(); - this.initSecurityChecks(); - } - /** - * Initialize security checks and validation - * @private - */ - initSecurityChecks() { - } - /** - * Get hidden property name for cross-browser compatibility - * @returns {string} Hidden property name - * @private - */ - getHiddenProperty() { - if (typeof document.hidden !== "undefined") { - return "hidden"; - } else if (typeof document.msHidden !== "undefined") { - return "msHidden"; - } else if (typeof document.webkitHidden !== "undefined") { - return "webkitHidden"; - } - return "hidden"; - } - /** - * Get visibility change event name for cross-browser compatibility - * @returns {string} Visibility change event name - * @private - */ - getVisibilityChangeEvent() { - if (typeof document.hidden !== "undefined") { - return "visibilitychange"; - } else if (typeof document.msHidden !== "undefined") { - return "msvisibilitychange"; - } else if (typeof document.webkitHidden !== "undefined") { - return "webkitvisibilitychange"; - } - return "visibilitychange"; - } - /** - * Check if tab is currently active using multiple methods - * @returns {boolean} True if tab is active - * @private - */ - checkTabActive() { - if (this.hidden && typeof document[this.hidden] !== "undefined") { - return !document[this.hidden]; - } - if (typeof document.hasFocus === "function") { - return document.hasFocus(); - } - return true; - } - /** - * Initialize page visibility tracking (Page Visibility API) - * @private - */ - initVisibilityTracking() { - if (typeof document.addEventListener !== "undefined" && typeof document[this.hidden] !== "undefined") { - document.addEventListener(this.visibilityChange, () => { - this.isTabActive = this.checkTabActive(); - if (this.isTabActive) { - this.resetUnreadCount(); - this.clearNotificationQueue(); - } - }); - } - window.addEventListener("focus", () => { - this.isTabActive = this.checkTabActive(); - if (this.isTabActive) { - this.resetUnreadCount(); - } - }); - window.addEventListener("blur", () => { - this.isTabActive = this.checkTabActive(); - }); - window.addEventListener("beforeunload", () => { - this.clearNotificationQueue(); - }); - } - /** - * Request notification permission (BEST PRACTICE: Only call in response to user action) - * Never call on page load! - * @returns {Promise} Permission granted status - */ - async requestPermission() { - if (!this.isSecureContext || !("Notification" in window)) { - return false; - } - if (this.permission === "granted") { - return true; - } - if (this.permission === "denied") { - return false; - } - try { - this.permission = await Notification.requestPermission(); - return this.permission === "granted"; - } catch (error) { - return false; - } - } - /** - * Update page title with unread count - * @private - */ - updateTitle() { - if (this.unreadCount > 0) { - document.title = `(${this.unreadCount}) ${this.originalTitle}`; - } else { - document.title = this.originalTitle; - } - } - /** - * XSS Protection: Sanitize input text - * @param {string} text - Text to sanitize - * @returns {string} Sanitized text - * @private - */ - sanitizeText(text2) { - if (typeof text2 !== "string") { - return ""; - } - const div = document.createElement("div"); - div.textContent = text2; - return div.innerHTML.replace(//g, ">").replace(/"/g, """).replace(/'/g, "'").substring(0, 500); - } - /** - * Validate icon URL (XSS protection) - * @param {string} url - URL to validate - * @returns {string|null} Validated URL or null - * @private - */ - validateIconUrl(url) { - if (!url) return null; - try { - const parsedUrl = new URL(url, window.location.origin); - if (parsedUrl.protocol === "https:" || parsedUrl.protocol === "data:") { - if (this.trustedOrigins.length > 0) { - const isTrusted = this.trustedOrigins.some( - (origin) => parsedUrl.origin === origin - ); - return isTrusted ? parsedUrl.href : null; - } - return parsedUrl.href; - } - return null; - } catch (error) { - return null; - } - } - /** - * Rate limiting for spam protection - * @returns {boolean} Rate limit check passed - * @private - */ - checkRateLimit() { - const now = Date.now(); - if (now - this.lastNotificationTime < this.rateLimitMs) { - return false; - } - this.lastNotificationTime = now; - return true; - } - /** - * Send secure notification - * @param {string} senderName - Name of message sender - * @param {string} message - Message content - * @param {Object} options - Notification options - * @returns {Notification|null} Created notification or null - */ - notify(senderName, message, options = {}) { - if (typeof Notification === "undefined") { - return null; - } - this.isTabActive = this.checkTabActive(); - if (this.isTabActive) { - return null; - } - if (this.permission !== "granted") { - return null; - } - if (!this.checkRateLimit()) { - return null; - } - const safeSenderName = this.sanitizeText(senderName || "Unknown"); - const safeMessage = this.sanitizeText(message || ""); - const safeIcon = this.validateIconUrl(options.icon) || "/logo/icon-192x192.png"; - if (this.notificationQueue.length >= this.maxQueueSize) { - this.clearNotificationQueue(); - } - try { - const notification = new Notification( - `${safeSenderName}`, - { - body: safeMessage.substring(0, 200), - // Length limit - icon: safeIcon, - badge: safeIcon, - tag: `chat-${options.senderId || "unknown"}`, - // Grouping - requireInteraction: false, - // Don't block user - silent: options.silent || false, - // Vibrate only for mobile and if supported - vibrate: navigator.vibrate ? [200, 100, 200] : void 0, - // Safe metadata - data: { - senderId: this.sanitizeText(options.senderId), - timestamp: Date.now() - // Don't include sensitive data! - } - } - ); - this.unreadCount++; - this.updateTitle(); - this.notificationQueue.push(notification); - notification.onclick = (event) => { - event.preventDefault(); - window.focus(); - notification.close(); - if (typeof options.onClick === "function") { - try { - options.onClick(options.senderId); - } catch (error) { - console.error("[Notifications] Error in onClick handler:", error); - } - } - }; - notification.onerror = (event) => { - console.error("[Notifications] Error showing notification:", event); - }; - const autoCloseTimeout = Math.min(options.autoClose || 5e3, 1e4); - setTimeout(() => { - notification.close(); - this.removeFromQueue(notification); - }, autoCloseTimeout); - return notification; - } catch (error) { - console.error("[Notifications] Failed to create notification:", error); - return null; - } - } - /** - * Remove notification from queue - * @param {Notification} notification - Notification to remove - * @private - */ - removeFromQueue(notification) { - const index = this.notificationQueue.indexOf(notification); - if (index > -1) { - this.notificationQueue.splice(index, 1); - } - } - /** - * Clear all notifications - */ - clearNotificationQueue() { - this.notificationQueue.forEach((notification) => { - try { - notification.close(); - } catch (error) { - } - }); - this.notificationQueue = []; - } - /** - * Reset unread counter - */ - resetUnreadCount() { - this.unreadCount = 0; - this.updateTitle(); - } - /** - * Get current status - * @returns {Object} Current notification status - */ - getStatus() { - return { - permission: this.permission, - isTabActive: this.isTabActive, - unreadCount: this.unreadCount, - isSecureContext: this.isSecureContext, - queueSize: this.notificationQueue.length - }; - } - }; - var SecureP2PChat = class { - constructor() { - this.notificationManager = new SecureChatNotificationManager({ - maxQueueSize: 5, - rateLimitMs: 2e3, - trustedOrigins: [ - window.location.origin - // Add other trusted origins for CDN icons - ] - }); - this.dataChannel = null; - this.peerConnection = null; - this.remotePeerName = "Peer"; - this.messageHistory = []; - this.maxHistorySize = 100; - } - /** - * Initialize when user connects - */ - async init() { - } - /** - * Method for manual permission request (called on click) - * @returns {Promise} Permission granted status - */ - async enableNotifications() { - const granted = await this.notificationManager.requestPermission(); - return granted; - } - /** - * Setup DataChannel with security checks - * @param {RTCDataChannel} dataChannel - WebRTC data channel - */ - setupDataChannel(dataChannel) { - if (!dataChannel) { - console.error("[Chat] Invalid DataChannel"); - return; - } - this.dataChannel = dataChannel; - this.dataChannel.onmessage = (event) => { - this.handleIncomingMessage(event.data); - }; - this.dataChannel.onerror = (error) => { - }; - } - /** - * XSS Protection: Validate incoming messages - * @param {string|Object} data - Message data - * @returns {Object|null} Validated message or null - * @private - */ - validateMessage(data) { - try { - const message = typeof data === "string" ? JSON.parse(data) : data; - if (!message || typeof message !== "object") { - throw new Error("Invalid message structure"); - } - if (!message.text || typeof message.text !== "string") { - throw new Error("Invalid message text"); - } - if (message.text.length > 1e4) { - throw new Error("Message too long"); - } - return { - text: message.text, - senderName: message.senderName || "Unknown", - senderId: message.senderId || "unknown", - timestamp: message.timestamp || Date.now(), - senderAvatar: message.senderAvatar || null - }; - } catch (error) { - console.error("[Chat] Message validation failed:", error); - return null; - } - } - /** - * Secure handling of incoming messages - * @param {string|Object} data - Message data - * @private - */ - handleIncomingMessage(data) { - const message = this.validateMessage(data); - if (!message) { - return; - } - this.messageHistory.push(message); - if (this.messageHistory.length > this.maxHistorySize) { - this.messageHistory.shift(); - } - this.displayMessage(message); - this.notificationManager.notify( - message.senderName, - message.text, - { - icon: message.senderAvatar, - senderId: message.senderId, - onClick: (senderId) => { - this.scrollToLatestMessage(); - } - } - ); - if (!this.notificationManager.isTabActive) { - this.playNotificationSound(); - } - } - /** - * XSS Protection: Safe message display - * @param {Object} message - Message to display - * @private - */ - displayMessage(message) { - const container = document.getElementById("messages"); - if (!container) { - return; - } - const messageEl = document.createElement("div"); - messageEl.className = "message"; - const nameEl = document.createElement("strong"); - nameEl.textContent = message.senderName + ": "; - const textEl = document.createElement("span"); - textEl.textContent = message.text; - textEl.style.wordWrap = "break-word"; - textEl.style.overflowWrap = "break-word"; - textEl.style.whiteSpace = "normal"; - const timeEl = document.createElement("small"); - timeEl.textContent = new Date(message.timestamp).toLocaleTimeString(); - messageEl.appendChild(nameEl); - messageEl.appendChild(textEl); - messageEl.appendChild(document.createElement("br")); - messageEl.appendChild(timeEl); - container.appendChild(messageEl); - this.scrollToLatestMessage(); - } - /** - * Safe sound playback - * @private - */ - playNotificationSound() { - try { - const audio = new Audio("/assets/audio/notification.mp3"); - audio.volume = 0.3; - audio.play().catch((error) => { - }); - } catch (error) { - } - } - /** - * Scroll to latest message - * @private - */ - scrollToLatestMessage() { - const container = document.getElementById("messages"); - if (container) { - container.scrollTop = container.scrollHeight; - } - } - /** - * Get status - * @returns {Object} Current chat status - */ - getStatus() { - return { - notifications: this.notificationManager.getStatus(), - messageCount: this.messageHistory.length, - connected: this.dataChannel?.readyState === "open" - }; - } - }; - if (typeof module !== "undefined" && module.exports) { - module.exports = { SecureChatNotificationManager, SecureP2PChat }; - } - if (typeof window !== "undefined") { - window.SecureChatNotificationManager = SecureChatNotificationManager; - window.SecureP2PChat = SecureP2PChat; - } - } -}); - -// src/notifications/NotificationIntegration.js -var require_NotificationIntegration = __commonJS({ - "src/notifications/NotificationIntegration.js"(exports, module) { - var import_SecureNotificationManager = __toESM(require_SecureNotificationManager()); - var NotificationIntegration2 = class { - constructor(webrtcManager) { - this.webrtcManager = webrtcManager; - this.notificationManager = new import_SecureNotificationManager.SecureChatNotificationManager({ - maxQueueSize: 10, - rateLimitMs: 1e3, - // Reduced from 2000ms to 1000ms - trustedOrigins: [ - window.location.origin - // Add other trusted origins for CDN icons - ] - }); - this.isInitialized = false; - this.originalOnMessage = null; - this.originalOnStatusChange = null; - this.processedMessages = /* @__PURE__ */ new Set(); - } - /** - * Initialize notification integration - * @returns {Promise} Initialization success - */ - async init() { - try { - if (this.isInitialized) { - return true; - } - this.originalOnMessage = this.webrtcManager.onMessage; - this.originalOnStatusChange = this.webrtcManager.onStatusChange; - this.webrtcManager.onMessage = (message, type, ...rest) => { - this.handleIncomingMessage(message, type, rest[0]); - if (this.originalOnMessage) { - this.originalOnMessage(message, type, ...rest); - } - }; - this.webrtcManager.onStatusChange = (status) => { - this.handleStatusChange(status); - if (this.originalOnStatusChange) { - this.originalOnStatusChange(status); - } - }; - if (this.webrtcManager.deliverMessageToUI) { - this.originalDeliverMessageToUI = this.webrtcManager.deliverMessageToUI.bind(this.webrtcManager); - this.webrtcManager.deliverMessageToUI = (message, type, ...rest) => { - this.handleIncomingMessage(message, type, rest[0]); - this.originalDeliverMessageToUI(message, type, ...rest); - }; - } - this.isInitialized = true; - return true; - } catch (error) { - return false; - } - } - /** - * Handle incoming messages and trigger notifications - * @param {*} message - Message content - * @param {string} type - Message type - * @private - */ - handleIncomingMessage(message, type, meta) { - try { - const messageKey = `${type}:${typeof message === "string" ? message : JSON.stringify(message)}`; - if (this.processedMessages.has(messageKey)) { - return; - } - this.processedMessages.add(messageKey); - if (this.processedMessages.size > 100) { - const messagesArray = Array.from(this.processedMessages); - this.processedMessages.clear(); - messagesArray.slice(-50).forEach((msg) => this.processedMessages.add(msg)); - } - if (type === "system" || type === "file-transfer" || type === "heartbeat") { - return; - } - const messageInfo = this.extractMessageInfo(message, type); - if (!messageInfo) { - return; - } - const isEphemeral = !!meta && typeof meta === "object" && (meta.once === true || Number.isFinite(meta.ttl) && meta.ttl > 0); - const notificationText = isEphemeral ? "Sent you a private message" : messageInfo.text; - const notificationResult = this.notificationManager.notify( - messageInfo.senderName, - notificationText, - { - icon: messageInfo.senderAvatar, - senderId: messageInfo.senderId, - onClick: (senderId) => { - this.focusChatWindow(); - } - } - ); - } catch (error) { - } - } - /** - * Handle status changes - * @param {string} status - Connection status - * @private - */ - handleStatusChange(status) { - try { - if (status === "disconnected" || status === "failed") { - this.notificationManager.clearNotificationQueue(); - this.notificationManager.resetUnreadCount(); - } - } catch (error) { - } - } - /** - * Extract message information for notifications - * @param {*} message - Message content - * @param {string} type - Message type - * @returns {Object|null} Extracted message info or null - * @private - */ - extractMessageInfo(message, type) { - try { - let messageData = message; - if (typeof message === "string") { - try { - messageData = JSON.parse(message); - } catch (e) { - return { - senderName: "Peer", - text: message, - senderId: "peer", - senderAvatar: null - }; - } - } - if (typeof messageData === "object" && messageData !== null) { - return { - senderName: messageData.senderName || messageData.name || "Peer", - text: messageData.text || messageData.message || messageData.content || "", - senderId: messageData.senderId || messageData.id || "peer", - senderAvatar: messageData.senderAvatar || messageData.avatar || null - }; - } - return null; - } catch (error) { - return null; - } - } - /** - * Focus chat window when notification is clicked - * @private - */ - focusChatWindow() { - try { - window.focus(); - const messagesContainer = document.getElementById("messages"); - if (messagesContainer) { - messagesContainer.scrollTop = messagesContainer.scrollHeight; - } - } catch (error) { - } - } - /** - * Request notification permission - * @returns {Promise} Permission granted status - */ - async requestPermission() { - try { - return await this.notificationManager.requestPermission(); - } catch (error) { - return false; - } - } - /** - * Get notification status - * @returns {Object} Notification status - */ - getStatus() { - return this.notificationManager.getStatus(); - } - /** - * Clear all notifications - */ - clearNotifications() { - this.notificationManager.clearNotificationQueue(); - this.notificationManager.resetUnreadCount(); - } - /** - * Cleanup integration - */ - cleanup() { - try { - if (this.isInitialized) { - if (this.originalOnMessage) { - this.webrtcManager.onMessage = this.originalOnMessage; - } - if (this.originalOnStatusChange) { - this.webrtcManager.onStatusChange = this.originalOnStatusChange; - } - if (this.originalDeliverMessageToUI) { - this.webrtcManager.deliverMessageToUI = this.originalDeliverMessageToUI; - } - this.clearNotifications(); - this.isInitialized = false; - } - } catch (error) { - } - } - }; - if (typeof module !== "undefined" && module.exports) { - module.exports = { NotificationIntegration: NotificationIntegration2 }; - } - if (typeof window !== "undefined") { - window.NotificationIntegration = NotificationIntegration2; - } - } -}); - -// node_modules/dompurify/dist/purify.es.mjs -function _arrayLikeToArray(r, a) { - (null == a || a > r.length) && (a = r.length); - for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; - return n; -} -function _arrayWithHoles(r) { - if (Array.isArray(r)) return r; -} -function _iterableToArrayLimit(r, l) { - var t2 = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; - if (null != t2) { - var e, n, i, u, a = [], f = true, o = false; - try { - if (i = (t2 = t2.call(r)).next, 0 === l) ; - else for (; !(f = (e = i.call(t2)).done) && (a.push(e.value), a.length !== l); f = true) ; - } catch (r2) { - o = true, n = r2; - } finally { - try { - if (!f && null != t2.return && (u = t2.return(), Object(u) !== u)) return; - } finally { - if (o) throw n; - } - } - return a; - } -} -function _nonIterableRest() { - throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); -} -function _slicedToArray(r, e) { - return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); -} -function _unsupportedIterableToArray(r, a) { - if (r) { - if ("string" == typeof r) return _arrayLikeToArray(r, a); - var t2 = {}.toString.call(r).slice(8, -1); - return "Object" === t2 && r.constructor && (t2 = r.constructor.name), "Map" === t2 || "Set" === t2 ? Array.from(r) : "Arguments" === t2 || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t2) ? _arrayLikeToArray(r, a) : void 0; - } -} -var entries = Object.entries; -var setPrototypeOf = Object.setPrototypeOf; -var isFrozen = Object.isFrozen; -var getPrototypeOf = Object.getPrototypeOf; -var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; -var freeze = Object.freeze; -var seal = Object.seal; -var create = Object.create; -var _ref = typeof Reflect !== "undefined" && Reflect; -var apply = _ref.apply; -var construct = _ref.construct; -if (!freeze) { - freeze = function freeze2(x) { - return x; - }; -} -if (!seal) { - seal = function seal2(x) { - return x; - }; -} -if (!apply) { - apply = function apply2(func, thisArg) { - for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { - args[_key - 2] = arguments[_key]; - } - return func.apply(thisArg, args); - }; -} -if (!construct) { - construct = function construct2(Func) { - for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { - args[_key2 - 1] = arguments[_key2]; - } - return new Func(...args); - }; -} -var arrayForEach = unapply(Array.prototype.forEach); -var arrayLastIndexOf = unapply(Array.prototype.lastIndexOf); -var arrayPop = unapply(Array.prototype.pop); -var arrayPush = unapply(Array.prototype.push); -var arraySplice = unapply(Array.prototype.splice); -var arrayIsArray = Array.isArray; -var stringToLowerCase = unapply(String.prototype.toLowerCase); -var stringToString = unapply(String.prototype.toString); -var stringMatch = unapply(String.prototype.match); -var stringReplace = unapply(String.prototype.replace); -var stringIndexOf = unapply(String.prototype.indexOf); -var stringTrim = unapply(String.prototype.trim); -var numberToString = unapply(Number.prototype.toString); -var booleanToString = unapply(Boolean.prototype.toString); -var bigintToString = typeof BigInt === "undefined" ? null : unapply(BigInt.prototype.toString); -var symbolToString = typeof Symbol === "undefined" ? null : unapply(Symbol.prototype.toString); -var objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty); -var objectToString = unapply(Object.prototype.toString); -var regExpTest = unapply(RegExp.prototype.test); -var typeErrorCreate = unconstruct(TypeError); -function unapply(func) { - return function(thisArg) { - if (thisArg instanceof RegExp) { - thisArg.lastIndex = 0; - } - for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { - args[_key3 - 1] = arguments[_key3]; - } - return apply(func, thisArg, args); - }; -} -function unconstruct(Func) { - return function() { - for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { - args[_key4] = arguments[_key4]; - } - return construct(Func, args); - }; -} -function addToSet(set, array) { - let transformCaseFunc = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : stringToLowerCase; - if (setPrototypeOf) { - setPrototypeOf(set, null); - } - if (!arrayIsArray(array)) { - return set; - } - let l = array.length; - while (l--) { - let element = array[l]; - if (typeof element === "string") { - const lcElement = transformCaseFunc(element); - if (lcElement !== element) { - if (!isFrozen(array)) { - array[l] = lcElement; - } - element = lcElement; - } - } - set[element] = true; - } - return set; -} -function cleanArray(array) { - for (let index = 0; index < array.length; index++) { - const isPropertyExist = objectHasOwnProperty(array, index); - if (!isPropertyExist) { - array[index] = null; - } - } - return array; -} -function clone(object) { - const newObject = create(null); - for (const _ref2 of entries(object)) { - var _ref3 = _slicedToArray(_ref2, 2); - const property = _ref3[0]; - const value = _ref3[1]; - const isPropertyExist = objectHasOwnProperty(object, property); - if (isPropertyExist) { - if (arrayIsArray(value)) { - newObject[property] = cleanArray(value); - } else if (value && typeof value === "object" && value.constructor === Object) { - newObject[property] = clone(value); - } else { - newObject[property] = value; - } - } - } - return newObject; -} -function stringifyValue(value) { - switch (typeof value) { - case "string": { - return value; - } - case "number": { - return numberToString(value); - } - case "boolean": { - return booleanToString(value); - } - case "bigint": { - return bigintToString ? bigintToString(value) : "0"; - } - case "symbol": { - return symbolToString ? symbolToString(value) : "Symbol()"; - } - case "undefined": { - return objectToString(value); - } - case "function": - case "object": { - if (value === null) { - return objectToString(value); - } - const valueAsRecord = value; - const valueToString = lookupGetter(valueAsRecord, "toString"); - if (typeof valueToString === "function") { - const stringified = valueToString(valueAsRecord); - return typeof stringified === "string" ? stringified : objectToString(stringified); - } - return objectToString(value); - } - default: { - return objectToString(value); - } - } -} -function lookupGetter(object, prop) { - while (object !== null) { - const desc = getOwnPropertyDescriptor(object, prop); - if (desc) { - if (desc.get) { - return unapply(desc.get); - } - if (typeof desc.value === "function") { - return unapply(desc.value); - } - } - object = getPrototypeOf(object); - } - function fallbackValue() { - return null; - } - return fallbackValue; -} -function isRegex(value) { - try { - regExpTest(value, ""); - return true; - } catch (_unused) { - return false; - } -} -var html$1 = freeze(["a", "abbr", "acronym", "address", "area", "article", "aside", "audio", "b", "bdi", "bdo", "big", "blink", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "content", "data", "datalist", "dd", "decorator", "del", "details", "dfn", "dialog", "dir", "div", "dl", "dt", "element", "em", "fieldset", "figcaption", "figure", "font", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "img", "input", "ins", "kbd", "label", "legend", "li", "main", "map", "mark", "marquee", "menu", "menuitem", "meter", "nav", "nobr", "ol", "optgroup", "option", "output", "p", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "search", "section", "select", "shadow", "slot", "small", "source", "spacer", "span", "strike", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "tr", "track", "tt", "u", "ul", "var", "video", "wbr"]); -var svg$1 = freeze(["svg", "a", "altglyph", "altglyphdef", "altglyphitem", "animatecolor", "animatemotion", "animatetransform", "circle", "clippath", "defs", "desc", "ellipse", "enterkeyhint", "exportparts", "filter", "font", "g", "glyph", "glyphref", "hkern", "image", "inputmode", "line", "lineargradient", "marker", "mask", "metadata", "mpath", "part", "path", "pattern", "polygon", "polyline", "radialgradient", "rect", "stop", "style", "switch", "symbol", "text", "textpath", "title", "tref", "tspan", "view", "vkern"]); -var svgFilters = freeze(["feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence"]); -var svgDisallowed = freeze(["animate", "color-profile", "cursor", "discard", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignobject", "hatch", "hatchpath", "mesh", "meshgradient", "meshpatch", "meshrow", "missing-glyph", "script", "set", "solidcolor", "unknown", "use"]); -var mathMl$1 = freeze(["math", "menclose", "merror", "mfenced", "mfrac", "mglyph", "mi", "mlabeledtr", "mmultiscripts", "mn", "mo", "mover", "mpadded", "mphantom", "mroot", "mrow", "ms", "mspace", "msqrt", "mstyle", "msub", "msup", "msubsup", "mtable", "mtd", "mtext", "mtr", "munder", "munderover", "mprescripts"]); -var mathMlDisallowed = freeze(["maction", "maligngroup", "malignmark", "mlongdiv", "mscarries", "mscarry", "msgroup", "mstack", "msline", "msrow", "semantics", "annotation", "annotation-xml", "mprescripts", "none"]); -var text = freeze(["#text"]); -var html = freeze(["accept", "action", "align", "alt", "autocapitalize", "autocomplete", "autopictureinpicture", "autoplay", "background", "bgcolor", "border", "capture", "cellpadding", "cellspacing", "checked", "cite", "class", "clear", "color", "cols", "colspan", "command", "commandfor", "controls", "controlslist", "coords", "crossorigin", "datetime", "decoding", "default", "dir", "disabled", "disablepictureinpicture", "disableremoteplayback", "download", "draggable", "enctype", "enterkeyhint", "exportparts", "face", "for", "headers", "height", "hidden", "high", "href", "hreflang", "id", "inert", "inputmode", "integrity", "ismap", "kind", "label", "lang", "list", "loading", "loop", "low", "max", "maxlength", "media", "method", "min", "minlength", "multiple", "muted", "name", "nonce", "noshade", "novalidate", "nowrap", "open", "optimum", "part", "pattern", "placeholder", "playsinline", "popover", "popovertarget", "popovertargetaction", "poster", "preload", "pubdate", "radiogroup", "readonly", "rel", "required", "rev", "reversed", "role", "rows", "rowspan", "spellcheck", "scope", "selected", "shape", "size", "sizes", "slot", "span", "srclang", "start", "src", "srcset", "step", "style", "summary", "tabindex", "title", "translate", "type", "usemap", "valign", "value", "width", "wrap", "xmlns"]); -var svg = freeze(["accent-height", "accumulate", "additive", "alignment-baseline", "amplitude", "ascent", "attributename", "attributetype", "azimuth", "basefrequency", "baseline-shift", "begin", "bias", "by", "class", "clip", "clippathunits", "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", "color-profile", "color-rendering", "cx", "cy", "d", "dx", "dy", "diffuseconstant", "direction", "display", "divisor", "dur", "edgemode", "elevation", "end", "exponent", "fill", "fill-opacity", "fill-rule", "filter", "filterunits", "flood-color", "flood-opacity", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "fx", "fy", "g1", "g2", "glyph-name", "glyphref", "gradientunits", "gradienttransform", "height", "href", "id", "image-rendering", "in", "in2", "intercept", "k", "k1", "k2", "k3", "k4", "kerning", "keypoints", "keysplines", "keytimes", "lang", "lengthadjust", "letter-spacing", "kernelmatrix", "kernelunitlength", "lighting-color", "local", "marker-end", "marker-mid", "marker-start", "markerheight", "markerunits", "markerwidth", "maskcontentunits", "maskunits", "max", "mask", "mask-type", "media", "method", "mode", "min", "name", "numoctaves", "offset", "operator", "opacity", "order", "orient", "orientation", "origin", "overflow", "paint-order", "path", "pathlength", "patterncontentunits", "patterntransform", "patternunits", "points", "preservealpha", "preserveaspectratio", "primitiveunits", "r", "rx", "ry", "radius", "refx", "refy", "repeatcount", "repeatdur", "restart", "result", "rotate", "scale", "seed", "shape-rendering", "slope", "specularconstant", "specularexponent", "spreadmethod", "startoffset", "stddeviation", "stitchtiles", "stop-color", "stop-opacity", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke", "stroke-width", "style", "surfacescale", "systemlanguage", "tabindex", "tablevalues", "targetx", "targety", "transform", "transform-origin", "text-anchor", "text-decoration", "text-rendering", "textlength", "type", "u1", "u2", "unicode", "values", "viewbox", "visibility", "version", "vert-adv-y", "vert-origin-x", "vert-origin-y", "width", "word-spacing", "wrap", "writing-mode", "xchannelselector", "ychannelselector", "x", "x1", "x2", "xmlns", "y", "y1", "y2", "z", "zoomandpan"]); -var mathMl = freeze(["accent", "accentunder", "align", "bevelled", "close", "columnalign", "columnlines", "columnspacing", "columnspan", "denomalign", "depth", "dir", "display", "displaystyle", "encoding", "fence", "frame", "height", "href", "id", "largeop", "length", "linethickness", "lquote", "lspace", "mathbackground", "mathcolor", "mathsize", "mathvariant", "maxsize", "minsize", "movablelimits", "notation", "numalign", "open", "rowalign", "rowlines", "rowspacing", "rowspan", "rspace", "rquote", "scriptlevel", "scriptminsize", "scriptsizemultiplier", "selection", "separator", "separators", "stretchy", "subscriptshift", "supscriptshift", "symmetric", "voffset", "width", "xmlns"]); -var xml = freeze(["xlink:href", "xml:id", "xlink:title", "xml:space", "xmlns:xlink"]); -var MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g); -var ERB_EXPR = seal(/<%[\w\W]*|^[\w\W]*%>/g); -var TMPLIT_EXPR = seal(/\${[\w\W]*/g); -var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); -var ARIA_ATTR = seal(/^aria-[\-\w]+$/); -var IS_ALLOWED_URI = seal( - /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i - // eslint-disable-line no-useless-escape -); -var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i); -var ATTR_WHITESPACE = seal( - /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g - // eslint-disable-line no-control-regex -); -var DOCTYPE_NAME = seal(/^html$/i); -var CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i); -var ELEMENT_MARKUP_PROBE = seal(/<[/\w!]/g); -var COMMENT_MARKUP_PROBE = seal(/<[/\w]/g); -var FALLBACK_TAG_CLOSE = seal(/<\/no(script|embed|frames)/i); -var SELF_CLOSING_TAG = seal(/\/>/i); -var NODE_TYPE = { - element: 1, - attribute: 2, - text: 3, - cdataSection: 4, - entityReference: 5, - // Deprecated - entityNode: 6, - // Deprecated - processingInstruction: 7, - comment: 8, - document: 9, - documentType: 10, - documentFragment: 11, - notation: 12 - // Deprecated -}; -var getGlobal = function getGlobal2() { - return typeof window === "undefined" ? null : window; -}; -var _createTrustedTypesPolicy = function _createTrustedTypesPolicy2(trustedTypes, purifyHostElement) { - if (typeof trustedTypes !== "object" || typeof trustedTypes.createPolicy !== "function") { - return null; - } - let suffix = null; - const ATTR_NAME = "data-tt-policy-suffix"; - if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) { - suffix = purifyHostElement.getAttribute(ATTR_NAME); - } - const policyName = "dompurify" + (suffix ? "#" + suffix : ""); - try { - return trustedTypes.createPolicy(policyName, { - createHTML(html2) { - return html2; - }, - createScriptURL(scriptUrl) { - return scriptUrl; - } - }); - } catch (_) { - console.warn("TrustedTypes policy " + policyName + " could not be created."); - return null; - } -}; -var _createHooksMap = function _createHooksMap2() { - return { - afterSanitizeAttributes: [], - afterSanitizeElements: [], - afterSanitizeShadowDOM: [], - beforeSanitizeAttributes: [], - beforeSanitizeElements: [], - beforeSanitizeShadowDOM: [], - uponSanitizeAttribute: [], - uponSanitizeElement: [], - uponSanitizeShadowNode: [] - }; -}; -var _resolveSetOption = function _resolveSetOption2(cfg, key, fallback, options) { - return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key]) ? addToSet(options.base ? clone(options.base) : {}, cfg[key], options.transform) : fallback; -}; -function createDOMPurify() { - let window2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal(); - const DOMPurify = (root) => createDOMPurify(root); - DOMPurify.version = "3.4.10"; - DOMPurify.removed = []; - if (!window2 || !window2.document || window2.document.nodeType !== NODE_TYPE.document || !window2.Element) { - DOMPurify.isSupported = false; - return DOMPurify; - } - let document2 = window2.document; - const originalDocument = document2; - const currentScript = originalDocument.currentScript; - window2.DocumentFragment; - const HTMLTemplateElement = window2.HTMLTemplateElement, Node = window2.Node, Element = window2.Element, NodeFilter = window2.NodeFilter, _window$NamedNodeMap = window2.NamedNodeMap; - _window$NamedNodeMap === void 0 ? window2.NamedNodeMap || window2.MozNamedAttrMap : _window$NamedNodeMap; - window2.HTMLFormElement; - const DOMParser = window2.DOMParser, trustedTypes = window2.trustedTypes; - const ElementPrototype = Element.prototype; - const cloneNode = lookupGetter(ElementPrototype, "cloneNode"); - const remove = lookupGetter(ElementPrototype, "remove"); - const getNextSibling = lookupGetter(ElementPrototype, "nextSibling"); - const getChildNodes = lookupGetter(ElementPrototype, "childNodes"); - const getParentNode = lookupGetter(ElementPrototype, "parentNode"); - const getShadowRoot = lookupGetter(ElementPrototype, "shadowRoot"); - const getAttributes = lookupGetter(ElementPrototype, "attributes"); - const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeType") : null; - const getNodeName = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeName") : null; - if (typeof HTMLTemplateElement === "function") { - const template = document2.createElement("template"); - if (template.content && template.content.ownerDocument) { - document2 = template.content.ownerDocument; - } - } - let trustedTypesPolicy; - let emptyHTML = ""; - let defaultTrustedTypesPolicy; - let defaultTrustedTypesPolicyResolved = false; - let IN_TRUSTED_TYPES_POLICY = 0; - const _assertNotInTrustedTypesPolicy = function _assertNotInTrustedTypesPolicy2() { - if (IN_TRUSTED_TYPES_POLICY > 0) { - throw typeErrorCreate('A configured TRUSTED_TYPES_POLICY callback (createHTML or createScriptURL) must not call DOMPurify.sanitize, as that causes infinite recursion. Do not pass a policy whose callbacks wrap DOMPurify as TRUSTED_TYPES_POLICY; see the "DOMPurify and Trusted Types" section of the README.'); - } - }; - const _createTrustedHTML = function _createTrustedHTML2(html2) { - _assertNotInTrustedTypesPolicy(); - IN_TRUSTED_TYPES_POLICY++; - try { - return trustedTypesPolicy.createHTML(html2); - } finally { - IN_TRUSTED_TYPES_POLICY--; - } - }; - const _createTrustedScriptURL = function _createTrustedScriptURL2(scriptUrl) { - _assertNotInTrustedTypesPolicy(); - IN_TRUSTED_TYPES_POLICY++; - try { - return trustedTypesPolicy.createScriptURL(scriptUrl); - } finally { - IN_TRUSTED_TYPES_POLICY--; - } - }; - const _getDefaultTrustedTypesPolicy = function _getDefaultTrustedTypesPolicy2() { - if (!defaultTrustedTypesPolicyResolved) { - defaultTrustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript); - defaultTrustedTypesPolicyResolved = true; - } - return defaultTrustedTypesPolicy; - }; - const _document = document2, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName; - const importNode = originalDocument.importNode; - let hooks = _createHooksMap(); - DOMPurify.isSupported = typeof entries === "function" && typeof getParentNode === "function" && implementation && implementation.createHTMLDocument !== void 0; - const MUSTACHE_EXPR$1 = MUSTACHE_EXPR, ERB_EXPR$1 = ERB_EXPR, TMPLIT_EXPR$1 = TMPLIT_EXPR, DATA_ATTR$1 = DATA_ATTR, ARIA_ATTR$1 = ARIA_ATTR, IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA, ATTR_WHITESPACE$1 = ATTR_WHITESPACE, CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT; - let IS_ALLOWED_URI$1 = IS_ALLOWED_URI; - let ALLOWED_TAGS = null; - const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]); - let ALLOWED_ATTR = null; - const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]); - let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, { - tagNameCheck: { - writable: true, - configurable: false, - enumerable: true, - value: null - }, - attributeNameCheck: { - writable: true, - configurable: false, - enumerable: true, - value: null - }, - allowCustomizedBuiltInElements: { - writable: true, - configurable: false, - enumerable: true, - value: false - } - })); - let FORBID_TAGS = null; - let FORBID_ATTR = null; - const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, { - tagCheck: { - writable: true, - configurable: false, - enumerable: true, - value: null - }, - attributeCheck: { - writable: true, - configurable: false, - enumerable: true, - value: null - } - })); - let ALLOW_ARIA_ATTR = true; - let ALLOW_DATA_ATTR = true; - let ALLOW_UNKNOWN_PROTOCOLS = false; - let ALLOW_SELF_CLOSE_IN_ATTR = true; - let SAFE_FOR_TEMPLATES = false; - let SAFE_FOR_XML = true; - let WHOLE_DOCUMENT = false; - let SET_CONFIG = false; - let FORCE_BODY = false; - let RETURN_DOM = false; - let RETURN_DOM_FRAGMENT = false; - let RETURN_TRUSTED_TYPE = false; - let SANITIZE_DOM = true; - let SANITIZE_NAMED_PROPS = false; - const SANITIZE_NAMED_PROPS_PREFIX = "user-content-"; - let KEEP_CONTENT = true; - let IN_PLACE = false; - let USE_PROFILES = {}; - let FORBID_CONTENTS = null; - const DEFAULT_FORBID_CONTENTS = addToSet({}, [ - "annotation-xml", - "audio", - "colgroup", - "desc", - "foreignobject", - "head", - "iframe", - "math", - "mi", - "mn", - "mo", - "ms", - "mtext", - "noembed", - "noframes", - "noscript", - "plaintext", - "script", - // mirrors the selected