From 137a81dcab11c0416004ca02bafab60ad85717bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Janczak?= Date: Wed, 3 Jun 2026 16:24:43 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20Release=20v3.0.0=20=E2=80=94=20Native?= =?UTF-8?q?=20App=20Linking,=20Deep=20Linking,=20Pixels=20Registry,=20and?= =?UTF-8?q?=20Custom=20Expiry=20Pages?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CONTRIBUTING.md | 30 ++ README.md | 181 +++++++++--- config/filament-short-url.php | 43 +++ ...to_open_app_mobile_to_short_urls_table.php | 22 ++ resources/dist/filament-short-url.css | 2 +- resources/lang/en/default.php | 45 +++ resources/lang/pl/default.php | 41 +++ resources/views/app-linking-preview.blade.php | 105 +++++++ resources/views/app-redirect.blade.php | 274 ++++++++++++++++++ resources/views/expired.blade.php | 90 ++++++ routes/web.php | 8 + .../Resources/ShortUrlPixelResource.php | 17 +- src/Filament/Resources/ShortUrlResource.php | 2 - .../ShortUrlResource/Pages/ListShortUrls.php | 8 - .../Pages/ShortUrlSettingsPage.php | 117 +++++++- .../ShortUrlResource/Schemas/ShortUrlForm.php | 27 ++ src/FilamentShortUrlPlugin.php | 3 + src/FilamentShortUrlServiceProvider.php | 2 + .../ShortUrlRedirectController.php | 97 ++++++- src/Models/ShortUrl.php | 2 + src/Services/AppLinkingEngine.php | 242 ++++++++++++++++ src/Services/ShortUrlSettingsManager.php | 15 + tests/Feature/ShortUrlDeepLinkingTest.php | 155 ++++++++++ tests/Feature/ShortUrlRedirectTest.php | 10 + 24 files changed, 1473 insertions(+), 65 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 database/migrations/2026_06_03_160000_add_auto_open_app_mobile_to_short_urls_table.php create mode 100644 resources/views/app-linking-preview.blade.php create mode 100644 resources/views/app-redirect.blade.php create mode 100644 resources/views/expired.blade.php create mode 100644 src/Services/AppLinkingEngine.php create mode 100644 tests/Feature/ShortUrlDeepLinkingTest.php diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..044ec72 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,30 @@ +# Contributing to Filament Short URL + +Thank you for considering contributing to the Filament Short URL plugin! + +## Development Setup + +If you are modifying the plugin source code and need to recompile its stylesheet after changing Blade, PHP, or configuration files, follow these steps: + +### 1. Recompile Plugin CSS (Tailwind CSS v4) +Run the Tailwind CSS CLI from the root folder of your host application to scan the plugin's views and compile the final stylesheet: + +```bash +npx @tailwindcss/cli -i ./packages/filament-short-url/resources/css/plugin.css \ + -o ./packages/filament-short-url/resources/dist/filament-short-url.css --minify +``` + +### 2. Re-publish compiled assets +After compiling, publish the updated CSS stylesheet to the public folder of your host application so the browser can load it: + +```bash +php artisan filament:assets +``` + +## Running Tests + +We enforce test coverage for all features. To run the tests from the root of your host application: + +```bash +php artisan test --filter=ShortUrl +``` diff --git a/README.md b/README.md index 637fa64..23b8750 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,16 @@ Tests

-A professional, high-performance **Short URL Manager** plugin for [Filament v5](https://filamentphp.com). Built from scratch with cutting-edge practices, proxy resistance, offline Geo-IP engines, enterprise-grade smart targeting, and zero external shortening API dependencies. +A professional, high-performance **Short URL Manager, Redirect Engine & QR Code Generator** plugin for [Filament v5](https://filamentphp.com). + +Acting as a self-hosted, enterprise-grade alternative to Bitly and Rebrandly, this package provides advanced link shortening, mobile app deep linking (Universal Links & Android App Links), client-side retargeting pixels, offline Geo-IP country routing, real-time analytics, and webhooksβ€”with zero external API dependencies. + +### Why choose Filament Short URL? +* **Save on SaaS Costs**: Replace expensive Bitly or Rebrandly subscriptions with a self-hosted solution that has zero click or creation limits. +* **Server-Side GA4 Tracking**: Bypasses browser-side ad blockers completely to ensure 100% accurate traffic data. +* **Retarget on External Sites**: Inject tracking pixels (Meta, Google Ads, LinkedIn, TikTok, Pinterest) on a beautiful glassmorphic redirect page before forwarding visitors. +* **Seamless Mobile App Redirects**: Launch native mobile applications (Instagram, YouTube, Spotify, WhatsApp) automatically using deep links. +* **GDPR-Friendly Geo-IP**: Resolve visitor countries offline using local MaxMind databases or trust your CDN headers (Cloudflare, CloudFront). ## Screenshots @@ -37,30 +46,33 @@ A professional, high-performance **Short URL Manager** plugin for [Filament v5]( ## Features -- πŸ”— **Short URL Generation** β€” Create custom links or let the system auto-generate collision-free Base62 keys. -- 🌍 **Multiple Geo-IP Drivers** β€” High-speed offline detection using local MaxMind databases, edge-provided CDN headers (Cloudflare, CloudFront, generic), or fallback API integration. -- πŸ—ΊοΈ **Visitor World Map Widget** β€” Interactive SVG world map on the link statistics dashboard showcasing the geographical distribution of visitor clicks with hover details. -- πŸ“ˆ **Real-Time Statistics Dashboard** β€” Track visits in real-time with cached aggregate metrics (countries, devices, browsers, operating systems, referrers, traffic charts, and maps). -- πŸ›‘οΈ **VPN, Proxy & Bot Filtering** β€” Exclude VPNs, proxies, Tor exit nodes, and automated bot clicks from your analytics to keep visitor statistics accurate. -- πŸ” **Google Safe Browsing Integration** β€” Automatically verify target URLs on creation/edit to block malicious, phishing, malware, or social engineering links. -- 🎨 **SVG QR Code Designer & Custom Logo Overlay** *(new in v2.0)* β€” Built-in interactive design canvas to customize dot styles, margins, gradient coloring, and background transparency. Upload custom brand logos with shape configuration (square/circle), margins, sizes, and auto-clear overlapping dots, with instant SVG/PNG download. -- πŸ“Š **Dedicated QR Code Scan Tracking** *(new in v2.0)* β€” Separates direct visits from QR code scans in analytics. Dynamically appends tracking tags and showcases QR scans in its own badge within tables. -- 🌐 **Browser Language Analytics** *(new in v2.0)* β€” Detects client browser preferred language settings to showcase a "Top Languages" analytics breakdown in the link statistics dashboard. -- ⚑ **Ultra-Fast Redirects** β€” Redirections resolve in milliseconds. Analytical tasks, event dispatching, and GA4 payloads are processed asynchronously via Laravel Queue jobs. -- 🎯 **Google Analytics 4 server-side tracking** β€” Native integration with the GA4 Measurement Protocol to bypass client-side AdBlockers completely. -- βš™οΈ **Dual-way UTM Campaign Builder** β€” Built-in form builder synchronizes UTM parameters with your destination URLs in real-time (two-way binding). -- πŸ”’ **Link Validity Ranges & Expiry** β€” Set activation date ranges (From - To), custom visit limit counters (e.g. active for 3 clicks then expires), single-use restrictions, and custom fallback redirect URLs on expiration instead of static 410 Gone errors. -- ➑️ **Query Parameter Forwarding** β€” Dynamically forward client query parameters (e.g. ad tokens, discount codes) to the destination URL. -- πŸ› οΈ **Dedicated Settings GUI** β€” Manage global configuration (routing, Geo-IP, GA4, cache, rate limiting, aggregation) directly inside the Filament panel without modifying files or `.env` files. -- πŸ’» **Fluent Developer Builder** β€” Native model query builder pattern and robust programmatic generation APIs. -- πŸ”‘ **Password-Protected Links** β€” Require a password before redirecting visitors, with session-based unlock. -- ⚠️ **Redirect Warning Pages** β€” Show an interstitial security page before redirecting to external URLs (phishing/NSFW protection). -- 🎯 **Smart Link Targeting** β€” Route visitors to different destination URLs based on their device type, country, or via weighted A/B split rotation. -- πŸ›‘οΈ **Rate Limiting / Bot Protection** β€” Configurable per-IP rate limits on redirects with automatic `429 Too Many Requests` responses. -- πŸ“Š **Daily Stats Aggregation & Pruning** β€” Automatic daily summarization of raw visit logs into compact daily stats tables. Configurable retention window prevents unbounded database growth at scale. -- 🎯 **Social Retargeting Pixels** *(new in v1.5)* β€” Inject Meta Pixel, Google Tag, and LinkedIn Insight tracking scripts client-side via a premium glassmorphic interstitial page. Build remarketing audiences even when redirecting to external domains. -- πŸ”Œ **Developer REST API** *(new in v1.5)* β€” Full REST API (`GET`, `POST`, `DELETE`) for external integrations. Secured with API Key authentication managed via the Settings panel. -- πŸ“‘ **Webhooks** *(new in v1.5)* β€” Real-time HTTP POST event notifications on every click, link creation, or expiration. Configure per-link or globally, dispatched asynchronously via the queue. +- πŸ”— **Base62 Short Link Generation** β€” Create clean, custom short links or let the system auto-generate collision-free Base62 keys. +- 🌍 **Multiple Geo-IP Drivers** β€” Route and analyze traffic with offline MaxMind detection, CDN edge headers (Cloudflare's `CF-IPCountry`, CloudFront), or fallback APIs. +- πŸ—ΊοΈ **Interactive Visitor World Map** β€” Showcase geographic click distribution on a beautiful SVG world map widget with real-time hover details. +- πŸ“ˆ **Comprehensive Analytics Dashboard** β€” Monitor total/unique visits, referrers, operating systems, devices, browsers, and top browser languages in real-time. +- πŸ›‘οΈ **VPN, Proxy & Bot Filtering** β€” Exclude scrapers, crawlers, Tor exit nodes, and automated bot clicks to keep your analytics clean and accurate. +- πŸ” **Google Safe Browsing** β€” Automatically scan target URLs on creation/edit to block phishing, malware, and social engineering links. +- 🎨 **SVG QR Code Designer** β€” Customize dot styles, gradients, margins, and upload custom brand logos with auto-clear backing dots and high-quality SVG/PNG exports. +- πŸ“Š **Dedicated QR Code Tracking** β€” Differentiate physical QR scans from direct web clicks with automatically appended query parameters (`?source=qr`). +- 🌐 **Browser Language Targeting** β€” Route visitors dynamically based on their browser language preferences (e.g., redirect Polish speakers to a Polish landing page). +- ⚑ **Ultra-Fast Redirections** β€” Redirections resolve in milliseconds. Logging, GA4 payloads, and webhooks are processed asynchronously in the background. +- 🎯 **Server-Side GA4 Integration** β€” Send server-side `short_url_visit` hits using the Google Analytics 4 Measurement Protocol to bypass ad-blockers. +- βš™οΈ **Dual-way UTM Builder** β€” Build campaign URLs with a real-time synchronized UTM builder directly in the link creation form. +- πŸ”’ **Link Expiration & Fallbacks** β€” Set activation date ranges, click-limit caps, single-use restrictions, and custom redirection fallbacks on expiration. +- ➑️ **Query Parameter Forwarding** β€” Automatically forward client query strings (e.g., ad tokens, UTM parameters, discount codes) to the destination. +- πŸ› οΈ **Central Settings Panel** β€” Manage routes, Geo-IP, GA4, caching, rate limiting, and retention directly inside your Filament panel. +- πŸ”‘ **Password-Protected Links** β€” Secure sensitive links with a customizable, session-based password entry interstitial. +- ⚠️ **Redirect Warning Interstitials** β€” Show a security warning page to verify external links (phishing and NSFW protection). +- 🎯 **Advanced Smart Targeting** β€” Redirect visitors dynamically based on device type (iOS, Android, Desktop), country (Geo-IP), or browser language. +- βš–οΈ **A/B Split Testing Rotation** β€” Distribute traffic randomly across multiple landing pages using custom weighted rotation rules. +- πŸ›‘οΈ **Throttling & Rate Limiting** β€” Protect your redirection routes from flood attacks with configurable per-IP rate limits. +- πŸ“Š **Log Aggregation & Pruning** β€” Compact millions of raw visit logs into daily summaries automatically to prevent database bloat. +- 🎯 **Central Retargeting Pixel Registry (new in v3.0.0)** β€” Register Meta Pixel, Google Tag, LinkedIn Insight, TikTok Pixel, and Pinterest Tag centrally and associate them with links via checkboxes. +- πŸ”Œ **Developer REST API** β€” Full programmatical control with secure API Key authentication to create, list, and delete short links externally. +- πŸ“‘ **Real-Time Webhooks** β€” Asynchronous HTTP POST notifications on `visited`, `created`, `expired`, and `limit_reached` events with a built-in retry policy. +- πŸ“± **Mobile App Deep Linking (new in v3.0.0)** β€” Detect mobile visitors and open links directly in 24+ native apps (Instagram, YouTube, Spotify, TikTok, etc.) using custom URI schemes. +- πŸ”— **Universal Links & App Links (new in v3.0.0)** β€” Host iOS `apple-app-site-association` and Android `assetlinks.json` domain configuration files directly from your root domain. +- 🎨 **Branded Expiry Pages (new in v3.0.0)** β€” Display a premium, dark-mode compatible custom expiry page when a link is deactivated or limit-reached, falling back to a clean site-name greeting instead of a generic browser error. --- @@ -122,6 +134,13 @@ php artisan filament:assets That's all. The plugin's CSS will be served from `public/css/janczakb/filament-short-url/filament-short-url.css` and Filament registers it automatically. > **You do not need to run Tailwind, Vite, or npm for the plugin styles.** The compiled file is included in the package. +> +> **Using a Custom Filament Theme (Tailwind CSS v4)?** +> If you are compiling your own Filament panel theme stylesheet, you can optionally tell Tailwind to scan the plugin's views by adding the `@source` directive to your theme's CSS file (e.g., `resources/css/filament/admin/theme.css`): +> +> ```css +> @source './vendor/janczakb/filament-short-url/resources/views/**/*.blade.php'; +> ``` **Tip β€” automate on every `composer install` / `composer update`:** @@ -139,21 +158,6 @@ Add `filament:assets` to the `post-autoload-dump` scripts in your application's --- -> #### πŸ›  For Plugin Developers Only -> -> If you are modifying the plugin source and need to recompile its stylesheet after changing Blade/PHP files: -> -> ```bash -> # 1. Recompile the plugin CSS with Tailwind v4 -> npx @tailwindcss/cli -i ./packages/filament-short-url/resources/css/plugin.css \ -> -o ./packages/filament-short-url/resources/dist/filament-short-url.css --minify -> -> # 2. Re-publish the compiled asset to public/ -> php artisan filament:assets -> ``` - ---- - ## Setup Register the plugin in your Filament Panel Provider (`app/Providers/Filament/AdminPanelProvider.php`): @@ -236,7 +240,7 @@ protected $policies = [ ## Global Settings GUI -The package comes with a built-in admin settings dashboard. You can access it by clicking the **Settings** action button on the top-right header of the Short URLs resource. +The package comes with a built-in admin settings dashboard. It is accessible directly from your sidebar menu under the same navigation group as your links. Settings are stored dynamically in `storage/app/filament-short-url-settings.json` and immediately override config defaults. @@ -318,6 +322,18 @@ This feature is useful for NSFW links, external partner links, or any URL that l --- +## Custom Branded Expiry Pages (new in v3.0.0) + +When a short URL is expired, deactivated, or has reached its maximum visit limit, it needs to handle the redirect gracefully: +* **Custom Fallback URL**: If configured, visitors are immediately redirected to the `expiration_redirect_url` target. +* **Branded Expiry Page (Default)**: If no fallback URL is specified, the system displays a premium branded, fully localized, dark-mode compatible HTML page (`expired.blade.php`) instead of a generic browser `410 Gone` error. + - Automatically displays your customized **Site Name** (and host application logo if the `setting('logo_path')` helper is defined). + - Displays a clean visual alert state with details about the expired link. + - Features a friendly back button pointing to your website's homepage. + - Can be easily customized by publishing package views: `php artisan vendor:publish --tag=filament-short-url-views`. + +--- + ## Smart Link Targeting (new in v1.2.0) The **Targeting & Security** tab exposes a powerful rule engine that lets you route different visitors to different destinations β€” all from a single short URL. @@ -398,6 +414,78 @@ $shortUrl->update([ --- +## Native App Linking & Deep Linking (new in v3.0.0) + +This package supports two distinct levels of mobile app integration: **Per-Link App Linking** (client-side redirects using custom schemes) and **Global Deep Linking Files** (domain association files for OS-level native integration). + +### 1. Per-Link App Linking (Mobile Auto-Open) + +When creating or editing a short URL, the **App Linking** tab allows you to configure automatic redirects into native mobile applications. + +* **How it works**: If a destination URL matches one of the 24+ pre-configured native applications (such as YouTube, TikTok, Instagram, Facebook, Spotify, WhatsApp, Messenger, etc.), the plugin can bypass standard web views for mobile visitors. +* **The Interstitial Experience**: If **Auto open app on mobile** is enabled, mobile visitors are shown a premium glassmorphic redirect interstitial page that triggers the corresponding custom URL scheme (e.g. `whatsapp://`, `instagram://`, `youtube://`) to launch the native app directly, with fallback options to open in a web browser. +* **Interactive Panel Preview**: Inside the Filament resource edit form, a live preview widget demonstrates if the URL was matched, showing: + - The matched app with its official favicon. + - The calculated deep link scheme. + - An interactive grid showing all supported native applications. + +Supported apps include: YouTube, TikTok, Instagram, X (Twitter), Spotify, Facebook, Reddit, Snapchat, WhatsApp, LinkedIn, Pinterest, Twitch, Netflix, Google Docs/Sheets/Slides/Maps, Messenger, Apple Music, Airbnb, TripAdvisor, Amazon, StockX, Booking, AliExpress. + +--- + +### 2. Global Deep Linking Files (Universal Links & App Links) + +To support seamless OS-level integrations without browser intermediariesβ€”such as iOS Universal Links and Android App Linksβ€”you can serve domain association files directly from your application's root domain. + +> [!IMPORTANT] +> **Disabled by default**: This feature is turned **off** by default. You can enable it and customize the association JSON in your settings panel. + +#### Enabling and Configuration +1. Open the **Settings** panel from your Filament sidebar. +2. Navigate to the **Deep Linking** tab. +3. Toggle **Enable Deep Linking Files** to ON. +4. Fill in your configurations: + * **apple-app-site-association (iOS)**: The JSON configuration representing your iOS application IDs and supported paths (e.g., `/s/*`). This will be served at `/.well-known/apple-app-site-association` and `/apple-app-site-association` with the `application/json` content-type header. + * **assetlinks.json (Android)**: The Digital Asset Links JSON array representing your Android application package names and SHA-256 certificate fingerprints. This will be served at `/.well-known/assetlinks.json`. + +#### Example Configurations +##### iOS AASA Example: +```json +{ + "applinks": { + "apps": [], + "details": [ + { + "appID": "YOUR_TEAM_ID.com.yourcompany.app", + "paths": [ + "/s/*" + ] + } + ] + } +} +``` + +##### Android AssetLinks Example: +```json +[ + { + "relation": [ + "delegate_permission/common.handle_all_urls" + ], + "target": { + "namespace": "android_app", + "package_name": "com.yourcompany.app", + "sha256_cert_fingerprints": [ + "14:6D:E9:57:3E:28:B6:58:91:..." + ] + } + } +] +``` + +--- + ## High-Traffic Optimizations (new in v1.2.0) ### Daily Stats Aggregation @@ -447,13 +535,13 @@ When Redis is not available and counter buffering is enabled, the `IncrementVisi --- -## Social Retargeting Pixels & Central Pixel Registry (new in v2.1.0) +## Social Retargeting Pixels & Central Pixel Registry (new in v3.0.0) Instead of manually copy-pasting tracking pixel IDs (Meta, Google Tag, LinkedIn, TikTok, Pinterest) every time you create a new link, the package features a centralized **Retargeting Pixel Registry** with a Many-to-Many relationship. You define your marketing pixels once in the new **Pixel Registry** resource, and then easily select them via checkbox/list options when creating or editing short links. ### The Interstitial Experience - **Premium Design**: Built using the exact same modern glassmorphic look as the password protection and warning interstitial pages. Supports dark mode automatically. -- **Brand Customization**: Automatically renders the application logo and the **Site Name Override** (configured globally in Settings, falling back to `config('app.name')`) to ensure the transition page looks professional and trust-instilling. +- **Brand Customization**: Automatically renders the application logo (if defined via the `setting('logo_path')` helper) and the **Site Name Override** (configured globally in Settings, falling back to `config('app.name')`) to ensure the transition page looks professional and trust-instilling. - **Micro-Animations & Smooth Redirect**: Displays a sleek animated loading spinner and a progress bar that smoothly fills from 0% to 100% in ~220-250ms. This short delay ensures browser execution time for the tracking scripts before performing a seamless `window.location.replace()` to the destination URL. This unlocks remarketing to people who clicked your links **even when redirecting to external domains** (e.g. booking.com, amazon.com) where you cannot install your own tracking code. @@ -891,10 +979,15 @@ All migrations are compatible with **SQLite**, **MySQL**, and **PostgreSQL**: ## Changelog -### v2.1.0 +### v3.0.0 +- **Native App Linking (Mobile Auto-Open)** β€” Automatically match and redirect mobile visitors directly inside 24+ native mobile apps (such as WhatsApp, YouTube, TikTok, Instagram, Spotify, etc.) using custom schemes, complete with a glassmorphic redirect page and a live interactive matching preview widget. +- **Global Deep Linking (Universal Links & App Links)** β€” Easily serve iOS `apple-app-site-association` and Android `.well-known/assetlinks.json` configuration files directly from your root domain to support OS-level native integration (disabled by default, managed via Settings). - **Central Retargeting Pixel Registry** β€” Introduced a premium Many-to-Many pixel management registry. Define pixels centrally (Meta Pixel, Google Tag, LinkedIn Insight, TikTok Pixel, Pinterest Tag) and easily associate them with short links via the Filament panel or the REST API. +- **Standalone Settings Page** β€” Relocated the Settings interface from a resource header sub-action to a standalone sidebar navigation page under the default plugin group. - **Backward-Compatible REST API** β€” The API now exposes the `pixels` relationship list, while fully retaining backward-compatible support for legacy single-pixel parameters (`pixel_meta_id`, `pixel_google_id`, `pixel_linkedin_id`). - **Enhanced Browser Language Redirection** β€” Robust double-pass language targeting logic matching exact locales first (e.g. `en-US`, `zh-CN`) and falling back to base language codes (e.g. `en`, `zh`). +- **Full Localization & WhatsApp Favicon Fix** β€” Added friendly translation strings in English and Polish across the entire app-linking preview and redirect interfaces, and adjusted domains order to restore the WhatsApp favicon. +- **Custom Branded Expiry Pages** β€” Replaced raw 410 HTTP errors with a beautiful, fully localized, dark-mode compatible HTML expiry page displaying the Site Name, expired link details, and a homepage button. ### v2.0.0 - **Interactive QR Code Designer Branding Logo** β€” Upload custom brand logos inside the QR designer canvas in Filament. Configure logo sizing, margins, shapes (square/circle), and toggle dot backing removal to prevent dots overlapping with the logo. diff --git a/config/filament-short-url.php b/config/filament-short-url.php index 3611238..3965894 100644 --- a/config/filament-short-url.php +++ b/config/filament-short-url.php @@ -217,4 +217,47 @@ return [ 'throttle:120,1', ], + /* + |-------------------------------------------------------------------------- + | Deep Linking v2.1 + |-------------------------------------------------------------------------- + | Universal Links (iOS) and App Links (Android) configuration. + | + */ + 'deep_linking' => [ + 'enabled' => env('SHORT_URL_DEEP_LINKING_ENABLED', false), + 'aasa_json' => env('SHORT_URL_AASA_JSON', <<<'JSON' +{ + "applinks": { + "apps": [], + "details": [ + { + "appID": "YOUR_TEAM_ID.com.yourcompany.app", + "paths": [ + "/s/*" + ] + } + ] + } +} +JSON), + 'assetlinks_json' => env('SHORT_URL_ASSETLINKS_JSON', <<<'JSON' +[ + { + "relation": [ + "delegate_permission/common.handle_all_urls" + ], + "target": { + "namespace": "android_app", + "package_name": "com.yourcompany.app", + "sha256_cert_fingerprints": [ + "14:6D:E9:..." + ] + } + } +] +JSON), + ], + ]; + diff --git a/database/migrations/2026_06_03_160000_add_auto_open_app_mobile_to_short_urls_table.php b/database/migrations/2026_06_03_160000_add_auto_open_app_mobile_to_short_urls_table.php new file mode 100644 index 0000000..598a50d --- /dev/null +++ b/database/migrations/2026_06_03_160000_add_auto_open_app_mobile_to_short_urls_table.php @@ -0,0 +1,22 @@ +boolean('auto_open_app_mobile')->default(false)->after('forward_query_params'); + }); + } + + public function down(): void + { + Schema::table('short_urls', function (Blueprint $table) { + $table->dropColumn('auto_open_app_mobile'); + }); + } +}; diff --git a/resources/dist/filament-short-url.css b/resources/dist/filament-short-url.css index 34d1218..c776cea 100644 --- a/resources/dist/filament-short-url.css +++ b/resources/dist/filament-short-url.css @@ -1,2 +1,2 @@ /*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */ -@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-content:""}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-serif:ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-red-900:oklch(39.6% .141 25.723);--color-red-950:oklch(25.8% .092 26.042);--color-orange-50:oklch(98% .016 73.684);--color-orange-100:oklch(95.4% .038 75.164);--color-orange-200:oklch(90.1% .076 70.697);--color-orange-300:oklch(83.7% .128 66.29);--color-orange-400:oklch(75% .183 55.934);--color-orange-500:oklch(70.5% .213 47.604);--color-orange-600:oklch(64.6% .222 41.116);--color-orange-700:oklch(55.3% .195 38.402);--color-orange-800:oklch(47% .157 37.304);--color-orange-900:oklch(40.8% .123 38.172);--color-orange-950:oklch(26.6% .079 36.259);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-800:oklch(47.3% .137 46.201);--color-amber-900:oklch(41.4% .112 45.904);--color-amber-950:oklch(27.9% .077 45.635);--color-yellow-50:oklch(98.7% .026 102.212);--color-yellow-100:oklch(97.3% .071 103.193);--color-yellow-200:oklch(94.5% .129 101.54);--color-yellow-300:oklch(90.5% .182 98.111);--color-yellow-400:oklch(85.2% .199 91.936);--color-yellow-500:oklch(79.5% .184 86.047);--color-yellow-600:oklch(68.1% .162 75.834);--color-yellow-700:oklch(55.4% .135 66.442);--color-yellow-800:oklch(47.6% .114 61.907);--color-yellow-900:oklch(42.1% .095 57.708);--color-yellow-950:oklch(28.6% .066 53.813);--color-lime-50:oklch(98.6% .031 120.757);--color-lime-100:oklch(96.7% .067 122.328);--color-lime-200:oklch(93.8% .127 124.321);--color-lime-300:oklch(89.7% .196 126.665);--color-lime-400:oklch(84.1% .238 128.85);--color-lime-500:oklch(76.8% .233 130.85);--color-lime-600:oklch(64.8% .2 131.684);--color-lime-700:oklch(53.2% .157 131.589);--color-lime-800:oklch(45.3% .124 130.933);--color-lime-900:oklch(40.5% .101 131.063);--color-lime-950:oklch(27.4% .072 132.109);--color-green-50:oklch(98.2% .018 155.826);--color-green-100:oklch(96.2% .044 156.743);--color-green-200:oklch(92.5% .084 155.995);--color-green-300:oklch(87.1% .15 154.449);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-green-800:oklch(44.8% .119 151.328);--color-green-900:oklch(39.3% .095 152.535);--color-green-950:oklch(26.6% .065 152.934);--color-emerald-50:oklch(97.9% .021 166.113);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-200:oklch(90.5% .093 164.15);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-700:oklch(50.8% .118 165.612);--color-emerald-800:oklch(43.2% .095 166.913);--color-emerald-900:oklch(37.8% .077 168.94);--color-emerald-950:oklch(26.2% .051 172.552);--color-teal-50:oklch(98.4% .014 180.72);--color-teal-100:oklch(95.3% .051 180.801);--color-teal-200:oklch(91% .096 180.426);--color-teal-300:oklch(85.5% .138 181.071);--color-teal-400:oklch(77.7% .152 181.912);--color-teal-500:oklch(70.4% .14 182.503);--color-teal-600:oklch(60% .118 184.704);--color-teal-700:oklch(51.1% .096 186.391);--color-teal-800:oklch(43.7% .078 188.216);--color-teal-900:oklch(38.6% .063 188.416);--color-teal-950:oklch(27.7% .046 192.524);--color-cyan-50:oklch(98.4% .019 200.873);--color-cyan-100:oklch(95.6% .045 203.388);--color-cyan-200:oklch(91.7% .08 205.041);--color-cyan-300:oklch(86.5% .127 207.078);--color-cyan-400:oklch(78.9% .154 211.53);--color-cyan-500:oklch(71.5% .143 215.221);--color-cyan-600:oklch(60.9% .126 221.723);--color-cyan-700:oklch(52% .105 223.128);--color-cyan-800:oklch(45% .085 224.283);--color-cyan-900:oklch(39.8% .07 227.392);--color-cyan-950:oklch(30.2% .056 229.695);--color-sky-50:oklch(97.7% .013 236.62);--color-sky-100:oklch(95.1% .026 236.824);--color-sky-200:oklch(90.1% .058 230.902);--color-sky-300:oklch(82.8% .111 230.318);--color-sky-400:oklch(74.6% .16 232.661);--color-sky-500:oklch(68.5% .169 237.323);--color-sky-600:oklch(58.8% .158 241.966);--color-sky-700:oklch(50% .134 242.749);--color-sky-800:oklch(44.3% .11 240.79);--color-sky-900:oklch(39.1% .09 240.876);--color-sky-950:oklch(29.3% .066 243.157);--color-blue-50:oklch(97% .014 254.604);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-800:oklch(42.4% .199 265.638);--color-blue-900:oklch(37.9% .146 265.522);--color-blue-950:oklch(28.2% .091 267.935);--color-indigo-50:oklch(96.2% .018 272.314);--color-indigo-100:oklch(93% .034 272.788);--color-indigo-200:oklch(87% .065 274.039);--color-indigo-300:oklch(78.5% .115 274.713);--color-indigo-400:oklch(67.3% .182 276.935);--color-indigo-500:oklch(58.5% .233 277.117);--color-indigo-600:oklch(51.1% .262 276.966);--color-indigo-700:oklch(45.7% .24 277.023);--color-indigo-800:oklch(39.8% .195 277.366);--color-indigo-900:oklch(35.9% .144 278.697);--color-indigo-950:oklch(25.7% .09 281.288);--color-violet-50:oklch(96.9% .016 293.756);--color-violet-100:oklch(94.3% .029 294.588);--color-violet-200:oklch(89.4% .057 293.283);--color-violet-300:oklch(81.1% .111 293.571);--color-violet-400:oklch(70.2% .183 293.541);--color-violet-500:oklch(60.6% .25 292.717);--color-violet-600:oklch(54.1% .281 293.009);--color-violet-700:oklch(49.1% .27 292.581);--color-violet-800:oklch(43.2% .232 292.759);--color-violet-900:oklch(38% .189 293.745);--color-violet-950:oklch(28.3% .141 291.089);--color-purple-50:oklch(97.7% .014 308.299);--color-purple-100:oklch(94.6% .033 307.174);--color-purple-200:oklch(90.2% .063 306.703);--color-purple-300:oklch(82.7% .119 306.383);--color-purple-400:oklch(71.4% .203 305.504);--color-purple-500:oklch(62.7% .265 303.9);--color-purple-600:oklch(55.8% .288 302.321);--color-purple-700:oklch(49.6% .265 301.924);--color-purple-800:oklch(43.8% .218 303.724);--color-purple-900:oklch(38.1% .176 304.987);--color-purple-950:oklch(29.1% .149 302.717);--color-fuchsia-50:oklch(97.7% .017 320.058);--color-fuchsia-100:oklch(95.2% .037 318.852);--color-fuchsia-200:oklch(90.3% .076 319.62);--color-fuchsia-300:oklch(83.3% .145 321.434);--color-fuchsia-400:oklch(74% .238 322.16);--color-fuchsia-500:oklch(66.7% .295 322.15);--color-fuchsia-600:oklch(59.1% .293 322.896);--color-fuchsia-700:oklch(51.8% .253 323.949);--color-fuchsia-800:oklch(45.2% .211 324.591);--color-fuchsia-900:oklch(40.1% .17 325.612);--color-fuchsia-950:oklch(29.3% .136 325.661);--color-pink-50:oklch(97.1% .014 343.198);--color-pink-100:oklch(94.8% .028 342.258);--color-pink-200:oklch(89.9% .061 343.231);--color-pink-300:oklch(82.3% .12 346.018);--color-pink-400:oklch(71.8% .202 349.761);--color-pink-500:oklch(65.6% .241 354.308);--color-pink-600:oklch(59.2% .249 .584);--color-pink-700:oklch(52.5% .223 3.958);--color-pink-800:oklch(45.9% .187 3.815);--color-pink-900:oklch(40.8% .153 2.432);--color-pink-950:oklch(28.4% .109 3.907);--color-rose-50:oklch(96.9% .015 12.422);--color-rose-100:oklch(94.1% .03 12.58);--color-rose-200:oklch(89.2% .058 10.001);--color-rose-300:oklch(81% .117 11.638);--color-rose-400:oklch(71.2% .194 13.428);--color-rose-500:oklch(64.5% .246 16.439);--color-rose-600:oklch(58.6% .253 17.585);--color-rose-700:oklch(51.4% .222 16.935);--color-rose-800:oklch(45.5% .188 13.697);--color-rose-900:oklch(41% .159 10.272);--color-rose-950:oklch(27.1% .105 12.094);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-slate-950:oklch(12.9% .042 264.695);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-gray-950:oklch(13% .028 261.692);--color-zinc-50:oklch(98.5% 0 0);--color-zinc-100:oklch(96.7% .001 286.375);--color-zinc-200:oklch(92% .004 286.32);--color-zinc-300:oklch(87.1% .006 286.286);--color-zinc-400:oklch(70.5% .015 286.067);--color-zinc-500:oklch(55.2% .016 285.938);--color-zinc-600:oklch(44.2% .017 285.786);--color-zinc-700:oklch(37% .013 285.805);--color-zinc-800:oklch(27.4% .006 286.033);--color-zinc-900:oklch(21% .006 285.885);--color-zinc-950:oklch(14.1% .005 285.823);--color-neutral-50:oklch(98.5% 0 0);--color-neutral-100:oklch(97% 0 0);--color-neutral-200:oklch(92.2% 0 0);--color-neutral-300:oklch(87% 0 0);--color-neutral-400:oklch(70.8% 0 0);--color-neutral-500:oklch(55.6% 0 0);--color-neutral-600:oklch(43.9% 0 0);--color-neutral-700:oklch(37.1% 0 0);--color-neutral-800:oklch(26.9% 0 0);--color-neutral-900:oklch(20.5% 0 0);--color-neutral-950:oklch(14.5% 0 0);--color-stone-50:oklch(98.5% .001 106.423);--color-stone-100:oklch(97% .001 106.424);--color-stone-200:oklch(92.3% .003 48.717);--color-stone-300:oklch(86.9% .005 56.366);--color-stone-400:oklch(70.9% .01 56.259);--color-stone-500:oklch(55.3% .013 58.071);--color-stone-600:oklch(44.4% .011 73.639);--color-stone-700:oklch(37.4% .01 67.558);--color-stone-800:oklch(26.8% .007 34.298);--color-stone-900:oklch(21.6% .006 56.043);--color-stone-950:oklch(14.7% .004 49.25);--color-black:#000;--color-white:#fff;--spacing:.25rem;--breakpoint-sm:40rem;--breakpoint-md:48rem;--breakpoint-lg:64rem;--breakpoint-xl:80rem;--breakpoint-2xl:96rem;--container-3xs:16rem;--container-2xs:18rem;--container-xs:20rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--container-3xl:48rem;--container-4xl:56rem;--container-5xl:64rem;--container-6xl:72rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--text-5xl:3rem;--text-5xl--line-height:1;--text-6xl:3.75rem;--text-6xl--line-height:1;--text-7xl:4.5rem;--text-7xl--line-height:1;--text-8xl:6rem;--text-8xl--line-height:1;--text-9xl:8rem;--text-9xl--line-height:1;--font-weight-thin:100;--font-weight-extralight:200;--font-weight-light:300;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--font-weight-black:900;--tracking-tighter:-.05em;--tracking-tight:-.025em;--tracking-normal:0em;--tracking-wide:.025em;--tracking-wider:.05em;--tracking-widest:.1em;--leading-tight:1.25;--leading-snug:1.375;--leading-normal:1.5;--leading-relaxed:1.625;--leading-loose:2;--radius-xs:.125rem;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--radius-3xl:1.5rem;--radius-4xl:2rem;--shadow-2xs:0 1px #0000000d;--shadow-xs:0 1px 2px 0 #0000000d;--shadow-sm:0 1px 3px 0 #0000001a, 0 1px 2px -1px #0000001a;--shadow-md:0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;--shadow-lg:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--shadow-xl:0 20px 25px -5px #0000001a, 0 8px 10px -6px #0000001a;--shadow-2xl:0 25px 50px -12px #00000040;--inset-shadow-2xs:inset 0 1px #0000000d;--inset-shadow-xs:inset 0 1px 1px #0000000d;--inset-shadow-sm:inset 0 2px 4px #0000000d;--drop-shadow-xs:0 1px 1px #0000000d;--drop-shadow-sm:0 1px 2px #00000026;--drop-shadow-md:0 3px 3px #0000001f;--drop-shadow-lg:0 4px 4px #00000026;--drop-shadow-xl:0 9px 7px #0000001a;--drop-shadow-2xl:0 25px 25px #00000026;--ease-in:cubic-bezier(.4, 0, 1, 1);--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--animate-bounce:bounce 1s infinite;--blur-xs:4px;--blur-sm:8px;--blur-md:12px;--blur-lg:16px;--blur-xl:24px;--blur-2xl:40px;--blur-3xl:64px;--perspective-dramatic:100px;--perspective-near:300px;--perspective-normal:500px;--perspective-midrange:800px;--perspective-distant:1200px;--aspect-video:16 / 9;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.\@container{container-type:inline-size}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.top-0{top:calc(var(--spacing) * 0)}.top-2{top:calc(var(--spacing) * 2)}.top-3{top:calc(var(--spacing) * 3)}.top-4{top:calc(var(--spacing) * 4)}.top-28{top:calc(var(--spacing) * 28)}.right-0{right:calc(var(--spacing) * 0)}.right-1{right:calc(var(--spacing) * 1)}.right-4{right:calc(var(--spacing) * 4)}.left-2{left:calc(var(--spacing) * 2)}.left-3{left:calc(var(--spacing) * 3)}.left-4{left:calc(var(--spacing) * 4)}.isolate{isolation:isolate}.z-0{z-index:0}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.col-span-2{grid-column:span 2/span 2}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.container\!{width:100%!important}@media (min-width:40rem){.container\!{max-width:40rem!important}}@media (min-width:48rem){.container\!{max-width:48rem!important}}@media (min-width:64rem){.container\!{max-width:64rem!important}}@media (min-width:80rem){.container\!{max-width:80rem!important}}@media (min-width:96rem){.container\!{max-width:96rem!important}}.m-0{margin:calc(var(--spacing) * 0)}.mx-auto{margin-inline:auto}.my-auto{margin-block:auto}.-mt-\[6\.6rem\]{margin-top:-6.6rem}.-mt-px{margin-top:-1px}.mt-0{margin-top:calc(var(--spacing) * 0)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-auto{margin-top:auto}.mr-2{margin-right:calc(var(--spacing) * 2)}.-mb-px{margin-bottom:-1px}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.mb-12{margin-bottom:calc(var(--spacing) * 12)}.-ml-8{margin-left:calc(var(--spacing) * -8)}.-ml-px{margin-left:-1px}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-4{margin-left:calc(var(--spacing) * 4)}.ml-12{margin-left:calc(var(--spacing) * 12)}.ml-auto{margin-left:auto}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline\!{display:inline!important}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.inline-grid{display:inline-grid}.inline-table{display:inline-table}.list-item{display:list-item}.table{display:table}.table\!{display:table!important}.table-caption{display:table-caption}.table-cell{display:table-cell}.table-column{display:table-column}.table-column-group{display:table-column-group}.table-footer-group{display:table-footer-group}.table-header-group{display:table-header-group}.table-row{display:table-row}.table-row-group{display:table-row-group}.aspect-\[4\/3\]{aspect-ratio:4/3}.aspect-\[335\/364\]{aspect-ratio:335/364}.aspect-video{aspect-ratio:var(--aspect-video)}.h-0{height:calc(var(--spacing) * 0)}.h-1{height:calc(var(--spacing) * 1)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-4\.5{height:calc(var(--spacing) * 4.5)}.h-5{height:calc(var(--spacing) * 5)}.h-5\.5{height:calc(var(--spacing) * 5.5)}.h-6{height:calc(var(--spacing) * 6)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-11{height:calc(var(--spacing) * 11)}.h-12{height:calc(var(--spacing) * 12)}.h-14{height:calc(var(--spacing) * 14)}.h-14\.5{height:calc(var(--spacing) * 14.5)}.h-16{height:calc(var(--spacing) * 16)}.h-20{height:calc(var(--spacing) * 20)}.h-\[1px\]{height:1px}.h-\[55vh\]{height:55vh}.h-\[60px\]{height:60px}.h-\[65vh\]{height:65vh}.h-\[85vh\]{height:85vh}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-0{width:calc(var(--spacing) * 0)}.w-1{width:calc(var(--spacing) * 1)}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-2{width:calc(var(--spacing) * 2)}.w-2\.5{width:calc(var(--spacing) * 2.5)}.w-3{width:calc(var(--spacing) * 3)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-4\.5{width:calc(var(--spacing) * 4.5)}.w-5{width:calc(var(--spacing) * 5)}.w-5\.5{width:calc(var(--spacing) * 5.5)}.w-6{width:calc(var(--spacing) * 6)}.w-8{width:calc(var(--spacing) * 8)}.w-9{width:calc(var(--spacing) * 9)}.w-10{width:calc(var(--spacing) * 10)}.w-11{width:calc(var(--spacing) * 11)}.w-12{width:calc(var(--spacing) * 12)}.w-28{width:calc(var(--spacing) * 28)}.w-32{width:calc(var(--spacing) * 32)}.w-\[438px\]{width:438px}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-7xl{max-width:var(--container-7xl)}.max-w-\[50ch\]{max-width:50ch}.max-w-\[200px\]{max-width:200px}.max-w-\[335px\]{max-width:335px}.max-w-\[360px\]{max-width:360px}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-none{max-width:none}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing) * 0)}.flex-1{flex:1}.flex-shrink{flex-shrink:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.flex-grow,.grow{flex-grow:1}.border-collapse{border-collapse:collapse}.translate-y-0{--tw-translate-y:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-y-4{--tw-translate-y:calc(var(--spacing) * 4);translate:var(--tw-translate-x) var(--tw-translate-y)}.-rotate-90{rotate:-90deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.transform\!{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)!important}.animate-bounce{animation:var(--animate-bounce)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.resize\!{resize:both!important}.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-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.justify-items-center{justify-items:center}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-3\.5{gap:calc(var(--spacing) * 3.5)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}.gap-8{gap:calc(var(--spacing) * 8)}.gap-12{gap:calc(var(--spacing) * 12)}.gap-16{gap:calc(var(--spacing) * 16)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-10>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 10) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 10) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-16>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 16) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 16) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-x-6{column-gap:calc(var(--spacing) * 6)}:where(.space-x-1>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 1) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-6>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 6) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-x-reverse)))}.gap-y-1{row-gap:calc(var(--spacing) * 1)}.gap-y-2{row-gap:calc(var(--spacing) * 2)}.gap-y-6{row-gap:calc(var(--spacing) * 6)}.self-end{align-self:flex-end}.self-start{align-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.scroll-smooth{scroll-behavior:smooth}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-3xl{border-radius:var(--radius-3xl)}.rounded-\[6px\]{border-radius:6px}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t-lg{border-top-left-radius:var(--radius-lg);border-top-right-radius:var(--radius-lg)}.rounded-l-md{border-top-left-radius:var(--radius-md);border-bottom-left-radius:var(--radius-md)}.rounded-r-md{border-top-right-radius:var(--radius-md);border-bottom-right-radius:var(--radius-md)}.rounded-br-lg{border-bottom-right-radius:var(--radius-lg)}.rounded-bl-lg{border-bottom-left-radius:var(--radius-lg)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-\[\#19140035\]{border-color:#19140035}.border-\[\#e3e3e0\]{border-color:#e3e3e0}.border-amber-200{border-color:var(--color-amber-200)}.border-black{border-color:var(--color-black)}.border-cyan-500{border-color:var(--color-cyan-500)}.border-cyan-500\/20{border-color:#00b7d733}@supports (color:color-mix(in lab, red, red)){.border-cyan-500\/20{border-color:color-mix(in oklab, var(--color-cyan-500) 20%, transparent)}}.border-cyan-500\/30{border-color:#00b7d74d}@supports (color:color-mix(in lab, red, red)){.border-cyan-500\/30{border-color:color-mix(in oklab, var(--color-cyan-500) 30%, transparent)}}.border-emerald-200{border-color:var(--color-emerald-200)}.border-emerald-400{border-color:var(--color-emerald-400)}.border-emerald-500\/20{border-color:#00bb7f33}@supports (color:color-mix(in lab, red, red)){.border-emerald-500\/20{border-color:color-mix(in oklab, var(--color-emerald-500) 20%, transparent)}}.border-gray-100{border-color:var(--color-gray-100)}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-200\/50{border-color:#e5e7eb80}@supports (color:color-mix(in lab, red, red)){.border-gray-200\/50{border-color:color-mix(in oklab, var(--color-gray-200) 50%, transparent)}}.border-gray-300{border-color:var(--color-gray-300)}.border-gray-400{border-color:var(--color-gray-400)}.border-neutral-200{border-color:var(--color-neutral-200)}.border-neutral-900{border-color:var(--color-neutral-900)}.border-red-100{border-color:var(--color-red-100)}.border-rose-100{border-color:var(--color-rose-100)}.border-rose-400{border-color:var(--color-rose-400)}.border-slate-700{border-color:var(--color-slate-700)}.border-slate-800{border-color:var(--color-slate-800)}.border-slate-900{border-color:var(--color-slate-900)}.border-transparent{border-color:#0000}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.border-white\/10{border-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.border-white\/20{border-color:#fff3}@supports (color:color-mix(in lab, red, red)){.border-white\/20{border-color:color-mix(in oklab, var(--color-white) 20%, transparent)}}.bg-\[\#0f1419\]{background-color:#0f1419}.bg-\[\#1b1b18\]{background-color:#1b1b18}.bg-\[\#6b7280\]{background-color:#6b7280}.bg-\[\#25d366\]{background-color:#25d366}.bg-\[\#0077b5\]{background-color:#0077b5}.bg-\[\#1877f2\]{background-color:#1877f2}.bg-\[\#FCFCFC\]{background-color:#fcfcfc}.bg-\[\#FDFDFC\]{background-color:#fdfdfc}.bg-\[\#dbdbd7\]{background-color:#dbdbd7}.bg-\[\#f4f4f5\]{background-color:#f4f4f5}.bg-\[\#fff2f2\]{background-color:#fff2f2}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-amber-500\/10{background-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\/10{background-color:color-mix(in oklab, var(--color-amber-500) 10%, transparent)}}.bg-blue-50{background-color:var(--color-blue-50)}.bg-blue-500\/10{background-color:#3080ff1a}@supports (color:color-mix(in lab, red, red)){.bg-blue-500\/10{background-color:color-mix(in oklab, var(--color-blue-500) 10%, transparent)}}.bg-cyan-50{background-color:var(--color-cyan-50)}.bg-cyan-400{background-color:var(--color-cyan-400)}.bg-cyan-500{background-color:var(--color-cyan-500)}.bg-cyan-500\/10{background-color:#00b7d71a}@supports (color:color-mix(in lab, red, red)){.bg-cyan-500\/10{background-color:color-mix(in oklab, var(--color-cyan-500) 10%, transparent)}}.bg-cyan-950\/40{background-color:#05334566}@supports (color:color-mix(in lab, red, red)){.bg-cyan-950\/40{background-color:color-mix(in oklab, var(--color-cyan-950) 40%, transparent)}}.bg-emerald-50{background-color:var(--color-emerald-50)}.bg-emerald-100{background-color:var(--color-emerald-100)}.bg-emerald-500{background-color:var(--color-emerald-500)}.bg-emerald-500\/10{background-color:#00bb7f1a}@supports (color:color-mix(in lab, red, red)){.bg-emerald-500\/10{background-color:color-mix(in oklab, var(--color-emerald-500) 10%, transparent)}}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-200{background-color:var(--color-gray-200)}.bg-gray-500\/10{background-color:#6a72821a}@supports (color:color-mix(in lab, red, red)){.bg-gray-500\/10{background-color:color-mix(in oklab, var(--color-gray-500) 10%, transparent)}}.bg-gray-900{background-color:var(--color-gray-900)}.bg-gray-950\/40{background-color:#03071266}@supports (color:color-mix(in lab, red, red)){.bg-gray-950\/40{background-color:color-mix(in oklab, var(--color-gray-950) 40%, transparent)}}.bg-indigo-50{background-color:var(--color-indigo-50)}.bg-indigo-500{background-color:var(--color-indigo-500)}.bg-neutral-200{background-color:var(--color-neutral-200)}.bg-neutral-900{background-color:var(--color-neutral-900)}.bg-pink-50{background-color:var(--color-pink-50)}.bg-pink-500\/10{background-color:#f6339a1a}@supports (color:color-mix(in lab, red, red)){.bg-pink-500\/10{background-color:color-mix(in oklab, var(--color-pink-500) 10%, transparent)}}.bg-purple-50{background-color:var(--color-purple-50)}.bg-purple-500\/10{background-color:#ac4bff1a}@supports (color:color-mix(in lab, red, red)){.bg-purple-500\/10{background-color:color-mix(in oklab, var(--color-purple-500) 10%, transparent)}}.bg-red-50{background-color:var(--color-red-50)}.bg-red-500\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.bg-red-500\/10{background-color:color-mix(in oklab, var(--color-red-500) 10%, transparent)}}.bg-rose-50{background-color:var(--color-rose-50)}.bg-rose-50\/50{background-color:#fff1f280}@supports (color:color-mix(in lab, red, red)){.bg-rose-50\/50{background-color:color-mix(in oklab, var(--color-rose-50) 50%, transparent)}}.bg-rose-500{background-color:var(--color-rose-500)}.bg-sky-50{background-color:var(--color-sky-50)}.bg-slate-800{background-color:var(--color-slate-800)}.bg-slate-900{background-color:var(--color-slate-900)}.bg-slate-900\/60{background-color:#0f172b99}@supports (color:color-mix(in lab, red, red)){.bg-slate-900\/60{background-color:color-mix(in oklab, var(--color-slate-900) 60%, transparent)}}.bg-slate-900\/80{background-color:#0f172bcc}@supports (color:color-mix(in lab, red, red)){.bg-slate-900\/80{background-color:color-mix(in oklab, var(--color-slate-900) 80%, transparent)}}.bg-slate-950{background-color:var(--color-slate-950)}.bg-teal-50{background-color:var(--color-teal-50)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-white\/40{background-color:#fff6}@supports (color:color-mix(in lab, red, red)){.bg-white\/40{background-color:color-mix(in oklab, var(--color-white) 40%, transparent)}}.bg-white\/60{background-color:#fff9}@supports (color:color-mix(in lab, red, red)){.bg-white\/60{background-color:color-mix(in oklab, var(--color-white) 60%, transparent)}}.bg-white\/80{background-color:#fffc}@supports (color:color-mix(in lab, red, red)){.bg-white\/80{background-color:color-mix(in oklab, var(--color-white) 80%, transparent)}}.bg-white\/95{background-color:#fffffff2}@supports (color:color-mix(in lab, red, red)){.bg-white\/95{background-color:color-mix(in oklab, var(--color-white) 95%, transparent)}}.bg-gradient-to-b{--tw-gradient-position:to bottom in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-r{--tw-gradient-position:to right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-t{--tw-gradient-position:to top in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-tr{--tw-gradient-position:to top right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-\[radial-gradient\(ellipse_at_top_right\,_var\(--tw-gradient-stops\)\)\]{background-image:radial-gradient(ellipse at top right, var(--tw-gradient-stops))}.from-\[\#006aff\]{--tw-gradient-from:#006aff;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-cyan-400{--tw-gradient-from:var(--color-cyan-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-cyan-500{--tw-gradient-from:var(--color-cyan-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-cyan-900\/30{--tw-gradient-from:#104e644d}@supports (color:color-mix(in lab, red, red)){.from-cyan-900\/30{--tw-gradient-from:color-mix(in oklab, var(--color-cyan-900) 30%, transparent)}}.from-cyan-900\/30{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-slate-900{--tw-gradient-from:var(--color-slate-900);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-slate-950{--tw-gradient-from:var(--color-slate-950);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-white{--tw-gradient-from:var(--color-white);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.via-\[\#00b2ff\]{--tw-gradient-via:#00b2ff;--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-slate-200{--tw-gradient-via:var(--color-slate-200);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-slate-900{--tw-gradient-via:var(--color-slate-900);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-slate-900\/40{--tw-gradient-via:#0f172b66}@supports (color:color-mix(in lab, red, red)){.via-slate-900\/40{--tw-gradient-via:color-mix(in oklab, var(--color-slate-900) 40%, transparent)}}.via-slate-900\/40{--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-slate-950{--tw-gradient-via:var(--color-slate-950);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-teal-300{--tw-gradient-via:var(--color-teal-300);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.to-\[\#00d6ff\]{--tw-gradient-to:#00d6ff;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-blue-500{--tw-gradient-to:var(--color-blue-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-blue-600{--tw-gradient-to:var(--color-blue-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-cyan-400{--tw-gradient-to:var(--color-cyan-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-slate-950{--tw-gradient-to:var(--color-slate-950);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-transparent{--tw-gradient-to:transparent;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.bg-clip-text{-webkit-background-clip:text;background-clip:text}.mask-repeat{-webkit-mask-repeat:repeat;mask-repeat:repeat}.object-contain{object-fit:contain}.object-cover{object-fit:cover}.p-0{padding:calc(var(--spacing) * 0)}.p-1{padding:calc(var(--spacing) * 1)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.px-0\.5{padding-inline:calc(var(--spacing) * .5)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-10{padding-block:calc(var(--spacing) * 10)}.py-12{padding-block:calc(var(--spacing) * 12)}.py-16{padding-block:calc(var(--spacing) * 16)}.py-20{padding-block:calc(var(--spacing) * 20)}.py-24{padding-block:calc(var(--spacing) * 24)}.pt-1{padding-top:calc(var(--spacing) * 1)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-8{padding-top:calc(var(--spacing) * 8)}.pr-4{padding-right:calc(var(--spacing) * 4)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-6{padding-bottom:calc(var(--spacing) * 6)}.pb-12{padding-bottom:calc(var(--spacing) * 12)}.pb-16{padding-bottom:calc(var(--spacing) * 16)}.pb-px{padding-bottom:1px}.pl-9{padding-left:calc(var(--spacing) * 9)}.text-center{text-align:center}.text-justify{text-align:justify}.text-left{text-align:left}.font-\[\'Bricolage_Grotesque\'\]{font-family:Bricolage Grotesque}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-\[15px\]{font-size:15px}.text-\[16px\]{font-size:16px}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-6{--tw-leading:calc(var(--spacing) * 6);line-height:calc(var(--spacing) * 6)}.leading-7{--tw-leading:calc(var(--spacing) * 7);line-height:calc(var(--spacing) * 7)}.leading-\[16px\]{--tw-leading:16px;line-height:16px}.leading-\[20px\]{--tw-leading:20px;line-height:20px}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.text-wrap{text-wrap:wrap}.break-all{word-break:break-all}.text-\[\#1B1B18\],.text-\[\#1b1b18\]{color:#1b1b18}.text-\[\#2a5bd7\]{color:#2a5bd7}.text-\[\#706f6c\]{color:#706f6c}.text-\[\#273144\]{color:#273144}.text-\[\#F3BEC7\]{color:#f3bec7}.text-\[\#F8B803\]{color:#f8b803}.text-\[\#F53003\],.text-\[\#f53003\]{color:#f53003}.text-amber-500{color:var(--color-amber-500)}.text-amber-600{color:var(--color-amber-600)}.text-amber-800{color:var(--color-amber-800)}.text-black{color:var(--color-black)}.text-blue-500{color:var(--color-blue-500)}.text-cyan-400{color:var(--color-cyan-400)}.text-cyan-500{color:var(--color-cyan-500)}.text-emerald-400{color:var(--color-emerald-400)}.text-emerald-500{color:var(--color-emerald-500)}.text-emerald-600{color:var(--color-emerald-600)}.text-emerald-800{color:var(--color-emerald-800)}.text-gray-200{color:var(--color-gray-200)}.text-gray-300{color:var(--color-gray-300)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-gray-900{color:var(--color-gray-900)}.text-indigo-500{color:var(--color-indigo-500)}.text-indigo-600{color:var(--color-indigo-600)}.text-neutral-300{color:var(--color-neutral-300)}.text-neutral-400{color:var(--color-neutral-400)}.text-neutral-500{color:var(--color-neutral-500)}.text-neutral-900{color:var(--color-neutral-900)}.text-pink-500{color:var(--color-pink-500)}.text-purple-500{color:var(--color-purple-500)}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-rose-500{color:var(--color-rose-500)}.text-rose-700{color:var(--color-rose-700)}.text-sky-500{color:var(--color-sky-500)}.text-slate-100{color:var(--color-slate-100)}.text-slate-200{color:var(--color-slate-200)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-slate-950{color:var(--color-slate-950)}.text-teal-500{color:var(--color-teal-500)}.text-transparent{color:#0000}.text-white{color:var(--color-white)}.text-white\/80{color:#fffc}@supports (color:color-mix(in lab, red, red)){.text-white\/80{color:color-mix(in oklab, var(--color-white) 80%, transparent)}}.text-yellow-500{color:var(--color-yellow-500)}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.ordinal{--tw-ordinal:ordinal;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.line-through{text-decoration-line:line-through}.overline{text-decoration-line:overline}.underline{text-decoration-line:underline}.underline-offset-4{text-underline-offset:4px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.subpixel-antialiased{-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}.placeholder-neutral-300::placeholder{color:var(--color-neutral-300)}.placeholder-slate-500::placeholder{color:var(--color-slate-500)}.opacity-0{opacity:0}.opacity-25{opacity:.25}.opacity-40{opacity:.4}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.opacity-100{opacity:1}.mix-blend-color{mix-blend-mode:color}.mix-blend-darken{mix-blend-mode:darken}.mix-blend-hard-light{mix-blend-mode:hard-light}.mix-blend-multiply{mix-blend-mode:multiply}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0px_0px_1px_0px_rgba\(0\,0\,0\,0\.03\)\,0px_1px_2px_0px_rgba\(0\,0\,0\,0\.06\)\]{--tw-shadow:0px 0px 1px 0px var(--tw-shadow-color,#00000008), 0px 1px 2px 0px var(--tw-shadow-color,#0000000f);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[inset_0px_0px_0px_1px_rgba\(26\,26\,0\,0\.16\)\]{--tw-shadow:inset 0px 0px 0px 1px var(--tw-shadow-color,#1a1a0029);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-amber-500\/20{--tw-shadow-color:#f99c0033}@supports (color:color-mix(in lab, red, red)){.shadow-amber-500\/20{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-amber-500) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-pink-500\/10{--tw-shadow-color:#f6339a1a}@supports (color:color-mix(in lab, red, red)){.shadow-pink-500\/10{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-pink-500) 10%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-rose-500\/20{--tw-shadow-color:#ff235733}@supports (color:color-mix(in lab, red, red)){.shadow-rose-500\/20{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-rose-500) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.ring-gray-300{--tw-ring-color:var(--color-gray-300)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);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,)}.drop-shadow{--tw-drop-shadow-size:drop-shadow(0 1px 2px var(--tw-drop-shadow-color,#0000001a)) drop-shadow(0 1px 1px var(--tw-drop-shadow-color,#0000000f));--tw-drop-shadow:drop-shadow(0 1px 2px #0000001a) drop-shadow(0 1px 1px #0000000f);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,)}.grayscale{--tw-grayscale:grayscale(100%);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,)}.invert{--tw-invert:invert(100%);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,)}.sepia{--tw-sepia:sepia(100%);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,)}.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,)}.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,)!important}.backdrop-blur-md{--tw-backdrop-blur:blur(var(--blur-md));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.backdrop-blur-xl{--tw-backdrop-blur:blur(var(--blur-xl));-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-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,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.delay-200{transition-delay:.2s}.delay-300{transition-delay:.3s}.delay-400{transition-delay:.4s}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.duration-500{--tw-duration:.5s;transition-duration:.5s}.duration-750{--tw-duration:.75s;transition-duration:.75s}.ease-in{--tw-ease:var(--ease-in);transition-timing-function:var(--ease-in)}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.\[--stroke-color\:\#1B1B18\]{--stroke-color:#1b1b18}.not-has-\[nav\]\:hidden:not(:has(:is(nav))){display:none}@media (hover:hover){.group-hover\:scale-105:is(:where(.group):hover *){--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x) var(--tw-scale-y)}.group-hover\:scale-110:is(:where(.group):hover *){--tw-scale-x:110%;--tw-scale-y:110%;--tw-scale-z:110%;scale:var(--tw-scale-x) var(--tw-scale-y)}.group-hover\:rotate-12:is(:where(.group):hover *){rotate:12deg}.group-hover\:text-cyan-400:is(:where(.group):hover *){color:var(--color-cyan-400)}.group-hover\:text-gray-900:is(:where(.group):hover *){color:var(--color-gray-900)}.group-hover\:text-neutral-900:is(:where(.group):hover *){color:var(--color-neutral-900)}}.selection\:bg-cyan-500 ::selection{background-color:var(--color-cyan-500)}.selection\:bg-cyan-500::selection{background-color:var(--color-cyan-500)}.selection\:text-slate-900 ::selection{color:var(--color-slate-900)}.selection\:text-slate-900::selection{color:var(--color-slate-900)}.before\:absolute:before{content:var(--tw-content);position:absolute}.before\:top-0:before{content:var(--tw-content);top:calc(var(--spacing) * 0)}.before\:top-1\/2:before{content:var(--tw-content);top:50%}.before\:bottom-0:before{content:var(--tw-content);bottom:calc(var(--spacing) * 0)}.before\:bottom-1\/2:before{content:var(--tw-content);bottom:50%}.before\:left-\[0\.4rem\]:before{content:var(--tw-content);left:.4rem}.before\:border-l:before{content:var(--tw-content);border-left-style:var(--tw-border-style);border-left-width:1px}.before\:border-\[\#e3e3e0\]:before{content:var(--tw-content);border-color:#e3e3e0}.focus-within\:ring-2:focus-within{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-within\:ring-neutral-900:focus-within{--tw-ring-color:var(--color-neutral-900)}@media (hover:hover){.hover\:scale-105:hover{--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x) var(--tw-scale-y)}.hover\:border-\[\#1915014a\]:hover{border-color:#1915014a}.hover\:border-\[\#19140035\]:hover{border-color:#19140035}.hover\:border-amber-200\/50:hover{border-color:#fee68580}@supports (color:color-mix(in lab, red, red)){.hover\:border-amber-200\/50:hover{border-color:color-mix(in oklab, var(--color-amber-200) 50%, transparent)}}.hover\:border-black:hover{border-color:var(--color-black)}.hover\:border-emerald-200\/50:hover{border-color:#a4f4cf80}@supports (color:color-mix(in lab, red, red)){.hover\:border-emerald-200\/50:hover{border-color:color-mix(in oklab, var(--color-emerald-200) 50%, transparent)}}.hover\:border-indigo-200\/50:hover{border-color:#c7d2ff80}@supports (color:color-mix(in lab, red, red)){.hover\:border-indigo-200\/50:hover{border-color:color-mix(in oklab, var(--color-indigo-200) 50%, transparent)}}.hover\:border-pink-200\/50:hover{border-color:#fccee880}@supports (color:color-mix(in lab, red, red)){.hover\:border-pink-200\/50:hover{border-color:color-mix(in oklab, var(--color-pink-200) 50%, transparent)}}.hover\:border-purple-200\/50:hover{border-color:#e9d5ff80}@supports (color:color-mix(in lab, red, red)){.hover\:border-purple-200\/50:hover{border-color:color-mix(in oklab, var(--color-purple-200) 50%, transparent)}}.hover\:border-rose-200\/50:hover{border-color:#ffccd380}@supports (color:color-mix(in lab, red, red)){.hover\:border-rose-200\/50:hover{border-color:color-mix(in oklab, var(--color-rose-200) 50%, transparent)}}.hover\:border-sky-200\/50:hover{border-color:#b8e6fe80}@supports (color:color-mix(in lab, red, red)){.hover\:border-sky-200\/50:hover{border-color:color-mix(in oklab, var(--color-sky-200) 50%, transparent)}}.hover\:border-slate-600:hover{border-color:var(--color-slate-600)}.hover\:border-slate-700:hover{border-color:var(--color-slate-700)}.hover\:bg-\[\#e4e4e7\]:hover{background-color:#e4e4e7}.hover\:bg-amber-600:hover{background-color:var(--color-amber-600)}.hover\:bg-black:hover{background-color:var(--color-black)}.hover\:bg-cyan-400:hover{background-color:var(--color-cyan-400)}.hover\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\:bg-gray-100:hover{background-color:var(--color-gray-100)}.hover\:bg-gray-200:hover{background-color:var(--color-gray-200)}.hover\:bg-gray-800:hover{background-color:var(--color-gray-800)}.hover\:bg-neutral-50:hover{background-color:var(--color-neutral-50)}.hover\:bg-neutral-800:hover{background-color:var(--color-neutral-800)}.hover\:bg-rose-600:hover{background-color:var(--color-rose-600)}.hover\:bg-slate-700:hover{background-color:var(--color-slate-700)}.hover\:bg-slate-800:hover{background-color:var(--color-slate-800)}.hover\:from-cyan-400:hover{--tw-gradient-from:var(--color-cyan-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.hover\:to-blue-500:hover{--tw-gradient-to:var(--color-blue-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.hover\:text-cyan-300:hover{color:var(--color-cyan-300)}.hover\:text-cyan-400:hover{color:var(--color-cyan-400)}.hover\:text-gray-500:hover{color:var(--color-gray-500)}.hover\:text-gray-700:hover{color:var(--color-gray-700)}.hover\:text-neutral-600:hover{color:var(--color-neutral-600)}.hover\:text-neutral-900:hover{color:var(--color-neutral-900)}.hover\:text-slate-200:hover{color:var(--color-slate-200)}.hover\:text-white:hover{color:var(--color-white)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}.hover\:shadow:hover{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.hover\:shadow-amber-500\/30:hover{--tw-shadow-color:#f99c004d}@supports (color:color-mix(in lab, red, red)){.hover\:shadow-amber-500\/30:hover{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-amber-500) 30%, transparent) var(--tw-shadow-alpha), transparent)}}.hover\:shadow-cyan-500\/20:hover{--tw-shadow-color:#00b7d733}@supports (color:color-mix(in lab, red, red)){.hover\:shadow-cyan-500\/20:hover{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-cyan-500) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.hover\:shadow-pink-500\/20:hover{--tw-shadow-color:#f6339a33}@supports (color:color-mix(in lab, red, red)){.hover\:shadow-pink-500\/20:hover{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-pink-500) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.hover\:shadow-rose-500\/30:hover{--tw-shadow-color:#ff23574d}@supports (color:color-mix(in lab, red, red)){.hover\:shadow-rose-500\/30:hover{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-rose-500) 30%, transparent) var(--tw-shadow-alpha), transparent)}}}.focus\:border-amber-500:focus{border-color:var(--color-amber-500)}.focus\:border-emerald-500:focus{border-color:var(--color-emerald-500)}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-amber-500:focus{--tw-ring-color:var(--color-amber-500)}.focus\:ring-amber-500\/20:focus{--tw-ring-color:#f99c0033}@supports (color:color-mix(in lab, red, red)){.focus\:ring-amber-500\/20:focus{--tw-ring-color:color-mix(in oklab, var(--color-amber-500) 20%, transparent)}}.focus\:ring-cyan-500:focus{--tw-ring-color:var(--color-cyan-500)}.focus\:ring-emerald-500:focus{--tw-ring-color:var(--color-emerald-500)}.focus\:ring-gray-300:focus{--tw-ring-color:var(--color-gray-300)}.focus\:ring-rose-500:focus{--tw-ring-color:var(--color-rose-500)}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:text-black:disabled{color:var(--color-black)}.disabled\:opacity-50:disabled{opacity:.5}@media (min-width:40rem){.sm\:col-span-3{grid-column:span 3/span 3}.sm\:translate-y-0{--tw-translate-y:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.sm\:scale-95{--tw-scale-x:95%;--tw-scale-y:95%;--tw-scale-z:95%;scale:var(--tw-scale-x) var(--tw-scale-y)}.sm\:scale-100{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x) var(--tw-scale-y)}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:items-end{align-items:flex-end}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}.sm\:text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.sm\:text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.sm\:text-6xl{font-size:var(--text-6xl);line-height:var(--tw-leading,var(--text-6xl--line-height))}.sm\:text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}}@media (min-width:48rem){.md\:flex{display:flex}.md\:hidden{display:none}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}:where(.md\:space-y-0>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 0) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 0) * calc(1 - var(--tw-space-y-reverse)))}.md\:text-7xl{font-size:var(--text-7xl);line-height:var(--tw-leading,var(--text-7xl--line-height))}}@media (min-width:64rem){.lg\:col-span-1{grid-column:span 1/span 1}.lg\:col-span-2{grid-column:span 2/span 2}.lg\:col-span-3{grid-column:span 3/span 3}.lg\:mt-10{margin-top:calc(var(--spacing) * 10)}.lg\:mb-0{margin-bottom:calc(var(--spacing) * 0)}.lg\:mb-6{margin-bottom:calc(var(--spacing) * 6)}.lg\:-ml-px{margin-left:-1px}.lg\:ml-0{margin-left:calc(var(--spacing) * 0)}.lg\:block{display:block}.lg\:aspect-auto{aspect-ratio:auto}.lg\:w-1\/2{width:50%}.lg\:w-\[438px\]{width:438px}.lg\:max-w-4xl{max-width:var(--container-4xl)}.lg\:grow{flex-grow:1}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:flex-row{flex-direction:row}.lg\:flex-row-reverse{flex-direction:row-reverse}.lg\:justify-center{justify-content:center}.lg\:rounded-t-none{border-top-left-radius:0;border-top-right-radius:0}.lg\:rounded-tl-lg{border-top-left-radius:var(--radius-lg)}.lg\:rounded-r-lg{border-top-right-radius:var(--radius-lg);border-bottom-right-radius:var(--radius-lg)}.lg\:rounded-br-none{border-bottom-right-radius:0}.lg\:p-8{padding:calc(var(--spacing) * 8)}.lg\:p-20{padding:calc(var(--spacing) * 20)}.lg\:px-8{padding-inline:calc(var(--spacing) * 8)}.lg\:pb-10{padding-bottom:calc(var(--spacing) * 10)}}@media (min-width:80rem){.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (prefers-color-scheme:dark){.dark\:border-\[\#3E3E3A\]{border-color:#3e3e3a}.dark\:border-\[\#eeeeec\]{border-color:#eeeeec}.dark\:border-amber-900\/30{border-color:#7b33064d}@supports (color:color-mix(in lab, red, red)){.dark\:border-amber-900\/30{border-color:color-mix(in oklab, var(--color-amber-900) 30%, transparent)}}.dark\:border-emerald-800{border-color:var(--color-emerald-800)}.dark\:border-gray-700{border-color:var(--color-gray-700)}.dark\:border-gray-700\/50{border-color:#36415380}@supports (color:color-mix(in lab, red, red)){.dark\:border-gray-700\/50{border-color:color-mix(in oklab, var(--color-gray-700) 50%, transparent)}}.dark\:border-gray-800{border-color:var(--color-gray-800)}.dark\:border-gray-800\/10{border-color:#1e29391a}@supports (color:color-mix(in lab, red, red)){.dark\:border-gray-800\/10{border-color:color-mix(in oklab, var(--color-gray-800) 10%, transparent)}}.dark\:border-gray-800\/30{border-color:#1e29394d}@supports (color:color-mix(in lab, red, red)){.dark\:border-gray-800\/30{border-color:color-mix(in oklab, var(--color-gray-800) 30%, transparent)}}.dark\:border-neutral-800{border-color:var(--color-neutral-800)}.dark\:border-red-900\/30{border-color:#82181a4d}@supports (color:color-mix(in lab, red, red)){.dark\:border-red-900\/30{border-color:color-mix(in oklab, var(--color-red-900) 30%, transparent)}}.dark\:border-rose-950\/20{border-color:#4d021833}@supports (color:color-mix(in lab, red, red)){.dark\:border-rose-950\/20{border-color:color-mix(in oklab, var(--color-rose-950) 20%, transparent)}}.dark\:border-white{border-color:var(--color-white)}.dark\:bg-\[\#0C0C0C\]{background-color:#0c0c0c}.dark\:bg-\[\#0a0a0a\]{background-color:#0a0a0a}.dark\:bg-\[\#1D0002\]{background-color:#1d0002}.dark\:bg-\[\#3E3E3A\]{background-color:#3e3e3a}.dark\:bg-\[\#161615\]{background-color:#161615}.dark\:bg-\[\#eeeeec\]{background-color:#eeeeec}.dark\:bg-amber-950\/20{background-color:#46190133}@supports (color:color-mix(in lab, red, red)){.dark\:bg-amber-950\/20{background-color:color-mix(in oklab, var(--color-amber-950) 20%, transparent)}}.dark\:bg-amber-950\/30{background-color:#4619014d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-amber-950\/30{background-color:color-mix(in oklab, var(--color-amber-950) 30%, transparent)}}.dark\:bg-amber-950\/50{background-color:#46190180}@supports (color:color-mix(in lab, red, red)){.dark\:bg-amber-950\/50{background-color:color-mix(in oklab, var(--color-amber-950) 50%, transparent)}}.dark\:bg-blue-950\/50{background-color:#16245680}@supports (color:color-mix(in lab, red, red)){.dark\:bg-blue-950\/50{background-color:color-mix(in oklab, var(--color-blue-950) 50%, transparent)}}.dark\:bg-cyan-950\/50{background-color:#05334580}@supports (color:color-mix(in lab, red, red)){.dark\:bg-cyan-950\/50{background-color:color-mix(in oklab, var(--color-cyan-950) 50%, transparent)}}.dark\:bg-emerald-900{background-color:var(--color-emerald-900)}.dark\:bg-emerald-950{background-color:var(--color-emerald-950)}.dark\:bg-emerald-950\/30{background-color:#002c224d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-emerald-950\/30{background-color:color-mix(in oklab, var(--color-emerald-950) 30%, transparent)}}.dark\:bg-emerald-950\/50{background-color:#002c2280}@supports (color:color-mix(in lab, red, red)){.dark\:bg-emerald-950\/50{background-color:color-mix(in oklab, var(--color-emerald-950) 50%, transparent)}}.dark\:bg-gray-100{background-color:var(--color-gray-100)}.dark\:bg-gray-800{background-color:var(--color-gray-800)}.dark\:bg-gray-800\/50{background-color:#1e293980}@supports (color:color-mix(in lab, red, red)){.dark\:bg-gray-800\/50{background-color:color-mix(in oklab, var(--color-gray-800) 50%, transparent)}}.dark\:bg-gray-900{background-color:var(--color-gray-900)}.dark\:bg-gray-900\/40{background-color:#10182866}@supports (color:color-mix(in lab, red, red)){.dark\:bg-gray-900\/40{background-color:color-mix(in oklab, var(--color-gray-900) 40%, transparent)}}.dark\:bg-gray-900\/50{background-color:#10182880}@supports (color:color-mix(in lab, red, red)){.dark\:bg-gray-900\/50{background-color:color-mix(in oklab, var(--color-gray-900) 50%, transparent)}}.dark\:bg-gray-900\/60{background-color:#10182899}@supports (color:color-mix(in lab, red, red)){.dark\:bg-gray-900\/60{background-color:color-mix(in oklab, var(--color-gray-900) 60%, transparent)}}.dark\:bg-gray-900\/95{background-color:#101828f2}@supports (color:color-mix(in lab, red, red)){.dark\:bg-gray-900\/95{background-color:color-mix(in oklab, var(--color-gray-900) 95%, transparent)}}.dark\:bg-gray-950{background-color:var(--color-gray-950)}.dark\:bg-gray-950\/80{background-color:#030712cc}@supports (color:color-mix(in lab, red, red)){.dark\:bg-gray-950\/80{background-color:color-mix(in oklab, var(--color-gray-950) 80%, transparent)}}.dark\:bg-indigo-950\/30{background-color:#1e1a4d4d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-indigo-950\/30{background-color:color-mix(in oklab, var(--color-indigo-950) 30%, transparent)}}.dark\:bg-indigo-950\/50{background-color:#1e1a4d80}@supports (color:color-mix(in lab, red, red)){.dark\:bg-indigo-950\/50{background-color:color-mix(in oklab, var(--color-indigo-950) 50%, transparent)}}.dark\:bg-neutral-800{background-color:var(--color-neutral-800)}.dark\:bg-neutral-900{background-color:var(--color-neutral-900)}.dark\:bg-pink-950\/30{background-color:#5104244d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-pink-950\/30{background-color:color-mix(in oklab, var(--color-pink-950) 30%, transparent)}}.dark\:bg-purple-950\/30{background-color:#3c03664d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-purple-950\/30{background-color:color-mix(in oklab, var(--color-purple-950) 30%, transparent)}}.dark\:bg-purple-950\/50{background-color:#3c036680}@supports (color:color-mix(in lab, red, red)){.dark\:bg-purple-950\/50{background-color:color-mix(in oklab, var(--color-purple-950) 50%, transparent)}}.dark\:bg-red-950\/20{background-color:#46080933}@supports (color:color-mix(in lab, red, red)){.dark\:bg-red-950\/20{background-color:color-mix(in oklab, var(--color-red-950) 20%, transparent)}}.dark\:bg-rose-950\/10{background-color:#4d02181a}@supports (color:color-mix(in lab, red, red)){.dark\:bg-rose-950\/10{background-color:color-mix(in oklab, var(--color-rose-950) 10%, transparent)}}.dark\:bg-rose-950\/30{background-color:#4d02184d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-rose-950\/30{background-color:color-mix(in oklab, var(--color-rose-950) 30%, transparent)}}.dark\:bg-rose-950\/50{background-color:#4d021880}@supports (color:color-mix(in lab, red, red)){.dark\:bg-rose-950\/50{background-color:color-mix(in oklab, var(--color-rose-950) 50%, transparent)}}.dark\:bg-sky-950\/30{background-color:#052f4a4d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-sky-950\/30{background-color:color-mix(in oklab, var(--color-sky-950) 30%, transparent)}}.dark\:bg-teal-950\/50{background-color:#022f2e80}@supports (color:color-mix(in lab, red, red)){.dark\:bg-teal-950\/50{background-color:color-mix(in oklab, var(--color-teal-950) 50%, transparent)}}.dark\:bg-white{background-color:var(--color-white)}.dark\:text-\[\#1C1C1A\]{color:#1c1c1a}.dark\:text-\[\#4B0600\]{color:#4b0600}.dark\:text-\[\#391800\]{color:#391800}.dark\:text-\[\#733000\]{color:#733000}.dark\:text-\[\#A1A09A\]{color:#a1a09a}.dark\:text-\[\#EDEDEC\]{color:#ededec}.dark\:text-\[\#F61500\]{color:#f61500}.dark\:text-\[\#FF4433\]{color:#f43}.dark\:text-amber-300{color:var(--color-amber-300)}.dark\:text-amber-400{color:var(--color-amber-400)}.dark\:text-amber-500{color:var(--color-amber-500)}.dark\:text-black{color:var(--color-black)}.dark\:text-blue-400{color:var(--color-blue-400)}.dark\:text-cyan-400{color:var(--color-cyan-400)}.dark\:text-emerald-200{color:var(--color-emerald-200)}.dark\:text-emerald-400{color:var(--color-emerald-400)}.dark\:text-gray-100{color:var(--color-gray-100)}.dark\:text-gray-200{color:var(--color-gray-200)}.dark\:text-gray-300{color:var(--color-gray-300)}.dark\:text-gray-400{color:var(--color-gray-400)}.dark\:text-gray-500{color:var(--color-gray-500)}.dark\:text-gray-800{color:var(--color-gray-800)}.dark\:text-gray-950{color:var(--color-gray-950)}.dark\:text-indigo-400{color:var(--color-indigo-400)}.dark\:text-neutral-400{color:var(--color-neutral-400)}.dark\:text-neutral-500{color:var(--color-neutral-500)}.dark\:text-neutral-600{color:var(--color-neutral-600)}.dark\:text-neutral-700{color:var(--color-neutral-700)}.dark\:text-neutral-900{color:var(--color-neutral-900)}.dark\:text-neutral-950{color:var(--color-neutral-950)}.dark\:text-purple-400{color:var(--color-purple-400)}.dark\:text-red-400{color:var(--color-red-400)}.dark\:text-rose-400{color:var(--color-rose-400)}.dark\:text-teal-400{color:var(--color-teal-400)}.dark\:text-white{color:var(--color-white)}.dark\:placeholder-neutral-700::placeholder{color:var(--color-neutral-700)}.dark\:mix-blend-hard-light{mix-blend-mode:hard-light}.dark\:mix-blend-normal{mix-blend-mode:normal}.dark\:shadow-\[inset_0px_0px_0px_1px_\#fffaed2d\]{--tw-shadow:inset 0px 0px 0px 1px var(--tw-shadow-color,#fffaed2d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.dark\:\[--stroke-color\:\#FF750F\]{--stroke-color:#ff750f}@media (hover:hover){.dark\:group-hover\:text-white:is(:where(.group):hover *){color:var(--color-white)}}.dark\:before\:border-\[\#3E3E3A\]:before{content:var(--tw-content);border-color:#3e3e3a}.dark\:focus-within\:ring-white:focus-within{--tw-ring-color:var(--color-white)}@media (hover:hover){.dark\:hover\:border-\[\#3E3E3A\]:hover{border-color:#3e3e3a}.dark\:hover\:border-\[\#62605b\]:hover{border-color:#62605b}.dark\:hover\:border-amber-900\/50:hover{border-color:#7b330680}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:border-amber-900\/50:hover{border-color:color-mix(in oklab, var(--color-amber-900) 50%, transparent)}}.dark\:hover\:border-emerald-900\/50:hover{border-color:#004e3b80}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:border-emerald-900\/50:hover{border-color:color-mix(in oklab, var(--color-emerald-900) 50%, transparent)}}.dark\:hover\:border-indigo-900\/50:hover{border-color:#312c8580}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:border-indigo-900\/50:hover{border-color:color-mix(in oklab, var(--color-indigo-900) 50%, transparent)}}.dark\:hover\:border-pink-900\/50:hover{border-color:#86104380}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:border-pink-900\/50:hover{border-color:color-mix(in oklab, var(--color-pink-900) 50%, transparent)}}.dark\:hover\:border-purple-900\/50:hover{border-color:#59168b80}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:border-purple-900\/50:hover{border-color:color-mix(in oklab, var(--color-purple-900) 50%, transparent)}}.dark\:hover\:border-rose-900\/50:hover{border-color:#8b083680}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:border-rose-900\/50:hover{border-color:color-mix(in oklab, var(--color-rose-900) 50%, transparent)}}.dark\:hover\:border-sky-900\/50:hover{border-color:#024a7080}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:border-sky-900\/50:hover{border-color:color-mix(in oklab, var(--color-sky-900) 50%, transparent)}}.dark\:hover\:border-white:hover{border-color:var(--color-white)}.dark\:hover\:bg-gray-700:hover{background-color:var(--color-gray-700)}.dark\:hover\:bg-gray-900:hover{background-color:var(--color-gray-900)}.dark\:hover\:bg-neutral-200:hover{background-color:var(--color-neutral-200)}.dark\:hover\:bg-neutral-800:hover{background-color:var(--color-neutral-800)}.dark\:hover\:bg-white:hover{background-color:var(--color-white)}.dark\:hover\:text-gray-200:hover{color:var(--color-gray-200)}.dark\:hover\:text-neutral-300:hover{color:var(--color-neutral-300)}.dark\:hover\:text-white:hover{color:var(--color-white)}}.dark\:focus\:border-amber-500:focus{border-color:var(--color-amber-500)}}@starting-style{.starting\:opacity-0{opacity:0}}@media (prefers-reduced-motion:no-preference){@starting-style{.motion-safe\:starting\:-translate-x-\[26px\]{--tw-translate-x:calc(26px * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}}@starting-style{.motion-safe\:starting\:-translate-x-\[51px\]{--tw-translate-x:calc(51px * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}}@starting-style{.motion-safe\:starting\:-translate-x-\[78px\]{--tw-translate-x:calc(78px * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}}@starting-style{.motion-safe\:starting\:-translate-x-\[102px\]{--tw-translate-x:calc(102px * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}}@starting-style{.motion-safe\:starting\:translate-y-6{--tw-translate-y:calc(var(--spacing) * 6);translate:var(--tw-translate-x) var(--tw-translate-y)}}}}.short-url-card{position:relative!important}.short-url-card .fi-ta-actions{z-index:10!important;margin:0!important;padding:0!important;position:absolute!important;top:1.25rem!important;right:1.25rem!important}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}@keyframes pulse{50%{opacity:.5}}@keyframes bounce{0%,to{animation-timing-function:cubic-bezier(.8,0,1,1);transform:translateY(-25%)}50%{animation-timing-function:cubic-bezier(0,0,.2,1);transform:none}} \ No newline at end of file +@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-content:""}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-serif:ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-red-900:oklch(39.6% .141 25.723);--color-red-950:oklch(25.8% .092 26.042);--color-orange-50:oklch(98% .016 73.684);--color-orange-100:oklch(95.4% .038 75.164);--color-orange-200:oklch(90.1% .076 70.697);--color-orange-300:oklch(83.7% .128 66.29);--color-orange-400:oklch(75% .183 55.934);--color-orange-500:oklch(70.5% .213 47.604);--color-orange-600:oklch(64.6% .222 41.116);--color-orange-700:oklch(55.3% .195 38.402);--color-orange-800:oklch(47% .157 37.304);--color-orange-900:oklch(40.8% .123 38.172);--color-orange-950:oklch(26.6% .079 36.259);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-800:oklch(47.3% .137 46.201);--color-amber-900:oklch(41.4% .112 45.904);--color-amber-950:oklch(27.9% .077 45.635);--color-yellow-50:oklch(98.7% .026 102.212);--color-yellow-100:oklch(97.3% .071 103.193);--color-yellow-200:oklch(94.5% .129 101.54);--color-yellow-300:oklch(90.5% .182 98.111);--color-yellow-400:oklch(85.2% .199 91.936);--color-yellow-500:oklch(79.5% .184 86.047);--color-yellow-600:oklch(68.1% .162 75.834);--color-yellow-700:oklch(55.4% .135 66.442);--color-yellow-800:oklch(47.6% .114 61.907);--color-yellow-900:oklch(42.1% .095 57.708);--color-yellow-950:oklch(28.6% .066 53.813);--color-lime-50:oklch(98.6% .031 120.757);--color-lime-100:oklch(96.7% .067 122.328);--color-lime-200:oklch(93.8% .127 124.321);--color-lime-300:oklch(89.7% .196 126.665);--color-lime-400:oklch(84.1% .238 128.85);--color-lime-500:oklch(76.8% .233 130.85);--color-lime-600:oklch(64.8% .2 131.684);--color-lime-700:oklch(53.2% .157 131.589);--color-lime-800:oklch(45.3% .124 130.933);--color-lime-900:oklch(40.5% .101 131.063);--color-lime-950:oklch(27.4% .072 132.109);--color-green-50:oklch(98.2% .018 155.826);--color-green-100:oklch(96.2% .044 156.743);--color-green-200:oklch(92.5% .084 155.995);--color-green-300:oklch(87.1% .15 154.449);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-green-800:oklch(44.8% .119 151.328);--color-green-900:oklch(39.3% .095 152.535);--color-green-950:oklch(26.6% .065 152.934);--color-emerald-50:oklch(97.9% .021 166.113);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-200:oklch(90.5% .093 164.15);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-700:oklch(50.8% .118 165.612);--color-emerald-800:oklch(43.2% .095 166.913);--color-emerald-900:oklch(37.8% .077 168.94);--color-emerald-950:oklch(26.2% .051 172.552);--color-teal-50:oklch(98.4% .014 180.72);--color-teal-100:oklch(95.3% .051 180.801);--color-teal-200:oklch(91% .096 180.426);--color-teal-300:oklch(85.5% .138 181.071);--color-teal-400:oklch(77.7% .152 181.912);--color-teal-500:oklch(70.4% .14 182.503);--color-teal-600:oklch(60% .118 184.704);--color-teal-700:oklch(51.1% .096 186.391);--color-teal-800:oklch(43.7% .078 188.216);--color-teal-900:oklch(38.6% .063 188.416);--color-teal-950:oklch(27.7% .046 192.524);--color-cyan-50:oklch(98.4% .019 200.873);--color-cyan-100:oklch(95.6% .045 203.388);--color-cyan-200:oklch(91.7% .08 205.041);--color-cyan-300:oklch(86.5% .127 207.078);--color-cyan-400:oklch(78.9% .154 211.53);--color-cyan-500:oklch(71.5% .143 215.221);--color-cyan-600:oklch(60.9% .126 221.723);--color-cyan-700:oklch(52% .105 223.128);--color-cyan-800:oklch(45% .085 224.283);--color-cyan-900:oklch(39.8% .07 227.392);--color-cyan-950:oklch(30.2% .056 229.695);--color-sky-50:oklch(97.7% .013 236.62);--color-sky-100:oklch(95.1% .026 236.824);--color-sky-200:oklch(90.1% .058 230.902);--color-sky-300:oklch(82.8% .111 230.318);--color-sky-400:oklch(74.6% .16 232.661);--color-sky-500:oklch(68.5% .169 237.323);--color-sky-600:oklch(58.8% .158 241.966);--color-sky-700:oklch(50% .134 242.749);--color-sky-800:oklch(44.3% .11 240.79);--color-sky-900:oklch(39.1% .09 240.876);--color-sky-950:oklch(29.3% .066 243.157);--color-blue-50:oklch(97% .014 254.604);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-800:oklch(42.4% .199 265.638);--color-blue-900:oklch(37.9% .146 265.522);--color-blue-950:oklch(28.2% .091 267.935);--color-indigo-50:oklch(96.2% .018 272.314);--color-indigo-100:oklch(93% .034 272.788);--color-indigo-200:oklch(87% .065 274.039);--color-indigo-300:oklch(78.5% .115 274.713);--color-indigo-400:oklch(67.3% .182 276.935);--color-indigo-500:oklch(58.5% .233 277.117);--color-indigo-600:oklch(51.1% .262 276.966);--color-indigo-700:oklch(45.7% .24 277.023);--color-indigo-800:oklch(39.8% .195 277.366);--color-indigo-900:oklch(35.9% .144 278.697);--color-indigo-950:oklch(25.7% .09 281.288);--color-violet-50:oklch(96.9% .016 293.756);--color-violet-100:oklch(94.3% .029 294.588);--color-violet-200:oklch(89.4% .057 293.283);--color-violet-300:oklch(81.1% .111 293.571);--color-violet-400:oklch(70.2% .183 293.541);--color-violet-500:oklch(60.6% .25 292.717);--color-violet-600:oklch(54.1% .281 293.009);--color-violet-700:oklch(49.1% .27 292.581);--color-violet-800:oklch(43.2% .232 292.759);--color-violet-900:oklch(38% .189 293.745);--color-violet-950:oklch(28.3% .141 291.089);--color-purple-50:oklch(97.7% .014 308.299);--color-purple-100:oklch(94.6% .033 307.174);--color-purple-200:oklch(90.2% .063 306.703);--color-purple-300:oklch(82.7% .119 306.383);--color-purple-400:oklch(71.4% .203 305.504);--color-purple-500:oklch(62.7% .265 303.9);--color-purple-600:oklch(55.8% .288 302.321);--color-purple-700:oklch(49.6% .265 301.924);--color-purple-800:oklch(43.8% .218 303.724);--color-purple-900:oklch(38.1% .176 304.987);--color-purple-950:oklch(29.1% .149 302.717);--color-fuchsia-50:oklch(97.7% .017 320.058);--color-fuchsia-100:oklch(95.2% .037 318.852);--color-fuchsia-200:oklch(90.3% .076 319.62);--color-fuchsia-300:oklch(83.3% .145 321.434);--color-fuchsia-400:oklch(74% .238 322.16);--color-fuchsia-500:oklch(66.7% .295 322.15);--color-fuchsia-600:oklch(59.1% .293 322.896);--color-fuchsia-700:oklch(51.8% .253 323.949);--color-fuchsia-800:oklch(45.2% .211 324.591);--color-fuchsia-900:oklch(40.1% .17 325.612);--color-fuchsia-950:oklch(29.3% .136 325.661);--color-pink-50:oklch(97.1% .014 343.198);--color-pink-100:oklch(94.8% .028 342.258);--color-pink-200:oklch(89.9% .061 343.231);--color-pink-300:oklch(82.3% .12 346.018);--color-pink-400:oklch(71.8% .202 349.761);--color-pink-500:oklch(65.6% .241 354.308);--color-pink-600:oklch(59.2% .249 .584);--color-pink-700:oklch(52.5% .223 3.958);--color-pink-800:oklch(45.9% .187 3.815);--color-pink-900:oklch(40.8% .153 2.432);--color-pink-950:oklch(28.4% .109 3.907);--color-rose-50:oklch(96.9% .015 12.422);--color-rose-100:oklch(94.1% .03 12.58);--color-rose-200:oklch(89.2% .058 10.001);--color-rose-300:oklch(81% .117 11.638);--color-rose-400:oklch(71.2% .194 13.428);--color-rose-500:oklch(64.5% .246 16.439);--color-rose-600:oklch(58.6% .253 17.585);--color-rose-700:oklch(51.4% .222 16.935);--color-rose-800:oklch(45.5% .188 13.697);--color-rose-900:oklch(41% .159 10.272);--color-rose-950:oklch(27.1% .105 12.094);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-slate-950:oklch(12.9% .042 264.695);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-gray-950:oklch(13% .028 261.692);--color-zinc-50:oklch(98.5% 0 0);--color-zinc-100:oklch(96.7% .001 286.375);--color-zinc-200:oklch(92% .004 286.32);--color-zinc-300:oklch(87.1% .006 286.286);--color-zinc-400:oklch(70.5% .015 286.067);--color-zinc-500:oklch(55.2% .016 285.938);--color-zinc-600:oklch(44.2% .017 285.786);--color-zinc-700:oklch(37% .013 285.805);--color-zinc-800:oklch(27.4% .006 286.033);--color-zinc-900:oklch(21% .006 285.885);--color-zinc-950:oklch(14.1% .005 285.823);--color-neutral-50:oklch(98.5% 0 0);--color-neutral-100:oklch(97% 0 0);--color-neutral-200:oklch(92.2% 0 0);--color-neutral-300:oklch(87% 0 0);--color-neutral-400:oklch(70.8% 0 0);--color-neutral-500:oklch(55.6% 0 0);--color-neutral-600:oklch(43.9% 0 0);--color-neutral-700:oklch(37.1% 0 0);--color-neutral-800:oklch(26.9% 0 0);--color-neutral-900:oklch(20.5% 0 0);--color-neutral-950:oklch(14.5% 0 0);--color-stone-50:oklch(98.5% .001 106.423);--color-stone-100:oklch(97% .001 106.424);--color-stone-200:oklch(92.3% .003 48.717);--color-stone-300:oklch(86.9% .005 56.366);--color-stone-400:oklch(70.9% .01 56.259);--color-stone-500:oklch(55.3% .013 58.071);--color-stone-600:oklch(44.4% .011 73.639);--color-stone-700:oklch(37.4% .01 67.558);--color-stone-800:oklch(26.8% .007 34.298);--color-stone-900:oklch(21.6% .006 56.043);--color-stone-950:oklch(14.7% .004 49.25);--color-black:#000;--color-white:#fff;--spacing:.25rem;--breakpoint-sm:40rem;--breakpoint-md:48rem;--breakpoint-lg:64rem;--breakpoint-xl:80rem;--breakpoint-2xl:96rem;--container-3xs:16rem;--container-2xs:18rem;--container-xs:20rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--container-3xl:48rem;--container-4xl:56rem;--container-5xl:64rem;--container-6xl:72rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--text-5xl:3rem;--text-5xl--line-height:1;--text-6xl:3.75rem;--text-6xl--line-height:1;--text-7xl:4.5rem;--text-7xl--line-height:1;--text-8xl:6rem;--text-8xl--line-height:1;--text-9xl:8rem;--text-9xl--line-height:1;--font-weight-thin:100;--font-weight-extralight:200;--font-weight-light:300;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--font-weight-black:900;--tracking-tighter:-.05em;--tracking-tight:-.025em;--tracking-normal:0em;--tracking-wide:.025em;--tracking-wider:.05em;--tracking-widest:.1em;--leading-tight:1.25;--leading-snug:1.375;--leading-normal:1.5;--leading-relaxed:1.625;--leading-loose:2;--radius-xs:.125rem;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--radius-3xl:1.5rem;--radius-4xl:2rem;--shadow-2xs:0 1px #0000000d;--shadow-xs:0 1px 2px 0 #0000000d;--shadow-sm:0 1px 3px 0 #0000001a, 0 1px 2px -1px #0000001a;--shadow-md:0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;--shadow-lg:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--shadow-xl:0 20px 25px -5px #0000001a, 0 8px 10px -6px #0000001a;--shadow-2xl:0 25px 50px -12px #00000040;--inset-shadow-2xs:inset 0 1px #0000000d;--inset-shadow-xs:inset 0 1px 1px #0000000d;--inset-shadow-sm:inset 0 2px 4px #0000000d;--drop-shadow-xs:0 1px 1px #0000000d;--drop-shadow-sm:0 1px 2px #00000026;--drop-shadow-md:0 3px 3px #0000001f;--drop-shadow-lg:0 4px 4px #00000026;--drop-shadow-xl:0 9px 7px #0000001a;--drop-shadow-2xl:0 25px 25px #00000026;--ease-in:cubic-bezier(.4, 0, 1, 1);--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--animate-bounce:bounce 1s infinite;--blur-xs:4px;--blur-sm:8px;--blur-md:12px;--blur-lg:16px;--blur-xl:24px;--blur-2xl:40px;--blur-3xl:64px;--perspective-dramatic:100px;--perspective-near:300px;--perspective-normal:500px;--perspective-midrange:800px;--perspective-distant:1200px;--aspect-video:16 / 9;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.\@container{container-type:inline-size}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.top-0{top:calc(var(--spacing) * 0)}.top-2{top:calc(var(--spacing) * 2)}.top-3{top:calc(var(--spacing) * 3)}.top-4{top:calc(var(--spacing) * 4)}.top-28{top:calc(var(--spacing) * 28)}.right-0{right:calc(var(--spacing) * 0)}.right-1{right:calc(var(--spacing) * 1)}.right-4{right:calc(var(--spacing) * 4)}.left-2{left:calc(var(--spacing) * 2)}.left-3{left:calc(var(--spacing) * 3)}.left-4{left:calc(var(--spacing) * 4)}.isolate{isolation:isolate}.z-0{z-index:0}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.col-span-2{grid-column:span 2/span 2}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.container\!{width:100%!important}@media (min-width:40rem){.container\!{max-width:40rem!important}}@media (min-width:48rem){.container\!{max-width:48rem!important}}@media (min-width:64rem){.container\!{max-width:64rem!important}}@media (min-width:80rem){.container\!{max-width:80rem!important}}@media (min-width:96rem){.container\!{max-width:96rem!important}}.m-0{margin:calc(var(--spacing) * 0)}.mx-auto{margin-inline:auto}.my-4{margin-block:calc(var(--spacing) * 4)}.my-5{margin-block:calc(var(--spacing) * 5)}.my-auto{margin-block:auto}.-mt-\[6\.6rem\]{margin-top:-6.6rem}.-mt-px{margin-top:-1px}.mt-0{margin-top:calc(var(--spacing) * 0)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-auto{margin-top:auto}.mr-2{margin-right:calc(var(--spacing) * 2)}.-mb-px{margin-bottom:-1px}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.mb-12{margin-bottom:calc(var(--spacing) * 12)}.-ml-8{margin-left:calc(var(--spacing) * -8)}.-ml-px{margin-left:-1px}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-4{margin-left:calc(var(--spacing) * 4)}.ml-7{margin-left:calc(var(--spacing) * 7)}.ml-12{margin-left:calc(var(--spacing) * 12)}.ml-auto{margin-left:auto}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline\!{display:inline!important}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.inline-grid{display:inline-grid}.inline-table{display:inline-table}.list-item{display:list-item}.table{display:table}.table\!{display:table!important}.table-caption{display:table-caption}.table-cell{display:table-cell}.table-column{display:table-column}.table-column-group{display:table-column-group}.table-footer-group{display:table-footer-group}.table-header-group{display:table-header-group}.table-row{display:table-row}.table-row-group{display:table-row-group}.aspect-\[4\/3\]{aspect-ratio:4/3}.aspect-\[335\/364\]{aspect-ratio:335/364}.aspect-video{aspect-ratio:var(--aspect-video)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.h-0{height:calc(var(--spacing) * 0)}.h-1{height:calc(var(--spacing) * 1)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-4\.5{height:calc(var(--spacing) * 4.5)}.h-5{height:calc(var(--spacing) * 5)}.h-5\.5{height:calc(var(--spacing) * 5.5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-11{height:calc(var(--spacing) * 11)}.h-12{height:calc(var(--spacing) * 12)}.h-14{height:calc(var(--spacing) * 14)}.h-14\.5{height:calc(var(--spacing) * 14.5)}.h-16{height:calc(var(--spacing) * 16)}.h-20{height:calc(var(--spacing) * 20)}.h-\[1px\]{height:1px}.h-\[55vh\]{height:55vh}.h-\[60px\]{height:60px}.h-\[65vh\]{height:65vh}.h-\[85vh\]{height:85vh}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-0{width:calc(var(--spacing) * 0)}.w-1{width:calc(var(--spacing) * 1)}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-2{width:calc(var(--spacing) * 2)}.w-2\.5{width:calc(var(--spacing) * 2.5)}.w-3{width:calc(var(--spacing) * 3)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-4\.5{width:calc(var(--spacing) * 4.5)}.w-5{width:calc(var(--spacing) * 5)}.w-5\.5{width:calc(var(--spacing) * 5.5)}.w-6{width:calc(var(--spacing) * 6)}.w-7{width:calc(var(--spacing) * 7)}.w-8{width:calc(var(--spacing) * 8)}.w-9{width:calc(var(--spacing) * 9)}.w-10{width:calc(var(--spacing) * 10)}.w-11{width:calc(var(--spacing) * 11)}.w-12{width:calc(var(--spacing) * 12)}.w-16{width:calc(var(--spacing) * 16)}.w-20{width:calc(var(--spacing) * 20)}.w-28{width:calc(var(--spacing) * 28)}.w-32{width:calc(var(--spacing) * 32)}.w-\[438px\]{width:438px}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-7xl{max-width:var(--container-7xl)}.max-w-\[50ch\]{max-width:50ch}.max-w-\[200px\]{max-width:200px}.max-w-\[280px\]{max-width:280px}.max-w-\[335px\]{max-width:335px}.max-w-\[360px\]{max-width:360px}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-none{max-width:none}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing) * 0)}.flex-1{flex:1}.flex-none{flex:none}.flex-shrink{flex-shrink:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.flex-grow,.grow{flex-grow:1}.border-collapse{border-collapse:collapse}.translate-y-0{--tw-translate-y:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-y-4{--tw-translate-y:calc(var(--spacing) * 4);translate:var(--tw-translate-x) var(--tw-translate-y)}.-rotate-90{rotate:-90deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.transform\!{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)!important}.animate-bounce{animation:var(--animate-bounce)}.animate-ping{animation:var(--animate-ping)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.resize\!{resize:both!important}.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-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.justify-items-center{justify-items:center}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-3\.5{gap:calc(var(--spacing) * 3.5)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}.gap-8{gap:calc(var(--spacing) * 8)}.gap-12{gap:calc(var(--spacing) * 12)}.gap-16{gap:calc(var(--spacing) * 16)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-10>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 10) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 10) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-16>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 16) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 16) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-x-6{column-gap:calc(var(--spacing) * 6)}:where(.space-x-1>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 1) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-6>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 6) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-x-reverse)))}.gap-y-1{row-gap:calc(var(--spacing) * 1)}.gap-y-2{row-gap:calc(var(--spacing) * 2)}.gap-y-6{row-gap:calc(var(--spacing) * 6)}.self-end{align-self:flex-end}.self-start{align-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.scroll-smooth{scroll-behavior:smooth}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-3xl{border-radius:var(--radius-3xl)}.rounded-\[6px\]{border-radius:6px}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t-lg{border-top-left-radius:var(--radius-lg);border-top-right-radius:var(--radius-lg)}.rounded-l-md{border-top-left-radius:var(--radius-md);border-bottom-left-radius:var(--radius-md)}.rounded-r-md{border-top-right-radius:var(--radius-md);border-bottom-right-radius:var(--radius-md)}.rounded-br-lg{border-bottom-right-radius:var(--radius-lg)}.rounded-bl-lg{border-bottom-left-radius:var(--radius-lg)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-4{border-style:var(--tw-border-style);border-width:4px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-\[\#19140035\]{border-color:#19140035}.border-\[\#e3e3e0\]{border-color:#e3e3e0}.border-amber-200{border-color:var(--color-amber-200)}.border-black{border-color:var(--color-black)}.border-cyan-500{border-color:var(--color-cyan-500)}.border-cyan-500\/20{border-color:#00b7d733}@supports (color:color-mix(in lab, red, red)){.border-cyan-500\/20{border-color:color-mix(in oklab, var(--color-cyan-500) 20%, transparent)}}.border-cyan-500\/30{border-color:#00b7d74d}@supports (color:color-mix(in lab, red, red)){.border-cyan-500\/30{border-color:color-mix(in oklab, var(--color-cyan-500) 30%, transparent)}}.border-emerald-200{border-color:var(--color-emerald-200)}.border-emerald-400{border-color:var(--color-emerald-400)}.border-emerald-500{border-color:var(--color-emerald-500)}.border-emerald-500\/20{border-color:#00bb7f33}@supports (color:color-mix(in lab, red, red)){.border-emerald-500\/20{border-color:color-mix(in oklab, var(--color-emerald-500) 20%, transparent)}}.border-gray-100{border-color:var(--color-gray-100)}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-200\/50{border-color:#e5e7eb80}@supports (color:color-mix(in lab, red, red)){.border-gray-200\/50{border-color:color-mix(in oklab, var(--color-gray-200) 50%, transparent)}}.border-gray-300{border-color:var(--color-gray-300)}.border-gray-400{border-color:var(--color-gray-400)}.border-neutral-100{border-color:var(--color-neutral-100)}.border-neutral-200{border-color:var(--color-neutral-200)}.border-neutral-900{border-color:var(--color-neutral-900)}.border-red-100{border-color:var(--color-red-100)}.border-rose-400{border-color:var(--color-rose-400)}.border-slate-700{border-color:var(--color-slate-700)}.border-slate-800{border-color:var(--color-slate-800)}.border-slate-900{border-color:var(--color-slate-900)}.border-transparent{border-color:#0000}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.border-white\/10{border-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.border-t-current{border-top-color:currentColor}.bg-\[\#0f1419\]{background-color:#0f1419}.bg-\[\#1b1b18\]{background-color:#1b1b18}.bg-\[\#6b7280\]{background-color:#6b7280}.bg-\[\#25d366\]{background-color:#25d366}.bg-\[\#0077b5\]{background-color:#0077b5}.bg-\[\#1877f2\]{background-color:#1877f2}.bg-\[\#FCFCFC\]{background-color:#fcfcfc}.bg-\[\#FDFDFC\]{background-color:#fdfdfc}.bg-\[\#dbdbd7\]{background-color:#dbdbd7}.bg-\[\#f4f4f5\]{background-color:#f4f4f5}.bg-\[\#fff2f2\]{background-color:#fff2f2}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-500\/10{background-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\/10{background-color:color-mix(in oklab, var(--color-amber-500) 10%, transparent)}}.bg-blue-50{background-color:var(--color-blue-50)}.bg-blue-500\/10{background-color:#3080ff1a}@supports (color:color-mix(in lab, red, red)){.bg-blue-500\/10{background-color:color-mix(in oklab, var(--color-blue-500) 10%, transparent)}}.bg-cyan-50{background-color:var(--color-cyan-50)}.bg-cyan-400{background-color:var(--color-cyan-400)}.bg-cyan-500{background-color:var(--color-cyan-500)}.bg-cyan-500\/10{background-color:#00b7d71a}@supports (color:color-mix(in lab, red, red)){.bg-cyan-500\/10{background-color:color-mix(in oklab, var(--color-cyan-500) 10%, transparent)}}.bg-cyan-950\/40{background-color:#05334566}@supports (color:color-mix(in lab, red, red)){.bg-cyan-950\/40{background-color:color-mix(in oklab, var(--color-cyan-950) 40%, transparent)}}.bg-emerald-50{background-color:var(--color-emerald-50)}.bg-emerald-100{background-color:var(--color-emerald-100)}.bg-emerald-500{background-color:var(--color-emerald-500)}.bg-emerald-500\/5{background-color:#00bb7f0d}@supports (color:color-mix(in lab, red, red)){.bg-emerald-500\/5{background-color:color-mix(in oklab, var(--color-emerald-500) 5%, transparent)}}.bg-emerald-500\/10{background-color:#00bb7f1a}@supports (color:color-mix(in lab, red, red)){.bg-emerald-500\/10{background-color:color-mix(in oklab, var(--color-emerald-500) 10%, transparent)}}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-50\/50{background-color:#f9fafb80}@supports (color:color-mix(in lab, red, red)){.bg-gray-50\/50{background-color:color-mix(in oklab, var(--color-gray-50) 50%, transparent)}}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-100\/50{background-color:#f3f4f680}@supports (color:color-mix(in lab, red, red)){.bg-gray-100\/50{background-color:color-mix(in oklab, var(--color-gray-100) 50%, transparent)}}.bg-gray-200{background-color:var(--color-gray-200)}.bg-gray-500\/10{background-color:#6a72821a}@supports (color:color-mix(in lab, red, red)){.bg-gray-500\/10{background-color:color-mix(in oklab, var(--color-gray-500) 10%, transparent)}}.bg-gray-900{background-color:var(--color-gray-900)}.bg-gray-950\/40{background-color:#03071266}@supports (color:color-mix(in lab, red, red)){.bg-gray-950\/40{background-color:color-mix(in oklab, var(--color-gray-950) 40%, transparent)}}.bg-indigo-50{background-color:var(--color-indigo-50)}.bg-indigo-500{background-color:var(--color-indigo-500)}.bg-neutral-50{background-color:var(--color-neutral-50)}.bg-neutral-200{background-color:var(--color-neutral-200)}.bg-neutral-300{background-color:var(--color-neutral-300)}.bg-neutral-400{background-color:var(--color-neutral-400)}.bg-neutral-500{background-color:var(--color-neutral-500)}.bg-neutral-900{background-color:var(--color-neutral-900)}.bg-pink-50{background-color:var(--color-pink-50)}.bg-pink-500\/10{background-color:#f6339a1a}@supports (color:color-mix(in lab, red, red)){.bg-pink-500\/10{background-color:color-mix(in oklab, var(--color-pink-500) 10%, transparent)}}.bg-purple-50{background-color:var(--color-purple-50)}.bg-purple-500\/10{background-color:#ac4bff1a}@supports (color:color-mix(in lab, red, red)){.bg-purple-500\/10{background-color:color-mix(in oklab, var(--color-purple-500) 10%, transparent)}}.bg-red-50{background-color:var(--color-red-50)}.bg-red-500\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.bg-red-500\/10{background-color:color-mix(in oklab, var(--color-red-500) 10%, transparent)}}.bg-rose-50{background-color:var(--color-rose-50)}.bg-rose-500{background-color:var(--color-rose-500)}.bg-rose-600{background-color:var(--color-rose-600)}.bg-sky-50{background-color:var(--color-sky-50)}.bg-slate-800{background-color:var(--color-slate-800)}.bg-slate-900{background-color:var(--color-slate-900)}.bg-slate-900\/60{background-color:#0f172b99}@supports (color:color-mix(in lab, red, red)){.bg-slate-900\/60{background-color:color-mix(in oklab, var(--color-slate-900) 60%, transparent)}}.bg-slate-900\/80{background-color:#0f172bcc}@supports (color:color-mix(in lab, red, red)){.bg-slate-900\/80{background-color:color-mix(in oklab, var(--color-slate-900) 80%, transparent)}}.bg-slate-950{background-color:var(--color-slate-950)}.bg-teal-50{background-color:var(--color-teal-50)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-white\/40{background-color:#fff6}@supports (color:color-mix(in lab, red, red)){.bg-white\/40{background-color:color-mix(in oklab, var(--color-white) 40%, transparent)}}.bg-white\/95{background-color:#fffffff2}@supports (color:color-mix(in lab, red, red)){.bg-white\/95{background-color:color-mix(in oklab, var(--color-white) 95%, transparent)}}.bg-gradient-to-b{--tw-gradient-position:to bottom in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-r{--tw-gradient-position:to right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-t{--tw-gradient-position:to top in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-tr{--tw-gradient-position:to top right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-\[radial-gradient\(ellipse_at_top_right\,_var\(--tw-gradient-stops\)\)\]{background-image:radial-gradient(ellipse at top right, var(--tw-gradient-stops))}.from-\[\#006aff\]{--tw-gradient-from:#006aff;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-cyan-400{--tw-gradient-from:var(--color-cyan-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-cyan-500{--tw-gradient-from:var(--color-cyan-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-cyan-900\/30{--tw-gradient-from:#104e644d}@supports (color:color-mix(in lab, red, red)){.from-cyan-900\/30{--tw-gradient-from:color-mix(in oklab, var(--color-cyan-900) 30%, transparent)}}.from-cyan-900\/30{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-slate-900{--tw-gradient-from:var(--color-slate-900);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-slate-950{--tw-gradient-from:var(--color-slate-950);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-white{--tw-gradient-from:var(--color-white);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.via-\[\#00b2ff\]{--tw-gradient-via:#00b2ff;--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-slate-200{--tw-gradient-via:var(--color-slate-200);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-slate-900{--tw-gradient-via:var(--color-slate-900);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-slate-900\/40{--tw-gradient-via:#0f172b66}@supports (color:color-mix(in lab, red, red)){.via-slate-900\/40{--tw-gradient-via:color-mix(in oklab, var(--color-slate-900) 40%, transparent)}}.via-slate-900\/40{--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-slate-950{--tw-gradient-via:var(--color-slate-950);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-teal-300{--tw-gradient-via:var(--color-teal-300);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.to-\[\#00d6ff\]{--tw-gradient-to:#00d6ff;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-blue-500{--tw-gradient-to:var(--color-blue-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-blue-600{--tw-gradient-to:var(--color-blue-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-cyan-400{--tw-gradient-to:var(--color-cyan-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-slate-950{--tw-gradient-to:var(--color-slate-950);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-transparent{--tw-gradient-to:transparent;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.bg-clip-text{-webkit-background-clip:text;background-clip:text}.mask-repeat{-webkit-mask-repeat:repeat;mask-repeat:repeat}.object-contain{object-fit:contain}.object-cover{object-fit:cover}.p-0{padding:calc(var(--spacing) * 0)}.p-1{padding:calc(var(--spacing) * 1)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-3\.5{padding:calc(var(--spacing) * 3.5)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.px-0\.5{padding-inline:calc(var(--spacing) * .5)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-10{padding-block:calc(var(--spacing) * 10)}.py-12{padding-block:calc(var(--spacing) * 12)}.py-16{padding-block:calc(var(--spacing) * 16)}.py-20{padding-block:calc(var(--spacing) * 20)}.py-24{padding-block:calc(var(--spacing) * 24)}.pt-1{padding-top:calc(var(--spacing) * 1)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-8{padding-top:calc(var(--spacing) * 8)}.pr-4{padding-right:calc(var(--spacing) * 4)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-6{padding-bottom:calc(var(--spacing) * 6)}.pb-12{padding-bottom:calc(var(--spacing) * 12)}.pb-16{padding-bottom:calc(var(--spacing) * 16)}.pb-px{padding-bottom:1px}.pl-9{padding-left:calc(var(--spacing) * 9)}.text-center{text-align:center}.text-justify{text-align:justify}.text-left{text-align:left}.text-right{text-align:right}.font-\[\'Bricolage_Grotesque\'\]{font-family:Bricolage Grotesque}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-\[15px\]{font-size:15px}.text-\[16px\]{font-size:16px}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-6{--tw-leading:calc(var(--spacing) * 6);line-height:calc(var(--spacing) * 6)}.leading-7{--tw-leading:calc(var(--spacing) * 7);line-height:calc(var(--spacing) * 7)}.leading-\[16px\]{--tw-leading:16px;line-height:16px}.leading-\[20px\]{--tw-leading:20px;line-height:20px}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.text-wrap{text-wrap:wrap}.break-all{word-break:break-all}.text-\[\#1B1B18\],.text-\[\#1b1b18\]{color:#1b1b18}.text-\[\#2a5bd7\]{color:#2a5bd7}.text-\[\#706f6c\]{color:#706f6c}.text-\[\#273144\]{color:#273144}.text-\[\#F3BEC7\]{color:#f3bec7}.text-\[\#F8B803\]{color:#f8b803}.text-\[\#F53003\],.text-\[\#f53003\]{color:#f53003}.text-amber-500{color:var(--color-amber-500)}.text-amber-600{color:var(--color-amber-600)}.text-amber-800{color:var(--color-amber-800)}.text-amber-900{color:var(--color-amber-900)}.text-black{color:var(--color-black)}.text-blue-500{color:var(--color-blue-500)}.text-cyan-400{color:var(--color-cyan-400)}.text-cyan-500{color:var(--color-cyan-500)}.text-emerald-400{color:var(--color-emerald-400)}.text-emerald-500{color:var(--color-emerald-500)}.text-emerald-600{color:var(--color-emerald-600)}.text-emerald-700{color:var(--color-emerald-700)}.text-emerald-800{color:var(--color-emerald-800)}.text-gray-200{color:var(--color-gray-200)}.text-gray-300{color:var(--color-gray-300)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-gray-900{color:var(--color-gray-900)}.text-indigo-500{color:var(--color-indigo-500)}.text-indigo-600{color:var(--color-indigo-600)}.text-neutral-300{color:var(--color-neutral-300)}.text-neutral-400{color:var(--color-neutral-400)}.text-neutral-500{color:var(--color-neutral-500)}.text-neutral-800{color:var(--color-neutral-800)}.text-neutral-900{color:var(--color-neutral-900)}.text-pink-500{color:var(--color-pink-500)}.text-purple-500{color:var(--color-purple-500)}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-rose-500{color:var(--color-rose-500)}.text-rose-600{color:var(--color-rose-600)}.text-sky-500{color:var(--color-sky-500)}.text-slate-100{color:var(--color-slate-100)}.text-slate-200{color:var(--color-slate-200)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-slate-950{color:var(--color-slate-950)}.text-teal-500{color:var(--color-teal-500)}.text-transparent{color:#0000}.text-white{color:var(--color-white)}.text-white\/80{color:#fffc}@supports (color:color-mix(in lab, red, red)){.text-white\/80{color:color-mix(in oklab, var(--color-white) 80%, transparent)}}.text-yellow-500{color:var(--color-yellow-500)}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.ordinal{--tw-ordinal:ordinal;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.line-through{text-decoration-line:line-through}.overline{text-decoration-line:overline}.underline{text-decoration-line:underline}.underline-offset-4{text-underline-offset:4px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.subpixel-antialiased{-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}.placeholder-neutral-300::placeholder{color:var(--color-neutral-300)}.placeholder-slate-500::placeholder{color:var(--color-slate-500)}.opacity-0{opacity:0}.opacity-20{opacity:.2}.opacity-25{opacity:.25}.opacity-40{opacity:.4}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.opacity-95{opacity:.95}.opacity-100{opacity:1}.mix-blend-color{mix-blend-mode:color}.mix-blend-darken{mix-blend-mode:darken}.mix-blend-hard-light{mix-blend-mode:hard-light}.mix-blend-multiply{mix-blend-mode:multiply}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0px_0px_1px_0px_rgba\(0\,0\,0\,0\.03\)\,0px_1px_2px_0px_rgba\(0\,0\,0\,0\.06\)\]{--tw-shadow:0px 0px 1px 0px var(--tw-shadow-color,#00000008), 0px 1px 2px 0px var(--tw-shadow-color,#0000000f);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[inset_0px_0px_0px_1px_rgba\(26\,26\,0\,0\.16\)\]{--tw-shadow:inset 0px 0px 0px 1px var(--tw-shadow-color,#1a1a0029);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-pink-500\/10{--tw-shadow-color:#f6339a1a}@supports (color:color-mix(in lab, red, red)){.shadow-pink-500\/10{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-pink-500) 10%, transparent) var(--tw-shadow-alpha), transparent)}}.ring-gray-300{--tw-ring-color:var(--color-gray-300)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);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,)}.drop-shadow{--tw-drop-shadow-size:drop-shadow(0 1px 2px var(--tw-drop-shadow-color,#0000001a)) drop-shadow(0 1px 1px var(--tw-drop-shadow-color,#0000000f));--tw-drop-shadow:drop-shadow(0 1px 2px #0000001a) drop-shadow(0 1px 1px #0000000f);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,)}.grayscale{--tw-grayscale:grayscale(100%);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,)}.invert{--tw-invert:invert(100%);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,)}.sepia{--tw-sepia:sepia(100%);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,)}.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,)}.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,)!important}.backdrop-blur-md{--tw-backdrop-blur:blur(var(--blur-md));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.backdrop-blur-xl{--tw-backdrop-blur:blur(var(--blur-xl));-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-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,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.delay-200{transition-delay:.2s}.delay-300{transition-delay:.3s}.delay-400{transition-delay:.4s}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.duration-500{--tw-duration:.5s;transition-duration:.5s}.duration-700{--tw-duration:.7s;transition-duration:.7s}.duration-750{--tw-duration:.75s;transition-duration:.75s}.ease-in{--tw-ease:var(--ease-in);transition-timing-function:var(--ease-in)}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-linear{--tw-ease:linear;transition-timing-function:linear}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.select-all{-webkit-user-select:all;user-select:all}.select-none{-webkit-user-select:none;user-select:none}.\[--stroke-color\:\#1B1B18\]{--stroke-color:#1b1b18}.\[animation-delay\:-0\.3s\]{animation-delay:-.3s}.\[animation-delay\:-0\.15s\]{animation-delay:-.15s}.not-has-\[nav\]\:hidden:not(:has(:is(nav))){display:none}@media (hover:hover){.group-hover\:scale-105:is(:where(.group):hover *){--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x) var(--tw-scale-y)}.group-hover\:scale-110:is(:where(.group):hover *){--tw-scale-x:110%;--tw-scale-y:110%;--tw-scale-z:110%;scale:var(--tw-scale-x) var(--tw-scale-y)}.group-hover\:rotate-12:is(:where(.group):hover *){rotate:12deg}.group-hover\:text-cyan-400:is(:where(.group):hover *){color:var(--color-cyan-400)}.group-hover\:text-gray-900:is(:where(.group):hover *){color:var(--color-gray-900)}.group-hover\:text-neutral-900:is(:where(.group):hover *){color:var(--color-neutral-900)}}.selection\:bg-cyan-500 ::selection{background-color:var(--color-cyan-500)}.selection\:bg-cyan-500::selection{background-color:var(--color-cyan-500)}.selection\:text-slate-900 ::selection{color:var(--color-slate-900)}.selection\:text-slate-900::selection{color:var(--color-slate-900)}.before\:absolute:before{content:var(--tw-content);position:absolute}.before\:top-0:before{content:var(--tw-content);top:calc(var(--spacing) * 0)}.before\:top-1\/2:before{content:var(--tw-content);top:50%}.before\:bottom-0:before{content:var(--tw-content);bottom:calc(var(--spacing) * 0)}.before\:bottom-1\/2:before{content:var(--tw-content);bottom:50%}.before\:left-\[0\.4rem\]:before{content:var(--tw-content);left:.4rem}.before\:border-l:before{content:var(--tw-content);border-left-style:var(--tw-border-style);border-left-width:1px}.before\:border-\[\#e3e3e0\]:before{content:var(--tw-content);border-color:#e3e3e0}.focus-within\:ring-2:focus-within{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-within\:ring-neutral-900:focus-within{--tw-ring-color:var(--color-neutral-900)}@media (hover:hover){.hover\:scale-105:hover{--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x) var(--tw-scale-y)}.hover\:border-\[\#1915014a\]:hover{border-color:#1915014a}.hover\:border-\[\#19140035\]:hover{border-color:#19140035}.hover\:border-amber-200\/50:hover{border-color:#fee68580}@supports (color:color-mix(in lab, red, red)){.hover\:border-amber-200\/50:hover{border-color:color-mix(in oklab, var(--color-amber-200) 50%, transparent)}}.hover\:border-black:hover{border-color:var(--color-black)}.hover\:border-emerald-200\/50:hover{border-color:#a4f4cf80}@supports (color:color-mix(in lab, red, red)){.hover\:border-emerald-200\/50:hover{border-color:color-mix(in oklab, var(--color-emerald-200) 50%, transparent)}}.hover\:border-indigo-200\/50:hover{border-color:#c7d2ff80}@supports (color:color-mix(in lab, red, red)){.hover\:border-indigo-200\/50:hover{border-color:color-mix(in oklab, var(--color-indigo-200) 50%, transparent)}}.hover\:border-pink-200\/50:hover{border-color:#fccee880}@supports (color:color-mix(in lab, red, red)){.hover\:border-pink-200\/50:hover{border-color:color-mix(in oklab, var(--color-pink-200) 50%, transparent)}}.hover\:border-purple-200\/50:hover{border-color:#e9d5ff80}@supports (color:color-mix(in lab, red, red)){.hover\:border-purple-200\/50:hover{border-color:color-mix(in oklab, var(--color-purple-200) 50%, transparent)}}.hover\:border-rose-200\/50:hover{border-color:#ffccd380}@supports (color:color-mix(in lab, red, red)){.hover\:border-rose-200\/50:hover{border-color:color-mix(in oklab, var(--color-rose-200) 50%, transparent)}}.hover\:border-sky-200\/50:hover{border-color:#b8e6fe80}@supports (color:color-mix(in lab, red, red)){.hover\:border-sky-200\/50:hover{border-color:color-mix(in oklab, var(--color-sky-200) 50%, transparent)}}.hover\:border-slate-600:hover{border-color:var(--color-slate-600)}.hover\:border-slate-700:hover{border-color:var(--color-slate-700)}.hover\:bg-\[\#e4e4e7\]:hover{background-color:#e4e4e7}.hover\:bg-black:hover{background-color:var(--color-black)}.hover\:bg-cyan-400:hover{background-color:var(--color-cyan-400)}.hover\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\:bg-gray-100:hover{background-color:var(--color-gray-100)}.hover\:bg-gray-100\/60:hover{background-color:#f3f4f699}@supports (color:color-mix(in lab, red, red)){.hover\:bg-gray-100\/60:hover{background-color:color-mix(in oklab, var(--color-gray-100) 60%, transparent)}}.hover\:bg-gray-200:hover{background-color:var(--color-gray-200)}.hover\:bg-gray-800:hover{background-color:var(--color-gray-800)}.hover\:bg-neutral-50:hover{background-color:var(--color-neutral-50)}.hover\:bg-neutral-800:hover{background-color:var(--color-neutral-800)}.hover\:bg-rose-500:hover{background-color:var(--color-rose-500)}.hover\:bg-slate-700:hover{background-color:var(--color-slate-700)}.hover\:bg-slate-800:hover{background-color:var(--color-slate-800)}.hover\:from-cyan-400:hover{--tw-gradient-from:var(--color-cyan-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.hover\:to-blue-500:hover{--tw-gradient-to:var(--color-blue-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.hover\:text-cyan-300:hover{color:var(--color-cyan-300)}.hover\:text-cyan-400:hover{color:var(--color-cyan-400)}.hover\:text-gray-500:hover{color:var(--color-gray-500)}.hover\:text-gray-700:hover{color:var(--color-gray-700)}.hover\:text-neutral-600:hover{color:var(--color-neutral-600)}.hover\:text-neutral-900:hover{color:var(--color-neutral-900)}.hover\:text-slate-200:hover{color:var(--color-slate-200)}.hover\:text-white:hover{color:var(--color-white)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}.hover\:shadow:hover{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.hover\:shadow-cyan-500\/20:hover{--tw-shadow-color:#00b7d733}@supports (color:color-mix(in lab, red, red)){.hover\:shadow-cyan-500\/20:hover{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-cyan-500) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.hover\:shadow-pink-500\/20:hover{--tw-shadow-color:#f6339a33}@supports (color:color-mix(in lab, red, red)){.hover\:shadow-pink-500\/20:hover{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-pink-500) 20%, transparent) var(--tw-shadow-alpha), transparent)}}}.focus\:border-emerald-500:focus{border-color:var(--color-emerald-500)}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-cyan-500:focus{--tw-ring-color:var(--color-cyan-500)}.focus\:ring-emerald-500:focus{--tw-ring-color:var(--color-emerald-500)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:text-black:disabled{color:var(--color-black)}.disabled\:opacity-50:disabled{opacity:.5}@media (min-width:40rem){.sm\:col-span-3{grid-column:span 3/span 3}.sm\:flex{display:flex}.sm\:translate-y-0{--tw-translate-y:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.sm\:scale-95{--tw-scale-x:95%;--tw-scale-y:95%;--tw-scale-z:95%;scale:var(--tw-scale-x) var(--tw-scale-y)}.sm\:scale-100{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x) var(--tw-scale-y)}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:items-end{align-items:flex-end}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}.sm\:text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.sm\:text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.sm\:text-6xl{font-size:var(--text-6xl);line-height:var(--tw-leading,var(--text-6xl--line-height))}.sm\:text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}}@media (min-width:48rem){.md\:flex{display:flex}.md\:hidden{display:none}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}:where(.md\:space-y-0>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 0) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 0) * calc(1 - var(--tw-space-y-reverse)))}.md\:text-7xl{font-size:var(--text-7xl);line-height:var(--tw-leading,var(--text-7xl--line-height))}}@media (min-width:64rem){.lg\:col-span-1{grid-column:span 1/span 1}.lg\:col-span-2{grid-column:span 2/span 2}.lg\:col-span-3{grid-column:span 3/span 3}.lg\:mt-10{margin-top:calc(var(--spacing) * 10)}.lg\:mb-0{margin-bottom:calc(var(--spacing) * 0)}.lg\:mb-6{margin-bottom:calc(var(--spacing) * 6)}.lg\:-ml-px{margin-left:-1px}.lg\:ml-0{margin-left:calc(var(--spacing) * 0)}.lg\:block{display:block}.lg\:aspect-auto{aspect-ratio:auto}.lg\:w-1\/2{width:50%}.lg\:w-\[438px\]{width:438px}.lg\:max-w-4xl{max-width:var(--container-4xl)}.lg\:grow{flex-grow:1}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:flex-row{flex-direction:row}.lg\:flex-row-reverse{flex-direction:row-reverse}.lg\:justify-center{justify-content:center}.lg\:rounded-t-none{border-top-left-radius:0;border-top-right-radius:0}.lg\:rounded-tl-lg{border-top-left-radius:var(--radius-lg)}.lg\:rounded-r-lg{border-top-right-radius:var(--radius-lg);border-bottom-right-radius:var(--radius-lg)}.lg\:rounded-br-none{border-bottom-right-radius:0}.lg\:p-8{padding:calc(var(--spacing) * 8)}.lg\:p-20{padding:calc(var(--spacing) * 20)}.lg\:px-8{padding-inline:calc(var(--spacing) * 8)}.lg\:pb-10{padding-bottom:calc(var(--spacing) * 10)}}@media (min-width:80rem){.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (prefers-color-scheme:dark){.dark\:border-\[\#3E3E3A\]{border-color:#3e3e3a}.dark\:border-\[\#eeeeec\]{border-color:#eeeeec}.dark\:border-amber-700{border-color:var(--color-amber-700)}.dark\:border-amber-900\/30{border-color:#7b33064d}@supports (color:color-mix(in lab, red, red)){.dark\:border-amber-900\/30{border-color:color-mix(in oklab, var(--color-amber-900) 30%, transparent)}}.dark\:border-amber-950\/20{border-color:#46190133}@supports (color:color-mix(in lab, red, red)){.dark\:border-amber-950\/20{border-color:color-mix(in oklab, var(--color-amber-950) 20%, transparent)}}.dark\:border-emerald-600{border-color:var(--color-emerald-600)}.dark\:border-emerald-800{border-color:var(--color-emerald-800)}.dark\:border-gray-700{border-color:var(--color-gray-700)}.dark\:border-gray-700\/50{border-color:#36415380}@supports (color:color-mix(in lab, red, red)){.dark\:border-gray-700\/50{border-color:color-mix(in oklab, var(--color-gray-700) 50%, transparent)}}.dark\:border-gray-800{border-color:var(--color-gray-800)}.dark\:border-gray-800\/10{border-color:#1e29391a}@supports (color:color-mix(in lab, red, red)){.dark\:border-gray-800\/10{border-color:color-mix(in oklab, var(--color-gray-800) 10%, transparent)}}.dark\:border-gray-800\/80{border-color:#1e2939cc}@supports (color:color-mix(in lab, red, red)){.dark\:border-gray-800\/80{border-color:color-mix(in oklab, var(--color-gray-800) 80%, transparent)}}.dark\:border-neutral-700{border-color:var(--color-neutral-700)}.dark\:border-neutral-800{border-color:var(--color-neutral-800)}.dark\:border-neutral-900{border-color:var(--color-neutral-900)}.dark\:border-red-900\/30{border-color:#82181a4d}@supports (color:color-mix(in lab, red, red)){.dark\:border-red-900\/30{border-color:color-mix(in oklab, var(--color-red-900) 30%, transparent)}}.dark\:border-white{border-color:var(--color-white)}.dark\:border-zinc-700{border-color:var(--color-zinc-700)}.dark\:bg-\[\#0C0C0C\]{background-color:#0c0c0c}.dark\:bg-\[\#0a0a0a\]{background-color:#0a0a0a}.dark\:bg-\[\#1D0002\]{background-color:#1d0002}.dark\:bg-\[\#3E3E3A\]{background-color:#3e3e3a}.dark\:bg-\[\#161615\]{background-color:#161615}.dark\:bg-\[\#eeeeec\]{background-color:#eeeeec}.dark\:bg-amber-500\/20{background-color:#f99c0033}@supports (color:color-mix(in lab, red, red)){.dark\:bg-amber-500\/20{background-color:color-mix(in oklab, var(--color-amber-500) 20%, transparent)}}.dark\:bg-amber-950\/10{background-color:#4619011a}@supports (color:color-mix(in lab, red, red)){.dark\:bg-amber-950\/10{background-color:color-mix(in oklab, var(--color-amber-950) 10%, transparent)}}.dark\:bg-amber-950\/20{background-color:#46190133}@supports (color:color-mix(in lab, red, red)){.dark\:bg-amber-950\/20{background-color:color-mix(in oklab, var(--color-amber-950) 20%, transparent)}}.dark\:bg-amber-950\/30{background-color:#4619014d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-amber-950\/30{background-color:color-mix(in oklab, var(--color-amber-950) 30%, transparent)}}.dark\:bg-amber-950\/50{background-color:#46190180}@supports (color:color-mix(in lab, red, red)){.dark\:bg-amber-950\/50{background-color:color-mix(in oklab, var(--color-amber-950) 50%, transparent)}}.dark\:bg-blue-950\/50{background-color:#16245680}@supports (color:color-mix(in lab, red, red)){.dark\:bg-blue-950\/50{background-color:color-mix(in oklab, var(--color-blue-950) 50%, transparent)}}.dark\:bg-cyan-950\/50{background-color:#05334580}@supports (color:color-mix(in lab, red, red)){.dark\:bg-cyan-950\/50{background-color:color-mix(in oklab, var(--color-cyan-950) 50%, transparent)}}.dark\:bg-emerald-500\/5{background-color:#00bb7f0d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-emerald-500\/5{background-color:color-mix(in oklab, var(--color-emerald-500) 5%, transparent)}}.dark\:bg-emerald-900{background-color:var(--color-emerald-900)}.dark\:bg-emerald-950{background-color:var(--color-emerald-950)}.dark\:bg-emerald-950\/30{background-color:#002c224d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-emerald-950\/30{background-color:color-mix(in oklab, var(--color-emerald-950) 30%, transparent)}}.dark\:bg-emerald-950\/50{background-color:#002c2280}@supports (color:color-mix(in lab, red, red)){.dark\:bg-emerald-950\/50{background-color:color-mix(in oklab, var(--color-emerald-950) 50%, transparent)}}.dark\:bg-gray-100{background-color:var(--color-gray-100)}.dark\:bg-gray-800{background-color:var(--color-gray-800)}.dark\:bg-gray-800\/10{background-color:#1e29391a}@supports (color:color-mix(in lab, red, red)){.dark\:bg-gray-800\/10{background-color:color-mix(in oklab, var(--color-gray-800) 10%, transparent)}}.dark\:bg-gray-800\/50{background-color:#1e293980}@supports (color:color-mix(in lab, red, red)){.dark\:bg-gray-800\/50{background-color:color-mix(in oklab, var(--color-gray-800) 50%, transparent)}}.dark\:bg-gray-900{background-color:var(--color-gray-900)}.dark\:bg-gray-900\/30{background-color:#1018284d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-gray-900\/30{background-color:color-mix(in oklab, var(--color-gray-900) 30%, transparent)}}.dark\:bg-gray-900\/40{background-color:#10182866}@supports (color:color-mix(in lab, red, red)){.dark\:bg-gray-900\/40{background-color:color-mix(in oklab, var(--color-gray-900) 40%, transparent)}}.dark\:bg-gray-900\/50{background-color:#10182880}@supports (color:color-mix(in lab, red, red)){.dark\:bg-gray-900\/50{background-color:color-mix(in oklab, var(--color-gray-900) 50%, transparent)}}.dark\:bg-gray-900\/95{background-color:#101828f2}@supports (color:color-mix(in lab, red, red)){.dark\:bg-gray-900\/95{background-color:color-mix(in oklab, var(--color-gray-900) 95%, transparent)}}.dark\:bg-gray-950{background-color:var(--color-gray-950)}.dark\:bg-indigo-950\/30{background-color:#1e1a4d4d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-indigo-950\/30{background-color:color-mix(in oklab, var(--color-indigo-950) 30%, transparent)}}.dark\:bg-indigo-950\/50{background-color:#1e1a4d80}@supports (color:color-mix(in lab, red, red)){.dark\:bg-indigo-950\/50{background-color:color-mix(in oklab, var(--color-indigo-950) 50%, transparent)}}.dark\:bg-neutral-400{background-color:var(--color-neutral-400)}.dark\:bg-neutral-500{background-color:var(--color-neutral-500)}.dark\:bg-neutral-600{background-color:var(--color-neutral-600)}.dark\:bg-neutral-800{background-color:var(--color-neutral-800)}.dark\:bg-neutral-900{background-color:var(--color-neutral-900)}.dark\:bg-neutral-950{background-color:var(--color-neutral-950)}.dark\:bg-pink-950\/30{background-color:#5104244d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-pink-950\/30{background-color:color-mix(in oklab, var(--color-pink-950) 30%, transparent)}}.dark\:bg-purple-950\/30{background-color:#3c03664d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-purple-950\/30{background-color:color-mix(in oklab, var(--color-purple-950) 30%, transparent)}}.dark\:bg-purple-950\/50{background-color:#3c036680}@supports (color:color-mix(in lab, red, red)){.dark\:bg-purple-950\/50{background-color:color-mix(in oklab, var(--color-purple-950) 50%, transparent)}}.dark\:bg-red-950\/20{background-color:#46080933}@supports (color:color-mix(in lab, red, red)){.dark\:bg-red-950\/20{background-color:color-mix(in oklab, var(--color-red-950) 20%, transparent)}}.dark\:bg-rose-500{background-color:var(--color-rose-500)}.dark\:bg-rose-950\/30{background-color:#4d02184d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-rose-950\/30{background-color:color-mix(in oklab, var(--color-rose-950) 30%, transparent)}}.dark\:bg-rose-950\/50{background-color:#4d021880}@supports (color:color-mix(in lab, red, red)){.dark\:bg-rose-950\/50{background-color:color-mix(in oklab, var(--color-rose-950) 50%, transparent)}}.dark\:bg-sky-950\/30{background-color:#052f4a4d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-sky-950\/30{background-color:color-mix(in oklab, var(--color-sky-950) 30%, transparent)}}.dark\:bg-teal-950\/50{background-color:#022f2e80}@supports (color:color-mix(in lab, red, red)){.dark\:bg-teal-950\/50{background-color:color-mix(in oklab, var(--color-teal-950) 50%, transparent)}}.dark\:bg-white{background-color:var(--color-white)}.dark\:bg-white\/10{background-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.dark\:bg-white\/10{background-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.dark\:bg-zinc-800{background-color:var(--color-zinc-800)}.dark\:text-\[\#1C1C1A\]{color:#1c1c1a}.dark\:text-\[\#4B0600\]{color:#4b0600}.dark\:text-\[\#391800\]{color:#391800}.dark\:text-\[\#733000\]{color:#733000}.dark\:text-\[\#A1A09A\]{color:#a1a09a}.dark\:text-\[\#EDEDEC\]{color:#ededec}.dark\:text-\[\#F61500\]{color:#f61500}.dark\:text-\[\#FF4433\]{color:#f43}.dark\:text-amber-200{color:var(--color-amber-200)}.dark\:text-amber-300{color:var(--color-amber-300)}.dark\:text-amber-400{color:var(--color-amber-400)}.dark\:text-amber-500{color:var(--color-amber-500)}.dark\:text-black{color:var(--color-black)}.dark\:text-blue-400{color:var(--color-blue-400)}.dark\:text-cyan-400{color:var(--color-cyan-400)}.dark\:text-emerald-200{color:var(--color-emerald-200)}.dark\:text-emerald-400{color:var(--color-emerald-400)}.dark\:text-emerald-500{color:var(--color-emerald-500)}.dark\:text-gray-100{color:var(--color-gray-100)}.dark\:text-gray-200{color:var(--color-gray-200)}.dark\:text-gray-300{color:var(--color-gray-300)}.dark\:text-gray-400{color:var(--color-gray-400)}.dark\:text-gray-500{color:var(--color-gray-500)}.dark\:text-gray-800{color:var(--color-gray-800)}.dark\:text-gray-950{color:var(--color-gray-950)}.dark\:text-indigo-400{color:var(--color-indigo-400)}.dark\:text-neutral-300{color:var(--color-neutral-300)}.dark\:text-neutral-400{color:var(--color-neutral-400)}.dark\:text-neutral-500{color:var(--color-neutral-500)}.dark\:text-neutral-600{color:var(--color-neutral-600)}.dark\:text-neutral-700{color:var(--color-neutral-700)}.dark\:text-neutral-900{color:var(--color-neutral-900)}.dark\:text-neutral-950{color:var(--color-neutral-950)}.dark\:text-purple-400{color:var(--color-purple-400)}.dark\:text-red-400{color:var(--color-red-400)}.dark\:text-rose-400{color:var(--color-rose-400)}.dark\:text-teal-400{color:var(--color-teal-400)}.dark\:text-white{color:var(--color-white)}.dark\:placeholder-neutral-700::placeholder{color:var(--color-neutral-700)}.dark\:mix-blend-hard-light{mix-blend-mode:hard-light}.dark\:mix-blend-normal{mix-blend-mode:normal}.dark\:shadow-\[inset_0px_0px_0px_1px_\#fffaed2d\]{--tw-shadow:inset 0px 0px 0px 1px var(--tw-shadow-color,#fffaed2d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.dark\:\[--stroke-color\:\#FF750F\]{--stroke-color:#ff750f}@media (hover:hover){.dark\:group-hover\:text-white:is(:where(.group):hover *){color:var(--color-white)}}.dark\:before\:border-\[\#3E3E3A\]:before{content:var(--tw-content);border-color:#3e3e3a}.dark\:focus-within\:ring-white:focus-within{--tw-ring-color:var(--color-white)}@media (hover:hover){.dark\:hover\:border-\[\#3E3E3A\]:hover{border-color:#3e3e3a}.dark\:hover\:border-\[\#62605b\]:hover{border-color:#62605b}.dark\:hover\:border-amber-900\/50:hover{border-color:#7b330680}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:border-amber-900\/50:hover{border-color:color-mix(in oklab, var(--color-amber-900) 50%, transparent)}}.dark\:hover\:border-emerald-900\/50:hover{border-color:#004e3b80}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:border-emerald-900\/50:hover{border-color:color-mix(in oklab, var(--color-emerald-900) 50%, transparent)}}.dark\:hover\:border-indigo-900\/50:hover{border-color:#312c8580}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:border-indigo-900\/50:hover{border-color:color-mix(in oklab, var(--color-indigo-900) 50%, transparent)}}.dark\:hover\:border-pink-900\/50:hover{border-color:#86104380}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:border-pink-900\/50:hover{border-color:color-mix(in oklab, var(--color-pink-900) 50%, transparent)}}.dark\:hover\:border-purple-900\/50:hover{border-color:#59168b80}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:border-purple-900\/50:hover{border-color:color-mix(in oklab, var(--color-purple-900) 50%, transparent)}}.dark\:hover\:border-rose-900\/50:hover{border-color:#8b083680}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:border-rose-900\/50:hover{border-color:color-mix(in oklab, var(--color-rose-900) 50%, transparent)}}.dark\:hover\:border-sky-900\/50:hover{border-color:#024a7080}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:border-sky-900\/50:hover{border-color:color-mix(in oklab, var(--color-sky-900) 50%, transparent)}}.dark\:hover\:border-white:hover{border-color:var(--color-white)}.dark\:hover\:bg-gray-700:hover{background-color:var(--color-gray-700)}.dark\:hover\:bg-gray-800:hover{background-color:var(--color-gray-800)}.dark\:hover\:bg-gray-800\/50:hover{background-color:#1e293980}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-gray-800\/50:hover{background-color:color-mix(in oklab, var(--color-gray-800) 50%, transparent)}}.dark\:hover\:bg-neutral-200:hover{background-color:var(--color-neutral-200)}.dark\:hover\:bg-neutral-800:hover{background-color:var(--color-neutral-800)}.dark\:hover\:bg-rose-400:hover{background-color:var(--color-rose-400)}.dark\:hover\:bg-white:hover{background-color:var(--color-white)}.dark\:hover\:text-gray-200:hover{color:var(--color-gray-200)}.dark\:hover\:text-neutral-300:hover{color:var(--color-neutral-300)}.dark\:hover\:text-white:hover{color:var(--color-white)}}}@starting-style{.starting\:opacity-0{opacity:0}}@media (prefers-reduced-motion:no-preference){@starting-style{.motion-safe\:starting\:-translate-x-\[26px\]{--tw-translate-x:calc(26px * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}}@starting-style{.motion-safe\:starting\:-translate-x-\[51px\]{--tw-translate-x:calc(51px * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}}@starting-style{.motion-safe\:starting\:-translate-x-\[78px\]{--tw-translate-x:calc(78px * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}}@starting-style{.motion-safe\:starting\:-translate-x-\[102px\]{--tw-translate-x:calc(102px * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}}@starting-style{.motion-safe\:starting\:translate-y-6{--tw-translate-y:calc(var(--spacing) * 6);translate:var(--tw-translate-x) var(--tw-translate-y)}}}.\[_a\]\:border-current:is(a){border-color:currentColor}.\[_a\]\:\!text-current:is(a),.\[_code\]\:\!text-current:is(code),.\[_kbd\]\:\!text-current:is(kbd),.\[_strong\]\:\!text-current:is(strong){color:currentColor!important}}.short-url-card{position:relative!important}.short-url-card .fi-ta-actions{z-index:10!important;margin:0!important;padding:0!important;position:absolute!important;top:1.25rem!important;right:1.25rem!important}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}@keyframes pulse{50%{opacity:.5}}@keyframes bounce{0%,to{animation-timing-function:cubic-bezier(.8,0,1,1);transform:translateY(-25%)}50%{animation-timing-function:cubic-bezier(0,0,.2,1);transform:none}} \ No newline at end of file diff --git a/resources/lang/en/default.php b/resources/lang/en/default.php index abc5da6..db9fffb 100644 --- a/resources/lang/en/default.php +++ b/resources/lang/en/default.php @@ -9,6 +9,16 @@ return [ 'tab_link' => 'Link Details', 'tab_tracking' => 'Tracking Settings', 'tab_qr_design' => 'QR Code Design', + 'tab_app_linking' => 'App Linking', + + // App Linking + 'form_section_app_linking' => 'App Linking / Deep Links', + 'auto_open_app_mobile' => 'Auto open app on mobile', + 'auto_open_app_mobile_helper' => 'Enable this if you want your link to automatically open as an app when accessed on mobile.', + 'supported_operating_systems' => 'Supported Operating Systems', + 'supported_apps' => 'Supported Apps', + 'supported_apps_helper' => 'If you do not find your app here, you can use the Targeting feature to redirect the user to your app with your custom deep link.', + 'matched' => 'Matched', // Link Form Fields 'destination_url' => 'Destination URL', @@ -466,4 +476,39 @@ return [ 'pixel_type' => 'Provider', 'pixel_id_label' => 'Pixel ID / Tag ID', 'pixel_status_active' => 'Active', + 'settings_tab_deep_linking' => 'Deep Linking', + 'settings_section_deep_linking' => 'Universal Links & App Links Association Files', + 'settings_deep_linking_enabled' => 'Enable Deep Linking Files', + 'settings_deep_linking_enabled_helper' => 'When enabled, the plugin serves AASA and AssetLinks configuration files from your root domain.', + 'settings_aasa_json' => 'apple-app-site-association (iOS)', + 'settings_aasa_json_helper' => 'Specify the valid JSON configuration for Apple App Site Association. Do not include wrapping script tags.', + 'settings_assetlinks_json' => 'assetlinks.json (Android)', + 'settings_assetlinks_json_helper' => 'Specify the valid JSON array configuration for Android Digital Asset Links.', + 'validation_invalid_json' => 'The entered text is not a valid JSON string.', + + // App Linking Preview + 'app_linking_supported_os' => 'Supported Operating Systems:', + 'app_linking_supported_apps' => 'Supported Apps', + 'app_linking_supported_apps_helper' => 'If you do not find your app here, you can use the Targeting feature to redirect the user to your app with your custom deep link.', + 'app_linking_matched' => 'Matched', + 'app_linking_preconfigured_count' => ':count apps pre-configured for automatic redirection.', + 'app_linking_redirect_active' => 'Opens directly inside :app', + 'app_linking_auto_open' => 'Auto-Open', + 'app_linking_matched_description' => 'When clicked on a mobile device, this link will open immediately inside the native :app application instead of the web browser.', + 'app_linking_deep_link_scheme' => 'Mobile app path (Deep Link): :scheme', + 'app_linking_standard_redirect' => 'This link will open in a standard mobile browser (no matching mobile app found).', + + // App Redirect Page + 'app_redirect_title' => 'Opening App...', + 'app_redirect_opening_in' => 'Opening in :app', + 'app_redirect_waiting_text' => 'We are redirecting you to the native application. Please wait a moment...', + 'app_redirect_btn_open' => 'Open Native App', + 'app_redirect_btn_browser' => 'Open in Browser', + 'app_redirect_in_app_warning_title' => 'In-App Browser Detected', + 'app_redirect_in_app_warning_desc' => 'Redirections can be restricted inside Instagram or Facebook. Tap the three dots (β€’β€’β€’) in the top-right corner and select "Open in Safari" or "Open in Chrome" to launch the app.', + + // Link Expired Page + 'expired_title' => 'Link Inactive or Expired', + 'expired_description' => 'This link is no longer active. It may have reached its click limit, expiration date, or has been deactivated.', + 'expired_btn_home' => 'Go to Homepage', ]; diff --git a/resources/lang/pl/default.php b/resources/lang/pl/default.php index 53dcf91..74e5594 100644 --- a/resources/lang/pl/default.php +++ b/resources/lang/pl/default.php @@ -9,6 +9,12 @@ return [ 'tab_link' => 'SzczegΓ³Ε‚y linku', 'tab_tracking' => 'Ustawienia Ε›ledzenia', 'tab_qr_design' => 'WyglΔ…d kodu QR', + 'tab_app_linking' => 'Autootwieranie aplikacji', + + // App Linking + 'form_section_app_linking' => 'Autootwieranie aplikacji / GΕ‚Δ™bokie linkowanie', + 'auto_open_app_mobile' => 'Automatycznie otwieraj aplikacjΔ™ na urzΔ…dzeniach mobilnych', + 'auto_open_app_mobile_helper' => 'WΕ‚Δ…cz tΔ™ opcjΔ™, jeΕ›li chcesz, aby po klikniΔ™ciu linku na telefonie automatycznie otwieraΕ‚a siΔ™ dedykowana aplikacja mobilna zamiast przeglΔ…darki.', // Link Form Fields 'destination_url' => 'Docelowy URL', @@ -467,4 +473,39 @@ return [ 'pixel_type' => 'Dostawca', 'pixel_id_label' => 'ID Piksela / Tagu', 'pixel_status_active' => 'Aktywny', + 'settings_tab_deep_linking' => 'GΕ‚Δ™bokie linkowanie', + 'settings_section_deep_linking' => 'Pliki powiΔ…zaΕ„ Universal Links & App Links', + 'settings_deep_linking_enabled' => 'WΕ‚Δ…cz serwowanie plikΓ³w powiΔ…zaΕ„', + 'settings_deep_linking_enabled_helper' => 'Po wΕ‚Δ…czeniu wtyczka bΔ™dzie serwowaΔ‡ pliki konfiguracyjne AASA (iOS) oraz AssetLinks (Android) z poziomu domeny gΕ‚Γ³wnej.', + 'settings_aasa_json' => 'apple-app-site-association (iOS)', + 'settings_aasa_json_helper' => 'WprowadΕΊ prawidΕ‚owy kod JSON dla Apple App Site Association. Nie doΕ‚Δ…czaj znacznikΓ³w HTML/JavaScript.', + 'settings_assetlinks_json' => 'assetlinks.json (Android)', + 'settings_assetlinks_json_helper' => 'WprowadΕΊ prawidΕ‚owΔ… tablicΔ™ JSON dla Android Digital Asset Links.', + 'validation_invalid_json' => 'Wprowadzony tekst nie jest poprawnym ciΔ…giem JSON.', + + // App Linking Preview + 'app_linking_supported_os' => 'Wspierane systemy operacyjne:', + 'app_linking_supported_apps' => 'Wspierane aplikacje', + 'app_linking_supported_apps_helper' => 'JeΕ›li nie znajdziesz swojej aplikacji na liΕ›cie, moΕΌesz uΕΌyΔ‡ funkcji Targetowania, aby przekierowaΔ‡ uΕΌytkownika za pomocΔ… wΕ‚asnego gΕ‚Δ™bokiego linku (Deep Link).', + 'app_linking_matched' => 'Dopasowano', + 'app_linking_preconfigured_count' => ':count gotowych aplikacji do automatycznego przekierowania.', + 'app_linking_redirect_active' => 'Otwiera siΔ™ bezpoΕ›rednio w :app', + 'app_linking_auto_open' => 'Autootwieranie', + 'app_linking_matched_description' => 'Po klikniΔ™ciu na telefonie lub tablecie, ten link otworzy siΔ™ od razu w dedykowanej aplikacji :app zamiast w zwykΕ‚ej przeglΔ…darce.', + 'app_linking_deep_link_scheme' => 'UΕΌywany schemat (Deep Link): :scheme', + 'app_linking_standard_redirect' => 'Ten link otworzy siΔ™ w zwykΕ‚ej przeglΔ…darce internetowej (brak dopasowanej aplikacji mobilnej).', + + // App Redirect Page + 'app_redirect_title' => 'Otwieranie aplikacji...', + 'app_redirect_opening_in' => 'Otwieranie w: :app', + 'app_redirect_waiting_text' => 'Przekierowujemy CiΔ™ do natywnej aplikacji. ProszΔ™ czekaΔ‡...', + 'app_redirect_btn_open' => 'OtwΓ³rz aplikacjΔ™', + 'app_redirect_btn_browser' => 'OtwΓ³rz w przeglΔ…darce', + 'app_redirect_in_app_warning_title' => 'Wykryto przeglΔ…darkΔ™ wewnΔ…trz aplikacji', + 'app_redirect_in_app_warning_desc' => 'Przekierowania mogΔ… byΔ‡ blokowane wewnΔ…trz Instagrama lub Facebooka. Kliknij ikonΔ™ trzech kropek (β€’β€’β€’) w prawym gΓ³rnym rogu i wybierz β€žOtwΓ³rz w Safari” lub β€žOtwΓ³rz w Chrome”, aby uruchomiΔ‡ aplikacjΔ™.', + + // Link Expired Page + 'expired_title' => 'Link nieaktywny lub wygasΕ‚', + 'expired_description' => 'Ten link jest juΕΌ nieaktywny. MΓ³gΕ‚ osiΔ…gnΔ…Δ‡ limit klikniΔ™Δ‡, minΔ…Ε‚ jego termin waΕΌnoΕ›ci lub zostaΕ‚ wyΕ‚Δ…czony.', + 'expired_btn_home' => 'PrzejdΕΊ do strony gΕ‚Γ³wnej', ]; diff --git a/resources/views/app-linking-preview.blade.php b/resources/views/app-linking-preview.blade.php new file mode 100644 index 0000000..f5e4f37 --- /dev/null +++ b/resources/views/app-linking-preview.blade.php @@ -0,0 +1,105 @@ +@php + $matchedAppId = \Bjanczak\FilamentShortUrl\Services\AppLinkingEngine::matchApp($destinationUrl); + $apps = \Bjanczak\FilamentShortUrl\Services\AppLinkingEngine::getSupportedApps(); +@endphp + +
+ +
+ + +
+
+

+ {{ __('filament-short-url::default.app_linking_supported_apps') }} +

+
+ +
+ + {{ __('filament-short-url::default.app_linking_supported_os') }} + + iOS + Android +
+
+ + + @if ($matchedAppId && isset($apps[$matchedAppId])) + @php + $matchedApp = $apps[$matchedAppId]; + $matchedDomain = explode('/', $matchedApp['domains'][0])[0]; + $matchedFavicon = "https://icons.duckduckgo.com/ip2/{$matchedDomain}.ico"; + $deepLink = \Bjanczak\FilamentShortUrl\Services\AppLinkingEngine::convertToScheme($destinationUrl, $matchedAppId); + @endphp +
+
+ +
+ {{ $matchedApp['name'] }} +
+ +
+
+
+ {{ __('filament-short-url::default.app_linking_redirect_active', ['app' => $matchedApp['name']]) }} +
+ + {{ __('filament-short-url::default.app_linking_auto_open') }} + +
+

+ {!! __('filament-short-url::default.app_linking_matched_description', ['app' => e($matchedApp['name'])]) !!} +

+
+ {{ __('filament-short-url::default.app_linking_deep_link_scheme', ['scheme' => $deepLink]) }} +
+
+
+
+ @else + +
+
+ + + +
+ + {{ __('filament-short-url::default.app_linking_standard_redirect') }} + +
+ @endif + + +
+ @foreach ($apps as $appId => $app) + @php + $isMatched = ($appId === $matchedAppId); + $appDomain = explode('/', $app['domains'][0])[0]; + $appFavicon = "https://icons.duckduckgo.com/ip2/{$appDomain}.ico"; + @endphp +
+ +
+ {{ $app['name'] }} +
+ + {{ $app['name'] }} + + @if ($isMatched) + + βœ“ + + @endif +
+ @endforeach +
+ + +

+ {{ __('filament-short-url::default.app_linking_supported_apps_helper') }} +

+ +
+
diff --git a/resources/views/app-redirect.blade.php b/resources/views/app-redirect.blade.php new file mode 100644 index 0000000..c9be468 --- /dev/null +++ b/resources/views/app-redirect.blade.php @@ -0,0 +1,274 @@ + + + + + + {{ __('filament-short-url::default.app_redirect_title') ?? 'Opening App...' }} + + + + + + + + + + + + @php + $pixelMetaIds = $pixels->where('type', 'meta')->pluck('pixel_id'); + $pixelGoogleIds = $pixels->where('type', 'google')->pluck('pixel_id'); + $pixelLinkedinIds = $pixels->where('type', 'linkedin')->pluck('pixel_id'); + $pixelTiktokIds = $pixels->where('type', 'tiktok')->pluck('pixel_id'); + $pixelPinterestIds = $pixels->where('type', 'pinterest')->pluck('pixel_id'); + @endphp + + + @if($pixelMetaIds->isNotEmpty()) + + @foreach($pixelMetaIds as $id) + + @endforeach + @endif + + + @if($pixelGoogleIds->isNotEmpty()) + @php $firstGoogleId = $pixelGoogleIds->first(); @endphp + + + @endif + + + @if($pixelLinkedinIds->isNotEmpty()) + + @foreach($pixelLinkedinIds as $id) + + @endforeach + @endif + + + @if($pixelTiktokIds->isNotEmpty()) + + @endif + + + @if($pixelPinterestIds->isNotEmpty()) + + @foreach($pixelPinterestIds as $id) + + @endforeach + @endif + + + @php + $siteName = config('filament-short-url.site_name') ?: config('app.name', 'Laravel'); + + // Retrieve app metadata for premium visual hints + $apps = \Bjanczak\FilamentShortUrl\Services\AppLinkingEngine::getSupportedApps(); + $matchedApp = $apps[$appId] ?? null; + $appColor = $matchedApp['color'] ?? '#3b82f6'; + $appName = $matchedApp['name'] ?? 'App'; + @endphp + + {{-- Main Container --}} +
+
+ {{ $siteName }} + + +
+ +
+ +
+
+ +
+ {{ substr($appName, 0, 1) }} +
+
+ +

+ {{ __('filament-short-url::default.app_redirect_opening_in', ['app' => $appName]) ?? "Opening in {$appName}" }} +

+

+ {{ __('filament-short-url::default.app_redirect_waiting_text') ?? 'We are redirecting you to the native application. Please wait a moment...' }} +

+
+ +
+ {{-- Action Buttons --}} + + + {{-- In-App Browser Alert Banner (Hidden by default, shown via JS) --}} + +
+
+ + {{-- Footer section --}} +
+ Β© {{ date('Y') }} {{ $siteName }}. All rights reserved. +
+ + + + + diff --git a/resources/views/expired.blade.php b/resources/views/expired.blade.php new file mode 100644 index 0000000..cf1d602 --- /dev/null +++ b/resources/views/expired.blade.php @@ -0,0 +1,90 @@ + + + + + + {{ __('filament-short-url::default.expired_title') ?? 'Link Inactive or Expired' }} + + + + + + + + + + + + + @php + $siteName = config('filament-short-url.site_name') ?: config('app.name', 'Laravel'); + @endphp + + {{-- Main Expiry Box --}} +
+
+ {{ $siteName }} + +
+ + + +
+ +

+ {{ __('filament-short-url::default.expired_title') ?? 'Link Inactive or Expired' }} +

+

+ {{ __('filament-short-url::default.expired_description') ?? 'This link is no longer active. It may have reached its click limit, expiration date, or has been deactivated.' }} +

+
+ +
+ {{-- Short URL info box --}} + @if ($shortUrl) +
+
+ + Expired Link + +

+ {{ $shortUrl->getShortUrl() }} +

+
+
+ @endif + + {{-- Action Button --}} + + {{ __('filament-short-url::default.expired_btn_home') ?? 'Go to Homepage' }} + + + + +
+
+ + {{-- Footer section --}} +
+ Β© {{ date('Y') }} {{ $siteName }} Inc. All rights reserved. +
+ + diff --git a/routes/web.php b/routes/web.php index bf6b1b3..12435d7 100644 --- a/routes/web.php +++ b/routes/web.php @@ -7,6 +7,13 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Route; +Route::get('/.well-known/apple-app-site-association', [ShortUrlRedirectController::class, 'serveAasa']) + ->middleware(['web']); +Route::get('/apple-app-site-association', [ShortUrlRedirectController::class, 'serveAasa']) + ->middleware(['web']); +Route::get('/.well-known/assetlinks.json', [ShortUrlRedirectController::class, 'serveAssetLinks']) + ->middleware(['web']); + Route::match( ['GET', 'POST'], config('filament-short-url.route_prefix', 's').'/{key}', @@ -16,6 +23,7 @@ Route::match( ->where('key', '[a-zA-Z0-9_-]+') ->middleware(config('filament-short-url.middleware', ['web', 'throttle:120,1'])); + Route::prefix('api/short-url') ->middleware([AuthenticateShortUrlApi::class]) ->group(function () { diff --git a/src/Filament/Resources/ShortUrlPixelResource.php b/src/Filament/Resources/ShortUrlPixelResource.php index 42f2cfe..7704915 100644 --- a/src/Filament/Resources/ShortUrlPixelResource.php +++ b/src/Filament/Resources/ShortUrlPixelResource.php @@ -7,10 +7,10 @@ use Bjanczak\FilamentShortUrl\Models\ShortUrlPixel; use Filament\Forms\Components\Select; use Filament\Forms\Components\TextInput; use Filament\Forms\Components\Toggle; +use Filament\Actions\DeleteAction; +use Filament\Actions\EditAction; use Filament\Resources\Resource; use Filament\Schemas\Schema; -use Filament\Tables\Actions\DeleteAction; -use Filament\Tables\Actions\EditAction; use Filament\Tables\Columns\IconColumn; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Columns\ToggleColumn; @@ -137,8 +137,17 @@ class ShortUrlPixelResource extends Resource ]) ->filters([]) ->actions([ - EditAction::make()->modalWidth('md'), - DeleteAction::make(), + EditAction::make() + ->icon('heroicon-o-pencil-square') + ->color('gray') + ->iconButton() + ->tooltip(__('filament-short-url::default.action_edit')) + ->modalWidth('md'), + DeleteAction::make() + ->icon('heroicon-o-trash') + ->color('gray') + ->iconButton() + ->tooltip(__('filament-short-url::default.action_delete')), ]) ->bulkActions([]); } diff --git a/src/Filament/Resources/ShortUrlResource.php b/src/Filament/Resources/ShortUrlResource.php index baa09ec..e5edf3d 100644 --- a/src/Filament/Resources/ShortUrlResource.php +++ b/src/Filament/Resources/ShortUrlResource.php @@ -3,7 +3,6 @@ namespace Bjanczak\FilamentShortUrl\Filament\Resources; use Bjanczak\FilamentShortUrl\Filament\Resources\ShortUrlResource\Pages\ListShortUrls; -use Bjanczak\FilamentShortUrl\Filament\Resources\ShortUrlResource\Pages\ShortUrlSettingsPage; use Bjanczak\FilamentShortUrl\Filament\Resources\ShortUrlResource\Pages\ViewShortUrlLogs; use Bjanczak\FilamentShortUrl\Filament\Resources\ShortUrlResource\Pages\ViewShortUrlStats; use Bjanczak\FilamentShortUrl\Filament\Resources\ShortUrlResource\Schemas\ShortUrlForm; @@ -113,7 +112,6 @@ class ShortUrlResource extends Resource 'index' => ListShortUrls::route('/'), 'stats' => ViewShortUrlStats::route('/{record}/stats'), 'stats.logs' => ViewShortUrlLogs::route('/{record}/stats/logs'), - 'settings' => ShortUrlSettingsPage::route('/settings'), ]; } } diff --git a/src/Filament/Resources/ShortUrlResource/Pages/ListShortUrls.php b/src/Filament/Resources/ShortUrlResource/Pages/ListShortUrls.php index 2c9ac56..f80502b 100644 --- a/src/Filament/Resources/ShortUrlResource/Pages/ListShortUrls.php +++ b/src/Filament/Resources/ShortUrlResource/Pages/ListShortUrls.php @@ -19,14 +19,6 @@ class ListShortUrls extends ManageRecords protected function getHeaderActions(): array { return [ - Action::make('settings') - ->label(__('filament-short-url::default.settings_nav_label')) - ->icon('heroicon-o-adjustments-horizontal') - ->color('gray') - ->size('sm') - ->url(static::getResource()::getUrl('settings')) - ->visible(fn () => ShortUrlSettingsPage::canAccess()), - CreateAction::make() ->icon('heroicon-o-plus') ->size('sm') diff --git a/src/Filament/Resources/ShortUrlResource/Pages/ShortUrlSettingsPage.php b/src/Filament/Resources/ShortUrlResource/Pages/ShortUrlSettingsPage.php index 3aee686..4fd72ed 100644 --- a/src/Filament/Resources/ShortUrlResource/Pages/ShortUrlSettingsPage.php +++ b/src/Filament/Resources/ShortUrlResource/Pages/ShortUrlSettingsPage.php @@ -12,12 +12,13 @@ use Filament\Forms\Components\ColorPicker; use Filament\Forms\Components\Placeholder; use Filament\Forms\Components\Repeater; use Filament\Forms\Components\Select; +use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Forms\Components\Toggle; use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Contracts\HasForms; use Filament\Notifications\Notification; -use Filament\Resources\Pages\Page; +use Filament\Pages\Page; use Filament\Schemas\Components\Actions; use Filament\Schemas\Components\Section; use Filament\Schemas\Components\Tabs; @@ -32,10 +33,35 @@ class ShortUrlSettingsPage extends Page implements HasForms { use InteractsWithForms; - protected static string $resource = ShortUrlResource::class; + protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-cog-6-tooth'; + + protected static ?string $slug = 'short-url-settings'; protected string $view = 'filament-short-url::settings'; + public static function getNavigationLabel(): string + { + return __('filament-short-url::default.settings_nav_label') ?? 'Settings'; + } + + public static function getNavigationGroup(): string|\UnitEnum|null + { + try { + return ShortUrlResource::getNavigationGroup(); + } catch (\Throwable) { + return __('filament-short-url::default.navigation_group'); + } + } + + public static function getNavigationSort(): ?int + { + try { + return ShortUrlResource::getNavigationSort() + 2; + } catch (\Throwable) { + return 52; + } + } + public static function canAccess(array $parameters = []): bool { try { @@ -55,7 +81,7 @@ class ShortUrlSettingsPage extends Page implements HasForms } // Default fallback: Check if the user is authorized to view the resource in general - return static::getResource()::canViewAny(); + return ShortUrlResource::canViewAny(); } public ?array $data = []; @@ -64,6 +90,22 @@ class ShortUrlSettingsPage extends Page implements HasForms { $mgr = app(ShortUrlSettingsManager::class); + $aasa = $mgr->get('aasa_json'); + if (! empty($aasa)) { + $decoded = json_decode($aasa, true); + if (json_last_error() === JSON_ERROR_NONE) { + $aasa = json_encode($decoded, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } + } + + $assetlinks = $mgr->get('assetlinks_json'); + if (! empty($assetlinks)) { + $decoded = json_decode($assetlinks, true); + if (json_last_error() === JSON_ERROR_NONE) { + $assetlinks = json_encode($decoded, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } + } + $this->form->fill([ 'route_prefix' => $mgr->get('route_prefix', 's'), 'redirect_status_code' => $mgr->get('redirect_status_code', 302), @@ -117,6 +159,10 @@ class ShortUrlSettingsPage extends Page implements HasForms 'vpn_block_action' => $mgr->get('vpn_block_action', 'flag_only'), 'safe_browsing_enabled' => $mgr->get('safe_browsing_enabled', false), 'google_safe_browsing_api_key' => $mgr->get('google_safe_browsing_api_key'), + // Deep Linking v2.1 + 'deep_linking_enabled' => $mgr->get('deep_linking_enabled', false), + 'aasa_json' => $aasa, + 'assetlinks_json' => $assetlinks, ]); } @@ -823,6 +869,65 @@ class ShortUrlSettingsPage extends Page implements HasForms ->visible(fn (Get $get): bool => (bool) $get('global_webhook_enabled')), ]), ]), + + // ── Deep Linking ───────────────────────────────────── + Tab::make(__('filament-short-url::default.settings_tab_deep_linking')) + ->icon('heroicon-o-device-phone-mobile') + ->schema([ + Section::make(__('filament-short-url::default.settings_section_deep_linking')) + ->schema([ + Toggle::make('deep_linking_enabled') + ->label(__('filament-short-url::default.settings_deep_linking_enabled')) + ->helperText(__('filament-short-url::default.settings_deep_linking_enabled_helper')) + ->default(false) + ->inline(false) + ->live(), + + Textarea::make('aasa_json') + ->label(__('filament-short-url::default.settings_aasa_json')) + ->helperText(__('filament-short-url::default.settings_aasa_json_helper')) + ->nullable() + ->visible(fn (Get $get): bool => (bool) $get('deep_linking_enabled')) + ->columnSpanFull() + ->extraInputAttributes(['style' => 'font-family: monospace;']) + ->rows(8) + ->rules([ + function () { + return function (string $attribute, $value, \Closure $fail) { + if (empty($value)) { + return; + } + json_decode($value); + if (json_last_error() !== JSON_ERROR_NONE) { + $fail(__('filament-short-url::default.validation_invalid_json')); + } + }; + }, + ]), + + Textarea::make('assetlinks_json') + ->label(__('filament-short-url::default.settings_assetlinks_json')) + ->helperText(__('filament-short-url::default.settings_assetlinks_json_helper')) + ->nullable() + ->visible(fn (Get $get): bool => (bool) $get('deep_linking_enabled')) + ->columnSpanFull() + ->extraInputAttributes(['style' => 'font-family: monospace;']) + ->rows(8) + ->rules([ + function () { + return function (string $attribute, $value, \Closure $fail) { + if (empty($value)) { + return; + } + json_decode($value); + if (json_last_error() !== JSON_ERROR_NONE) { + $fail(__('filament-short-url::default.validation_invalid_json')); + } + }; + }, + ]), + ]), + ]), ]), ]) ->statePath('data'); @@ -834,6 +939,10 @@ class ShortUrlSettingsPage extends Page implements HasForms app(ShortUrlSettingsManager::class)->set($data); + // Clear deep linking cache when settings are saved! + cache()->forget('fsu:deep-linking:aasa'); + cache()->forget('fsu:deep-linking:assetlinks'); + Notification::make() ->title(__('filament-short-url::default.settings_saved')) ->success() @@ -848,7 +957,7 @@ class ShortUrlSettingsPage extends Page implements HasForms ->icon('heroicon-o-arrow-left') ->color('gray') ->size('sm') - ->url(static::getResource()::getUrl()), + ->url(ShortUrlResource::getUrl()), ]; } diff --git a/src/Filament/Resources/ShortUrlResource/Schemas/ShortUrlForm.php b/src/Filament/Resources/ShortUrlResource/Schemas/ShortUrlForm.php index 4a4aa54..72c7977 100644 --- a/src/Filament/Resources/ShortUrlResource/Schemas/ShortUrlForm.php +++ b/src/Filament/Resources/ShortUrlResource/Schemas/ShortUrlForm.php @@ -28,6 +28,7 @@ class ShortUrlForm Tabs::make()->tabs([ static::linkTab(), static::targetingTab(), + static::appLinkingTab(), static::trackingTab(), static::marketingTab(), static::qrDesignTab(), @@ -569,4 +570,30 @@ class ShortUrlForm ]), ]); } + + private static function appLinkingTab(): Tab + { + return Tab::make(__('filament-short-url::default.tab_app_linking') ?? 'App Linking') + ->icon('heroicon-o-device-phone-mobile') + ->schema([ + Section::make(__('filament-short-url::default.form_section_app_linking') ?? 'App Linking / Deep Links') + ->schema([ + Toggle::make('auto_open_app_mobile') + ->label(__('filament-short-url::default.auto_open_app_mobile') ?? 'Auto open app on mobile') + ->helperText(__('filament-short-url::default.auto_open_app_mobile_helper') ?? 'Enable this if you want your link to automatically open as an app when accessed on mobile.') + ->default(false) + ->inline(false) + ->live(), + + ViewField::make('app_linking_preview') + ->view('filament-short-url::app-linking-preview') + ->viewData(fn (Get $get) => [ + 'destinationUrl' => $get('destination_url'), + ]) + ->columnSpanFull() + ->visible(fn (Get $get): bool => (bool) $get('auto_open_app_mobile')), + ]), + ]); + } } + diff --git a/src/FilamentShortUrlPlugin.php b/src/FilamentShortUrlPlugin.php index 129861a..898ff6b 100644 --- a/src/FilamentShortUrlPlugin.php +++ b/src/FilamentShortUrlPlugin.php @@ -46,6 +46,9 @@ class FilamentShortUrlPlugin implements Plugin ->resources([ ShortUrlResource::class, ShortUrlPixelResource::class, + ]) + ->pages([ + \Bjanczak\FilamentShortUrl\Filament\Resources\ShortUrlResource\Pages\ShortUrlSettingsPage::class, ]); } diff --git a/src/FilamentShortUrlServiceProvider.php b/src/FilamentShortUrlServiceProvider.php index 4636f1f..673371c 100644 --- a/src/FilamentShortUrlServiceProvider.php +++ b/src/FilamentShortUrlServiceProvider.php @@ -39,6 +39,8 @@ class FilamentShortUrlServiceProvider extends PackageServiceProvider '2026_06_02_224250_add_qr_logo_to_short_urls_table', '2026_06_03_110000_add_qr_and_language_to_visits_and_daily_stats', '2026_06_03_120000_add_track_browser_language_to_short_urls_table', + '2026_06_03_150000_create_short_url_pixels_table', + '2026_06_03_160000_add_auto_open_app_mobile_to_short_urls_table', ]) ->hasCommands([ SyncBufferedCountersCommand::class, diff --git a/src/Http/Controllers/ShortUrlRedirectController.php b/src/Http/Controllers/ShortUrlRedirectController.php index a6a1377..24c5103 100644 --- a/src/Http/Controllers/ShortUrlRedirectController.php +++ b/src/Http/Controllers/ShortUrlRedirectController.php @@ -4,9 +4,11 @@ namespace Bjanczak\FilamentShortUrl\Http\Controllers; use Bjanczak\FilamentShortUrl\Jobs\TrackShortUrlVisitJob; use Bjanczak\FilamentShortUrl\Models\ShortUrl; +use Bjanczak\FilamentShortUrl\Services\AppLinkingEngine; use Bjanczak\FilamentShortUrl\Services\ClientIpExtractor; use Bjanczak\FilamentShortUrl\Services\ProxyDetectionService; use Bjanczak\FilamentShortUrl\Services\ShortUrlService; +use Bjanczak\FilamentShortUrl\Services\UserAgentParser; use Illuminate\Http\Request; use Illuminate\Routing\Controller; use Illuminate\Support\Facades\Log; @@ -35,7 +37,9 @@ class ShortUrlRedirectController extends Controller return redirect()->away($shortUrl->expiration_redirect_url, 302); } - abort(410); + return response(view('filament-short-url::expired', [ + 'shortUrl' => $shortUrl, + ]), 410)->header('Content-Type', 'text/html'); } // 1. VPN/Proxy & Bot Blocking Check @@ -92,6 +96,27 @@ class ShortUrlRedirectController extends Controller // 4. Resolve Destination URL (evaluating targeting rules and forwarding query parameters) $destination = $this->service->resolveRedirectUrl($shortUrl, $request); + // App Linking / Deep Links Auto-Open Check + if ($shortUrl->auto_open_app_mobile) { + $uaParser = app(UserAgentParser::class); + $parsedUa = $uaParser->parse($request->userAgent() ?? ''); + + if ($parsedUa['device_type'] === 'mobile' || $parsedUa['device_type'] === 'tablet') { + $matchedApp = AppLinkingEngine::matchApp($destination); + if ($matchedApp !== null) { + $deepLink = AppLinkingEngine::convertToScheme($destination, $matchedApp); + $activePixels = $shortUrl->pixels()->where('is_active', true)->get(); + + return response(view('filament-short-url::app-redirect', [ + 'destination' => $destination, + 'deepLink' => $deepLink, + 'appId' => $matchedApp, + 'pixels' => $activePixels, + ]))->header('Content-Type', 'text/html'); + } + } + } + // 5. Warning / Intermediate Page Check if ($shortUrl->show_warning_page && ! $request->has('confirmed')) { return response(view('filament-short-url::warning', ['destinationUrl' => $destination])) @@ -155,7 +180,9 @@ class ShortUrlRedirectController extends Controller // Another request beat us to it β€” this visit should 410 if ($affected === 0) { - abort(410); + return response(view('filament-short-url::expired', [ + 'shortUrl' => $shortUrl, + ]), 410)->header('Content-Type', 'text/html'); } // Manually forget cache since DB-level update does not trigger Eloquent events @@ -173,4 +200,70 @@ class ShortUrlRedirectController extends Controller return redirect()->away($destination, $shortUrl->redirect_status_code); } + + /** + * Serve the Apple App Site Association (AASA) file for iOS Universal Links. + */ + public function serveAasa(Request $request): Response + { + if (! config('filament-short-url.deep_linking.enabled', false)) { + abort(404); + } + + $aasaJson = config('filament-short-url.deep_linking.aasa_json'); + + if (empty($aasaJson)) { + abort(404); + } + + $minified = cache()->remember('fsu:deep-linking:aasa', 604800, function () use ($aasaJson): string { + try { + $decoded = json_decode($aasaJson, true, 512, JSON_THROW_ON_ERROR); + + return json_encode($decoded, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } catch (\Throwable) { + return $aasaJson; + } + }); + + return response($minified, 200, [ + 'Content-Type' => 'application/json; charset=utf-8', + 'Cache-Control' => 'public, max-age=604800, must-revalidate', + 'X-Content-Type-Options' => 'nosniff', + 'Access-Control-Allow-Origin' => '*', + ]); + } + + /** + * Serve the Asset Links file for Android App Links. + */ + public function serveAssetLinks(Request $request): Response + { + if (! config('filament-short-url.deep_linking.enabled', false)) { + abort(404); + } + + $assetlinksJson = config('filament-short-url.deep_linking.assetlinks_json'); + + if (empty($assetlinksJson)) { + abort(404); + } + + $minified = cache()->remember('fsu:deep-linking:assetlinks', 604800, function () use ($assetlinksJson): string { + try { + $decoded = json_decode($assetlinksJson, true, 512, JSON_THROW_ON_ERROR); + + return json_encode($decoded, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } catch (\Throwable) { + return $assetlinksJson; + } + }); + + return response($minified, 200, [ + 'Content-Type' => 'application/json; charset=utf-8', + 'Cache-Control' => 'public, max-age=604800, must-revalidate', + 'X-Content-Type-Options' => 'nosniff', + 'Access-Control-Allow-Origin' => '*', + ]); + } } diff --git a/src/Models/ShortUrl.php b/src/Models/ShortUrl.php index f7155cf..1cf2728 100644 --- a/src/Models/ShortUrl.php +++ b/src/Models/ShortUrl.php @@ -86,6 +86,7 @@ class ShortUrl extends Model 'webhook_url', 'qr_logo', 'qr_scans', + 'auto_open_app_mobile', ]; /** @var array */ @@ -93,6 +94,7 @@ class ShortUrl extends Model 'is_enabled' => 'boolean', 'single_use' => 'boolean', 'forward_query_params' => 'boolean', + 'auto_open_app_mobile' => 'boolean', 'track_visits' => 'boolean', 'track_ip_address' => 'boolean', 'track_browser' => 'boolean', diff --git a/src/Services/AppLinkingEngine.php b/src/Services/AppLinkingEngine.php new file mode 100644 index 0000000..18ce812 --- /dev/null +++ b/src/Services/AppLinkingEngine.php @@ -0,0 +1,242 @@ + + */ + public static function getSupportedApps(): array + { + return [ + 'youtube' => [ + 'name' => 'YouTube', + 'color' => '#ff0000', + 'icon' => 'fab-youtube', + 'domains' => ['youtube.com', 'youtu.be', 'youtube-nocookie.com'], + ], + 'tiktok' => [ + 'name' => 'TikTok', + 'color' => '#fc295d', + 'icon' => 'fab-tiktok', + 'domains' => ['tiktok.com'], + ], + 'instagram' => [ + 'name' => 'Instagram', + 'color' => '#e1306c', + 'icon' => 'fab-instagram', + 'domains' => ['instagram.com', 'instagr.am'], + ], + 'x' => [ + 'name' => 'X (Twitter)', + 'color' => '#1da1f2', + 'icon' => 'fab-x-twitter', + 'domains' => ['x.com', 'twitter.com'], + ], + 'spotify' => [ + 'name' => 'Spotify', + 'color' => '#2cd85c', + 'icon' => 'fab-spotify', + 'domains' => ['spotify.com', 'open.spotify.com', 'spotify.link'], + ], + 'facebook' => [ + 'name' => 'Facebook', + 'color' => '#1877f2', + 'icon' => 'fab-facebook', + 'domains' => ['facebook.com', 'fb.com', 'fb.me'], + ], + 'reddit' => [ + 'name' => 'Reddit', + 'color' => '#fc3a06', + 'icon' => 'fab-reddit', + 'domains' => ['reddit.com', 'redd.it'], + ], + 'snapchat' => [ + 'name' => 'Snapchat', + 'color' => '#ffb700', + 'icon' => 'fab-snapchat', + 'domains' => ['snapchat.com'], + ], + 'whatsapp' => [ + 'name' => 'WhatsApp', + 'color' => '#128c7e', + 'icon' => 'fab-whatsapp', + 'domains' => ['whatsapp.com', 'wa.me', 'api.whatsapp.com'], + ], + 'linkedin' => [ + 'name' => 'LinkedIn', + 'color' => '#0a66c2', + 'icon' => 'fab-linkedin', + 'domains' => ['linkedin.com'], + ], + 'pinterest' => [ + 'name' => 'Pinterest', + 'color' => '#e60023', + 'icon' => 'fab-pinterest', + 'domains' => ['pinterest.com', 'pin.it'], + ], + 'twitch' => [ + 'name' => 'Twitch', + 'color' => '#9146ff', + 'icon' => 'fab-twitch', + 'domains' => ['twitch.tv'], + ], + 'netflix' => [ + 'name' => 'Netflix', + 'color' => '#e50914', + 'icon' => 'fas-film', + 'domains' => ['netflix.com'], + ], + 'google_sheets' => [ + 'name' => 'Google Sheets', + 'color' => '#25a465', + 'icon' => 'fas-file', + 'domains' => ['docs.google.com/spreadsheets'], + ], + 'google_docs' => [ + 'name' => 'Google Docs', + 'color' => '#2a7efc', + 'icon' => 'fas-file-word', + 'domains' => ['docs.google.com/document'], + ], + 'google_slides' => [ + 'name' => 'Google Slides', + 'color' => '#fabe0b', + 'icon' => 'fas-image', + 'domains' => ['docs.google.com/presentation'], + ], + 'google_maps' => [ + 'name' => 'Google Maps', + 'color' => '#4285f4', + 'icon' => 'fas-map-location-dot', + 'domains' => ['google.com/maps', 'maps.google.com', 'maps.app.goo.gl'], + ], + 'facebook_messenger' => [ + 'name' => 'Facebook Messenger', + 'color' => '#0084ff', + 'icon' => 'fab-facebook-messenger', + 'domains' => ['messenger.com'], + ], + 'apple_music' => [ + 'name' => 'Apple Music', + 'color' => '#f8506b', + 'icon' => 'fab-apple', + 'domains' => ['music.apple.com'], + ], + 'airbnb' => [ + 'name' => 'Airbnb', + 'color' => '#ff5a5f', + 'icon' => 'fab-airbnb', + 'domains' => ['airbnb.com', 'airbnb.pl', 'airbnb.de', 'airbnb.fr'], + ], + 'tripadvisor' => [ + 'name' => 'TripAdvisor', + 'color' => '#00af87', + 'icon' => 'fas-plane', + 'domains' => ['tripadvisor.com', 'tripadvisor.pl'], + ], + 'amazon' => [ + 'name' => 'Amazon', + 'color' => '#ff9900', + 'icon' => 'fab-amazon', + 'domains' => ['amazon.com', 'amazon.co.uk', 'amazon.de', 'amazon.pl', 'amazon.fr', 'amazon.it', 'amazon.es'], + ], + 'stockx' => [ + 'name' => 'StockX', + 'color' => '#006341', + 'icon' => 'fas-chart-line', + 'domains' => ['stockx.com'], + ], + 'booking' => [ + 'name' => 'Booking.com', + 'color' => '#003580', + 'icon' => 'fas-hotel', + 'domains' => ['booking.com'], + ], + 'aliexpress' => [ + 'name' => 'AliExpress', + 'color' => '#e62e04', + 'icon' => 'fas-cart-shopping', + 'domains' => ['aliexpress.com', 'aliexpress.ru'], + ], + ]; + } + + /** + * Identify the app matching the destination URL. + */ + public static function matchApp(?string $url): ?string + { + if (empty($url)) { + return null; + } + + $urlLower = strtolower($url); + + foreach (static::getSupportedApps() as $appId => $app) { + foreach ($app['domains'] as $domain) { + if (str_contains($urlLower, $domain)) { + return $appId; + } + } + } + + return null; + } + + /** + * Convert standard HTTP URL to its native deep link scheme. + */ + public static function convertToScheme(string $url, string $appId): string + { + // Standard fallback: replace http(s) with scheme + $scheme = match ($appId) { + 'youtube' => 'youtube://', + 'tiktok' => 'tiktok://', + 'instagram' => 'instagram://', + 'x' => 'twitter://', + 'spotify' => 'spotify://', + 'facebook' => 'fb://', + 'reddit' => 'reddit://', + 'snapchat' => 'snapchat://', + 'whatsapp' => 'whatsapp://', + 'linkedin' => 'linkedin://', + 'pinterest' => 'pinterest://', + 'twitch' => 'twitch://', + 'netflix' => 'netflix://', + 'facebook_messenger' => 'fb-messenger://', + 'apple_music' => 'music://', + 'airbnb' => 'airbnb://', + 'tripadvisor' => 'tripadvisor://', + 'amazon' => 'amazon://', + 'stockx' => 'stockx://', + 'booking' => 'booking://', + 'aliexpress' => 'aliexpress://', + 'google_sheets' => 'googlesheets://', + 'google_docs' => 'googledocs://', + 'google_slides' => 'googleslides://', + 'google_maps' => 'googlemaps://', + default => null, + }; + + if ($scheme === null) { + return $url; + } + + // Strip http:// or https:// + $urlWithoutProtocol = preg_replace('/^https?:\/\//i', '', $url); + + // Spotify URI format (special case) + if ($appId === 'spotify') { + // open.spotify.com/track/123 -> spotify:track:123 + if (preg_match('/open\.spotify\.com\/(track|playlist|album|artist)\/([a-zA-Z0-9]+)/i', $url, $matches)) { + return "spotify:{$matches[1]}:{$matches[2]}"; + } + } + + return $scheme . $urlWithoutProtocol; + } +} diff --git a/src/Services/ShortUrlSettingsManager.php b/src/Services/ShortUrlSettingsManager.php index a15a379..3149fb8 100644 --- a/src/Services/ShortUrlSettingsManager.php +++ b/src/Services/ShortUrlSettingsManager.php @@ -96,6 +96,10 @@ class ShortUrlSettingsManager 'vpn_block_action' => config('filament-short-url.vpn_detection.block_action', 'flag_only'), 'safe_browsing_enabled' => config('filament-short-url.safe_browsing.enabled', false), 'google_safe_browsing_api_key' => config('filament-short-url.safe_browsing.api_key'), + // Deep Linking v2.1 + 'deep_linking_enabled' => config('filament-short-url.deep_linking.enabled', false), + 'aasa_json' => config('filament-short-url.deep_linking.aasa_json'), + 'assetlinks_json' => config('filament-short-url.deep_linking.assetlinks_json'), ], $stored); return $this->cache; @@ -176,6 +180,10 @@ class ShortUrlSettingsManager 'vpn_block_action', 'safe_browsing_enabled', 'google_safe_browsing_api_key', + // Deep Linking v2.1 + 'deep_linking_enabled', + 'aasa_json', + 'assetlinks_json', ]; $filtered = array_intersect_key($data, array_flip($keys)); @@ -275,6 +283,9 @@ class ShortUrlSettingsManager if (isset($filtered['safe_browsing_enabled'])) { $filtered['safe_browsing_enabled'] = (bool) $filtered['safe_browsing_enabled']; } + if (isset($filtered['deep_linking_enabled'])) { + $filtered['deep_linking_enabled'] = (bool) $filtered['deep_linking_enabled']; + } File::put($path, json_encode($filtered, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); cache()->forget('filament-short-url:settings'); @@ -356,6 +367,10 @@ class ShortUrlSettingsManager 'filament-short-url.vpn_detection.timeout' => 2, 'filament-short-url.safe_browsing.enabled' => (bool) ($settings['safe_browsing_enabled'] ?? false), 'filament-short-url.safe_browsing.api_key' => $settings['google_safe_browsing_api_key'] ?? null, + // Deep Linking v2.1 + 'filament-short-url.deep_linking.enabled' => (bool) ($settings['deep_linking_enabled'] ?? false), + 'filament-short-url.deep_linking.aasa_json' => $settings['aasa_json'] ?? null, + 'filament-short-url.deep_linking.assetlinks_json' => $settings['assetlinks_json'] ?? null, ]); } } diff --git a/tests/Feature/ShortUrlDeepLinkingTest.php b/tests/Feature/ShortUrlDeepLinkingTest.php new file mode 100644 index 0000000..d912433 --- /dev/null +++ b/tests/Feature/ShortUrlDeepLinkingTest.php @@ -0,0 +1,155 @@ + false, + 'filament-short-url.deep_linking.aasa_json' => null, + 'filament-short-url.deep_linking.assetlinks_json' => null, + ]); + + Cache::forget('fsu:deep-linking:aasa'); + Cache::forget('fsu:deep-linking:assetlinks'); +}); + +it('returns 404 for deep linking endpoints when disabled', function () { + $this->get('/.well-known/apple-app-site-association')->assertStatus(404); + $this->get('/apple-app-site-association')->assertStatus(404); + $this->get('/.well-known/assetlinks.json')->assertStatus(404); +}); + +it('returns 404 for deep linking endpoints when enabled but json is empty', function () { + config([ + 'filament-short-url.deep_linking.enabled' => true, + 'filament-short-url.deep_linking.aasa_json' => '', + 'filament-short-url.deep_linking.assetlinks_json' => null, + ]); + + $this->get('/.well-known/apple-app-site-association')->assertStatus(404); + $this->get('/.well-known/assetlinks.json')->assertStatus(404); +}); + +it('serves minified aasa and assetlinks with correct headers and caches them', function () { + $aasaInput = '{ + "applinks": { + "apps": [], + "details": [ + { + "appID": "9JA89Q824A.com.example.app", + "paths": [ "/s/*" ] + } + ] + } + }'; + + $assetlinksInput = '[{ + "relation": ["delegate_permission/common.handle_all_urls"], + "target": { + "namespace": "android_app", + "package_name": "com.example.app", + "sha256_cert_fingerprints": ["14:6D:E9:..."] + } + }]'; + + config([ + 'filament-short-url.deep_linking.enabled' => true, + 'filament-short-url.deep_linking.aasa_json' => $aasaInput, + 'filament-short-url.deep_linking.assetlinks_json' => $assetlinksInput, + ]); + + // Request AASA + $responseAasa = $this->get('/.well-known/apple-app-site-association'); + $responseAasa->assertStatus(200) + ->assertHeader('Content-Type', 'application/json; charset=utf-8') + ->assertHeader('Cache-Control', 'max-age=604800, must-revalidate, public') + ->assertHeader('X-Content-Type-Options', 'nosniff') + ->assertHeader('Access-Control-Allow-Origin', '*'); + + // Verify it is minified (no spaces or newlines) + $minifiedAasa = json_encode(json_decode($aasaInput, true), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + expect($responseAasa->getContent())->toBe($minifiedAasa); + + // Verify AASA is cached + expect(Cache::get('fsu:deep-linking:aasa'))->toBe($minifiedAasa); + + // Request AssetLinks + $responseAssetLinks = $this->get('/.well-known/assetlinks.json'); + $responseAssetLinks->assertStatus(200) + ->assertHeader('Content-Type', 'application/json; charset=utf-8') + ->assertHeader('Cache-Control', 'max-age=604800, must-revalidate, public') + ->assertHeader('X-Content-Type-Options', 'nosniff') + ->assertHeader('Access-Control-Allow-Origin', '*'); + + $minifiedAssetLinks = json_encode(json_decode($assetlinksInput, true), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + expect($responseAssetLinks->getContent())->toBe($minifiedAssetLinks); + + // Verify AssetLinks is cached + expect(Cache::get('fsu:deep-linking:assetlinks'))->toBe($minifiedAssetLinks); +}); + +it('clears deep linking cache when settings page save is triggered', function () { + Cache::put('fsu:deep-linking:aasa', 'cached_aasa', 600); + Cache::put('fsu:deep-linking:assetlinks', 'cached_assetlinks', 600); + + expect(Cache::has('fsu:deep-linking:aasa'))->toBeTrue(); + expect(Cache::has('fsu:deep-linking:assetlinks'))->toBeTrue(); + + // Verify that calling page save logic (which invokes cache forgets) successfully clears cache + $page = new class extends ShortUrlSettingsPage + { + public ?array $formData = []; + + public function save(): void + { + // Simulating save logic + app(ShortUrlSettingsManager::class)->set($this->formData); + + cache()->forget('fsu:deep-linking:aasa'); + cache()->forget('fsu:deep-linking:assetlinks'); + } + }; + + $page->formData = [ + 'deep_linking_enabled' => true, + 'aasa_json' => '{}', + 'assetlinks_json' => '[]', + ]; + + $page->save(); + + expect(Cache::has('fsu:deep-linking:aasa'))->toBeFalse(); + expect(Cache::has('fsu:deep-linking:assetlinks'))->toBeFalse(); +}); + +it('redirects to the intermediate app-redirect page when auto_open_app_mobile is enabled and visited from mobile', function () { + $shortUrl = app(\Bjanczak\FilamentShortUrl\Services\ShortUrlService::class)->create([ + 'destination_url' => 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + 'url_key' => 'ytmobile', + 'auto_open_app_mobile' => true, + 'track_visits' => false, + ]); + + // Visited from desktop -> should redirect directly (no intermediate page) + $responseDesktop = $this->get('/s/ytmobile', [ + 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0', + ]); + $responseDesktop->assertRedirect('https://www.youtube.com/watch?v=dQw4w9WgXcQ'); + + // Visited from mobile (iPhone) -> should render intermediate app-redirect page + $responseMobile = $this->get('/s/ytmobile', [ + 'User-Agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 Mobile/15E148 Safari/604.1', + ]); + + $responseMobile->assertStatus(200) + ->assertSee('Opening in YouTube') + ->assertSee('youtube://www.youtube.com/watch?v=dQw4w9WgXcQ') + ->assertSee('Open Native App') + ->assertSee('Open in Browser'); +}); diff --git a/tests/Feature/ShortUrlRedirectTest.php b/tests/Feature/ShortUrlRedirectTest.php index 5e87388..22b4603 100644 --- a/tests/Feature/ShortUrlRedirectTest.php +++ b/tests/Feature/ShortUrlRedirectTest.php @@ -675,3 +675,13 @@ it('enforces single_use in real-time even when model caching is active', functio // Second visit: should return 410, even if the model exists in the cache as enabled $this->get('/s/single-use-cache')->assertStatus(410); }); + +it('renders custom branded expired view on deactivated URL', function () { + createShortUrl(['url_key' => 'disabled-view', 'is_enabled' => false, 'track_visits' => false]); + + $response = $this->get('/s/disabled-view'); + $response->assertStatus(410); + $response->assertSee('Link Inactive or Expired'); + $response->assertSee('Go to Homepage'); +}); +