eny.space Landingpage
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

chore(release): merge develop into release/0.1.0

+13160 -1346
+23 -1
.env.local.example
··· 1 + NEXT_PUBLIC_APP_URL=http://localhost:3000 2 + 3 + # Prelaunch feature flag. 4 + # When `true`, hide elements intended to ship only after launch. 5 + NEXT_PUBLIC_PRELAUNCH=false 6 + 7 + 1 8 # Stripe keys 2 9 # https://dashboard.stripe.com/apikeys 3 10 NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_12345 4 11 STRIPE_SECRET_KEY=sk_12345 5 - STRIPE_PAYMENT_DESCRIPTION='Software development services' 12 + STRIPE_PAYMENT_DESCRIPTION='Something descriptive' 6 13 # https://stripe.com/docs/webhooks/signatures 7 14 STRIPE_WEBHOOK_SECRET=whsec_1234 15 + 16 + # Supabase keys 17 + NEXT_PUBLIC_SUPABASE_URL=https://randomhash.supabase.co 18 + NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_random-hash 19 + NEXT_PUBLIC_SUPABASE_ANON_KEY=anonkey 20 + SUPABASE_SERVICE_ROLE_KEY=somekey 21 + 22 + # https://dashboard.stripe.com/ 23 + NEXT_PUBLIC_STRIPE_PRICE_ID=price_randomhash 24 + 25 + # Optional: plan-specific Stripe Price IDs (recommended). Keys match package names. 26 + # If provided, the UI will show amounts from Stripe and checkout will use the correct Price per plan. 27 + NEXT_PUBLIC_STRIPE_PRICE_PERSONAL_ID=price_randomhash_personal 28 + NEXT_PUBLIC_STRIPE_PRICE_COMMUNITY_ID=price_randomhash_community 29 + NEXT_PUBLIC_STRIPE_PRICE_BUSINESS_ID=price_randomhash_business
+22
.tangled/workflows/mirror.yml
··· 1 + # .tangled/workflows/mirror.yml 2 + when: 3 + - event: ["push"] 4 + branch: ["main", "develop", "feature/*", "docs/*"] 5 + - event: ["pull_request"] 6 + 7 + engine: "nixery" 8 + 9 + clone: 10 + depth: 0 11 + 12 + dependencies: 13 + nixpkgs: 14 + - git 15 + 16 + steps: 17 + - name: "Mirror to a different CI Repository" 18 + command: | 19 + git fetch --unshallow || true 20 + git remote add github https://x-access-token:$ACCESS_TOKEN@$GIT_REPOSITORY 21 + REF_NAME=${TANGLED_REF_NAME:-$TANGLED_PR_TARGET_BRANCH} 22 + git push github HEAD:refs/heads/mirror/$REF_NAME --force
+78 -51
README.md
··· 2 2 3 3 your data, your space, use it enywhere. 4 4 5 - A full-stack TypeScript application using Next.js for processing hosting service purchases. 5 + A full-stack TypeScript application using Next.js with Supabase Auth and Stripe subscriptions for access-controlled hosting services. 6 6 7 7 ## Features 8 8 9 - - **Checkout** - Custom amount hosting service purchases with hosted checkout 10 - - **Payment Elements** - Custom payment form with Payment Element 11 - - **Webhook handling** - Server-side webhook processing for payment events 9 + - **Authentication** - Email-based authentication with Supabase Auth 10 + - **Subscriptions** - Stripe subscription checkout and management 11 + - **Dashboard** - User dashboard showing subscription status 12 + - **Protected API** - Server endpoints only accessible to subscribed users 13 + - **Webhook handling** - Server-side webhook processing for subscription events 12 14 13 15 ## Tech Stack 14 16 15 17 - **Frontend**: Next.js, React, TypeScript 16 18 - **Backend**: Next.js Server Actions and Route Handlers 19 + - **Auth**: Supabase Auth 20 + - **Database**: Supabase PostgreSQL 21 + - **Payments**: Stripe Subscriptions 17 22 18 23 ## Getting Started 19 24 20 25 ### Prerequisites 21 26 22 27 - Node.js 18+ installed 23 - - A payment processor account 28 + - A Supabase account and project 29 + - A Stripe account 24 30 25 31 ### Installation 26 32 ··· 34 40 pnpm install 35 41 ``` 36 42 37 - 2. Set up environment variables: 43 + 2. Set up Supabase: 44 + 45 + - Create a new Supabase project at [supabase.com](https://supabase.com) 46 + - Run the migration file to create the subscriptions table: 47 + - Go to your Supabase project dashboard 48 + - Navigate to SQL Editor 49 + - Copy and run the contents of `supabase/migrations/001_subscriptions.sql` 50 + 51 + 3. Set up environment variables: 38 52 39 53 Create a `.env.local` file in the root directory: 40 54 41 55 ```bash 56 + # Supabase 57 + NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url 58 + NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key 59 + SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key 60 + 61 + # Stripe 42 62 NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=your_publishable_key 43 63 STRIPE_SECRET_KEY=your_secret_key 44 64 STRIPE_WEBHOOK_SECRET=your_webhook_secret 65 + NEXT_PUBLIC_STRIPE_PRICE_ID=your_stripe_price_id 66 + 67 + # Optional (recommended): plan-specific Price IDs for checkout + pricing display. 68 + # If set, the UI will show the real Stripe amounts for each plan. 69 + NEXT_PUBLIC_STRIPE_PRICE_PERSONAL_ID=your_stripe_price_id_personal 70 + NEXT_PUBLIC_STRIPE_PRICE_COMMUNITY_ID=your_stripe_price_id_community 71 + NEXT_PUBLIC_STRIPE_PRICE_BUSINESS_ID=your_stripe_price_id_business 72 + 73 + # App URL (for redirects) 74 + NEXT_PUBLIC_APP_URL=http://localhost:3000 45 75 ``` 46 76 47 - Get your API keys from your payment processor dashboard. 77 + Get your Supabase keys from your project settings → API. 78 + Get your Stripe keys from your Stripe dashboard. 79 + Create 3 subscription prices in Stripe (Personal / Community / Business). Set the resulting Price IDs in `NEXT_PUBLIC_STRIPE_PRICE_PERSONAL_ID`, `NEXT_PUBLIC_STRIPE_PRICE_COMMUNITY_ID`, and `NEXT_PUBLIC_STRIPE_PRICE_BUSINESS_ID`. 48 80 49 81 3. Start the development server: 50 82 ··· 62 94 63 95 #### Local Development 64 96 65 - 1. Install the payment processor CLI and link your account. 97 + 1. Install the Stripe CLI and link your account: 98 + 99 + ```bash 100 + stripe login 101 + ``` 66 102 67 103 2. Start webhook forwarding to your local server: 68 104 69 105 ```bash 70 - # Example command - adjust based on your payment processor 71 - webhook listen --forward-to localhost:3000/api/webhooks 106 + stripe listen --forward-to localhost:3000/api/webhooks 72 107 ``` 73 108 74 - 3. Copy the webhook secret from the CLI output and add it to your `.env.local` file. 109 + 3. Copy the webhook signing secret from the CLI output and add it to your `.env.local` file as `STRIPE_WEBHOOK_SECRET`. 75 110 76 111 #### Production 77 112 78 113 1. Deploy your application and copy the webhook URL (e.g., `https://your-domain.com/api/webhooks`). 79 114 80 - 2. Create a webhook endpoint in your payment processor dashboard. 115 + 2. In your Stripe dashboard, go to Developers → Webhooks and add an endpoint: 116 + 117 + - URL: `https://your-domain.com/api/webhooks` 118 + - Events to listen to: 119 + - `checkout.session.completed` 120 + - `customer.subscription.created` 121 + - `customer.subscription.updated` 122 + - `customer.subscription.deleted` 123 + - `invoice.payment_succeeded` 124 + - `invoice.payment_failed` 81 125 82 - 3. Add the webhook signing secret to your production environment variables. 126 + 3. Copy the webhook signing secret and add it to your production environment variables as `STRIPE_WEBHOOK_SECRET`. 83 127 84 128 ## Testing 85 129 ··· 97 141 ## Project Structure 98 142 99 143 - `app/` - Next.js app directory with pages and components 100 - - `app/actions/` - Server actions for payment operations 101 - - `app/api/webhooks/` - Webhook handler route 102 - - `lib/` - Payment processor client configuration 103 - - `components/` - React components for payment forms 144 + - `dashboard/` - User dashboard with subscription status and protected actions 145 + - `login/` - Login page 146 + - `signup/` - Sign up page 147 + - `actions/` - Server actions for auth and subscriptions 148 + - `api/` - API routes (webhooks, protected server endpoints) 149 + - `lib/` - Client configurations (Stripe, Supabase) 150 + - `supabase/migrations/` - Database migrations 151 + - `components/` - React components 104 152 - `utils/` - Utility functions 105 153 106 - ## Multi-Remote Git Setup 107 - 108 - This repo syncs to two servers (tangled.sh primary, GitHub mirror) using a custom `all` remote. Running `git push all` updates both simultaneously. 109 - 110 - ### Current Config 111 - 112 - ```bash 113 - all git@tangled.sh:samsour.de/eny-space (fetch) 114 - all git@github.com:Krekeny/eny-space.git (push) 115 - origin git@tangled.sh:samsour.de/eny-space (fetch) 116 - origin git@tangled.sh:samsour.de/eny-space (push) 117 - ``` 118 - 119 - ### Setup (New Clones) 120 - 121 - ```bash 122 - # Clone primary 123 - git clone git@tangled.sh:samsour.de/eny-space 154 + ## How It Works 124 155 125 - # Add GitHub mirror push 126 - cd eny-space 127 - git remote rename origin tangled 128 - git remote add all git@tangled.sh:samsour.de/eny-space 129 - git remote set-url --add --push all git@github.com:Krekeny/eny-space.git 156 + 1. **Authentication**: Users sign up/login with email via Supabase Auth 157 + 2. **Subscription**: Users can subscribe via Stripe Checkout 158 + 3. **Webhook Sync**: Stripe webhooks update subscription status in Supabase database 159 + 4. **Access Control**: Dashboard shows subscription status and protected API buttons 160 + 5. **Protected Routes**: `/api/server/[endpoint]` routes check for active subscription before allowing access 130 161 131 - # Push everything 132 - git push all --all 133 - git push all --tags 134 - ``` 162 + ## Mirroring 135 163 136 - ### How to Contribute 164 + Tangled is the primary git host. All pushes to `main`, `develop`, and `feature/*` branches are automatically mirrored to GitHub under `mirror/<branch-name>` via the Tangled CI pipeline at `.tangled/workflows/mirror.yml`. No manual multi-remote setup is needed. 137 165 138 - 1. Clone: `git clone git@tangled.sh:samsour.de/eny-space` 139 - 2. Branch: `git checkout -b your-feature` 140 - 3. Work: edit → `git add . && git commit -m "Your message"` 141 - 4. Push: `git push all` (syncs both servers!) 142 - 5. Update: `git fetch --all && git checkout main && git pull tangled main` 166 + ## How to Contribute 143 167 144 - Pro tip: add an alias `pushall="git push all"` in your shell config (e.g. `~/.bashrc` or `~/.zshrc`) for speed. 168 + 1. Clone: `git clone git@tangled.org:samsour.de/eny-space` 169 + 2. Branch: `git checkout -b feature/your-feature` 170 + 3. Work: edit → `git add . && git commit -m "your message"` 171 + 4. Push: `git push origin feature/your-feature`
+72
app/actions/auth.ts
··· 1 + "use server"; 2 + 3 + import { revalidatePath } from "next/cache"; 4 + import { redirect } from "next/navigation"; 5 + import { createClient } from "@/lib/supabase/server"; 6 + 7 + export async function signUp( 8 + _prevState: { error?: string; success?: boolean } | null, 9 + formData: FormData 10 + ): Promise<{ error?: string; success?: boolean }> { 11 + const supabase = await createClient(); 12 + 13 + const email = formData.get("email") as string; 14 + const password = formData.get("password") as string; 15 + 16 + try { 17 + const { error } = await supabase.auth.signUp({ 18 + email, 19 + password, 20 + options: { 21 + emailRedirectTo: `${ 22 + process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000" 23 + }/auth/callback`, 24 + }, 25 + }); 26 + 27 + if (error) { 28 + return { error: error.message }; 29 + } 30 + } catch (err) { 31 + const cause = (err as any)?.cause; 32 + const isTimeout = 33 + cause?.code === "UND_ERR_CONNECT_TIMEOUT" || 34 + (err as Error)?.message === "fetch failed"; 35 + return { 36 + error: isTimeout 37 + ? "Could not reach the server. Please check your connection and try again." 38 + : "An unexpected error occurred. Please try again.", 39 + }; 40 + } 41 + 42 + return { success: true }; 43 + } 44 + 45 + export async function signIn(formData: FormData) { 46 + const supabase = await createClient(); 47 + 48 + const data = { 49 + email: formData.get("email") as string, 50 + password: formData.get("password") as string, 51 + }; 52 + 53 + const { error } = await supabase.auth.signInWithPassword({ 54 + email: data.email, 55 + password: data.password, 56 + }); 57 + 58 + if (error) { 59 + return { error: error.message }; 60 + } 61 + 62 + const next = (formData.get("next") as string) || "/dashboard"; 63 + revalidatePath("/", "layout"); 64 + redirect(next); 65 + } 66 + 67 + export async function signOut() { 68 + const supabase = await createClient(); 69 + await supabase.auth.signOut(); 70 + revalidatePath("/", "layout"); 71 + redirect("/"); 72 + }
+495
app/actions/components/component-example.tsx
··· 1 + "use client" 2 + 3 + import * as React from "react" 4 + 5 + import { 6 + Example, 7 + ExampleWrapper, 8 + } from "@/actions/components/example" 9 + import { 10 + AlertDialog, 11 + AlertDialogAction, 12 + AlertDialogCancel, 13 + AlertDialogContent, 14 + AlertDialogDescription, 15 + AlertDialogFooter, 16 + AlertDialogHeader, 17 + AlertDialogMedia, 18 + AlertDialogTitle, 19 + AlertDialogTrigger, 20 + } from "@/actions/components/ui/alert-dialog" 21 + import { Badge } from "@/actions/components/ui/badge" 22 + import { Button } from "@/actions/components/ui/button" 23 + import { 24 + Card, 25 + CardAction, 26 + CardContent, 27 + CardDescription, 28 + CardFooter, 29 + CardHeader, 30 + CardTitle, 31 + } from "@/actions/components/ui/card" 32 + import { 33 + Combobox, 34 + ComboboxContent, 35 + ComboboxEmpty, 36 + ComboboxInput, 37 + ComboboxItem, 38 + ComboboxList, 39 + } from "@/actions/components/ui/combobox" 40 + import { 41 + DropdownMenu, 42 + DropdownMenuCheckboxItem, 43 + DropdownMenuContent, 44 + DropdownMenuGroup, 45 + DropdownMenuItem, 46 + DropdownMenuLabel, 47 + DropdownMenuPortal, 48 + DropdownMenuRadioGroup, 49 + DropdownMenuRadioItem, 50 + DropdownMenuSeparator, 51 + DropdownMenuShortcut, 52 + DropdownMenuSub, 53 + DropdownMenuSubContent, 54 + DropdownMenuSubTrigger, 55 + DropdownMenuTrigger, 56 + } from "@/actions/components/ui/dropdown-menu" 57 + import { Field, FieldGroup, FieldLabel } from "@/actions/components/ui/field" 58 + import { Input } from "@/actions/components/ui/input" 59 + import { 60 + Select, 61 + SelectContent, 62 + SelectGroup, 63 + SelectItem, 64 + SelectTrigger, 65 + SelectValue, 66 + } from "@/actions/components/ui/select" 67 + import { Textarea } from "@/actions/components/ui/textarea" 68 + import { PlusIcon, BluetoothIcon, MoreVerticalIcon, FileIcon, FolderIcon, FolderOpenIcon, FileCodeIcon, MoreHorizontalIcon, FolderSearchIcon, SaveIcon, DownloadIcon, EyeIcon, LayoutIcon, PaletteIcon, SunIcon, MoonIcon, MonitorIcon, UserIcon, CreditCardIcon, SettingsIcon, KeyboardIcon, LanguagesIcon, BellIcon, MailIcon, ShieldIcon, HelpCircleIcon, FileTextIcon, LogOutIcon } from "lucide-react" 69 + 70 + export function ComponentExample() { 71 + return ( 72 + <ExampleWrapper> 73 + <CardExample /> 74 + <FormExample /> 75 + </ExampleWrapper> 76 + ) 77 + } 78 + 79 + function CardExample() { 80 + return ( 81 + <Example title="Card" className="items-center justify-center"> 82 + <Card className="relative w-full max-w-sm overflow-hidden pt-0"> 83 + <div className="absolute inset-0 z-30 aspect-video bg-primary opacity-50 mix-blend-color" /> 84 + <img 85 + src="https://images.unsplash.com/photo-1604076850742-4c7221f3101b?q=80&w=1887&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" 86 + alt="Photo by mymind on Unsplash" 87 + title="Photo by mymind on Unsplash" 88 + className="relative z-20 aspect-video w-full object-cover brightness-60 grayscale" 89 + /> 90 + <CardHeader> 91 + <CardTitle>Observability Plus is replacing Monitoring</CardTitle> 92 + <CardDescription> 93 + Switch to the improved way to explore your data, with natural 94 + language. Monitoring will no longer be available on the Pro plan in 95 + November, 2025 96 + </CardDescription> 97 + </CardHeader> 98 + <CardFooter> 99 + <AlertDialog> 100 + <AlertDialogTrigger asChild> 101 + <Button> 102 + <PlusIcon data-icon="inline-start" /> 103 + Show Dialog 104 + </Button> 105 + </AlertDialogTrigger> 106 + <AlertDialogContent size="sm"> 107 + <AlertDialogHeader> 108 + <AlertDialogMedia> 109 + <BluetoothIcon 110 + /> 111 + </AlertDialogMedia> 112 + <AlertDialogTitle>Allow accessory to connect?</AlertDialogTitle> 113 + <AlertDialogDescription> 114 + Do you want to allow the USB accessory to connect to this 115 + device? 116 + </AlertDialogDescription> 117 + </AlertDialogHeader> 118 + <AlertDialogFooter> 119 + <AlertDialogCancel>Don&apos;t allow</AlertDialogCancel> 120 + <AlertDialogAction>Allow</AlertDialogAction> 121 + </AlertDialogFooter> 122 + </AlertDialogContent> 123 + </AlertDialog> 124 + <Badge variant="secondary" className="ml-auto"> 125 + Warning 126 + </Badge> 127 + </CardFooter> 128 + </Card> 129 + </Example> 130 + ) 131 + } 132 + 133 + const frameworks = [ 134 + "Next.js", 135 + "SvelteKit", 136 + "Nuxt.js", 137 + "Remix", 138 + "Astro", 139 + ] as const 140 + 141 + function FormExample() { 142 + const [notifications, setNotifications] = React.useState({ 143 + email: true, 144 + sms: false, 145 + push: true, 146 + }) 147 + const [theme, setTheme] = React.useState("light") 148 + 149 + return ( 150 + <Example title="Form"> 151 + <Card className="w-full max-w-md"> 152 + <CardHeader> 153 + <CardTitle>User Information</CardTitle> 154 + <CardDescription>Please fill in your details below</CardDescription> 155 + <CardAction> 156 + <DropdownMenu> 157 + <DropdownMenuTrigger asChild> 158 + <Button variant="ghost" size="icon"> 159 + <MoreVerticalIcon 160 + /> 161 + <span className="sr-only">More options</span> 162 + </Button> 163 + </DropdownMenuTrigger> 164 + <DropdownMenuContent align="end" className="w-56"> 165 + <DropdownMenuGroup> 166 + <DropdownMenuLabel>File</DropdownMenuLabel> 167 + <DropdownMenuItem> 168 + <FileIcon 169 + /> 170 + New File 171 + <DropdownMenuShortcut>⌘N</DropdownMenuShortcut> 172 + </DropdownMenuItem> 173 + <DropdownMenuItem> 174 + <FolderIcon 175 + /> 176 + New Folder 177 + <DropdownMenuShortcut>⇧⌘N</DropdownMenuShortcut> 178 + </DropdownMenuItem> 179 + <DropdownMenuSub> 180 + <DropdownMenuSubTrigger> 181 + <FolderOpenIcon 182 + /> 183 + Open Recent 184 + </DropdownMenuSubTrigger> 185 + <DropdownMenuPortal> 186 + <DropdownMenuSubContent> 187 + <DropdownMenuGroup> 188 + <DropdownMenuLabel>Recent Projects</DropdownMenuLabel> 189 + <DropdownMenuItem> 190 + <FileCodeIcon 191 + /> 192 + Project Alpha 193 + </DropdownMenuItem> 194 + <DropdownMenuItem> 195 + <FileCodeIcon 196 + /> 197 + Project Beta 198 + </DropdownMenuItem> 199 + <DropdownMenuSub> 200 + <DropdownMenuSubTrigger> 201 + <MoreHorizontalIcon 202 + /> 203 + More Projects 204 + </DropdownMenuSubTrigger> 205 + <DropdownMenuPortal> 206 + <DropdownMenuSubContent> 207 + <DropdownMenuItem> 208 + <FileCodeIcon 209 + /> 210 + Project Gamma 211 + </DropdownMenuItem> 212 + <DropdownMenuItem> 213 + <FileCodeIcon 214 + /> 215 + Project Delta 216 + </DropdownMenuItem> 217 + </DropdownMenuSubContent> 218 + </DropdownMenuPortal> 219 + </DropdownMenuSub> 220 + </DropdownMenuGroup> 221 + <DropdownMenuSeparator /> 222 + <DropdownMenuGroup> 223 + <DropdownMenuItem> 224 + <FolderSearchIcon 225 + /> 226 + Browse... 227 + </DropdownMenuItem> 228 + </DropdownMenuGroup> 229 + </DropdownMenuSubContent> 230 + </DropdownMenuPortal> 231 + </DropdownMenuSub> 232 + <DropdownMenuSeparator /> 233 + <DropdownMenuItem> 234 + <SaveIcon 235 + /> 236 + Save 237 + <DropdownMenuShortcut>⌘S</DropdownMenuShortcut> 238 + </DropdownMenuItem> 239 + <DropdownMenuItem> 240 + <DownloadIcon 241 + /> 242 + Export 243 + <DropdownMenuShortcut>⇧⌘E</DropdownMenuShortcut> 244 + </DropdownMenuItem> 245 + </DropdownMenuGroup> 246 + <DropdownMenuSeparator /> 247 + <DropdownMenuGroup> 248 + <DropdownMenuLabel>View</DropdownMenuLabel> 249 + <DropdownMenuCheckboxItem 250 + checked={notifications.email} 251 + onCheckedChange={(checked) => 252 + setNotifications({ 253 + ...notifications, 254 + email: checked === true, 255 + }) 256 + } 257 + > 258 + <EyeIcon 259 + /> 260 + Show Sidebar 261 + </DropdownMenuCheckboxItem> 262 + <DropdownMenuCheckboxItem 263 + checked={notifications.sms} 264 + onCheckedChange={(checked) => 265 + setNotifications({ 266 + ...notifications, 267 + sms: checked === true, 268 + }) 269 + } 270 + > 271 + <LayoutIcon 272 + /> 273 + Show Status Bar 274 + </DropdownMenuCheckboxItem> 275 + <DropdownMenuSub> 276 + <DropdownMenuSubTrigger> 277 + <PaletteIcon 278 + /> 279 + Theme 280 + </DropdownMenuSubTrigger> 281 + <DropdownMenuPortal> 282 + <DropdownMenuSubContent> 283 + <DropdownMenuGroup> 284 + <DropdownMenuLabel>Appearance</DropdownMenuLabel> 285 + <DropdownMenuRadioGroup 286 + value={theme} 287 + onValueChange={setTheme} 288 + > 289 + <DropdownMenuRadioItem value="light"> 290 + <SunIcon 291 + /> 292 + Light 293 + </DropdownMenuRadioItem> 294 + <DropdownMenuRadioItem value="dark"> 295 + <MoonIcon 296 + /> 297 + Dark 298 + </DropdownMenuRadioItem> 299 + <DropdownMenuRadioItem value="system"> 300 + <MonitorIcon 301 + /> 302 + System 303 + </DropdownMenuRadioItem> 304 + </DropdownMenuRadioGroup> 305 + </DropdownMenuGroup> 306 + </DropdownMenuSubContent> 307 + </DropdownMenuPortal> 308 + </DropdownMenuSub> 309 + </DropdownMenuGroup> 310 + <DropdownMenuSeparator /> 311 + <DropdownMenuGroup> 312 + <DropdownMenuLabel>Account</DropdownMenuLabel> 313 + <DropdownMenuItem> 314 + <UserIcon 315 + /> 316 + Profile 317 + <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut> 318 + </DropdownMenuItem> 319 + <DropdownMenuItem> 320 + <CreditCardIcon 321 + /> 322 + Billing 323 + </DropdownMenuItem> 324 + <DropdownMenuSub> 325 + <DropdownMenuSubTrigger> 326 + <SettingsIcon 327 + /> 328 + Settings 329 + </DropdownMenuSubTrigger> 330 + <DropdownMenuPortal> 331 + <DropdownMenuSubContent> 332 + <DropdownMenuGroup> 333 + <DropdownMenuLabel>Preferences</DropdownMenuLabel> 334 + <DropdownMenuItem> 335 + <KeyboardIcon 336 + /> 337 + Keyboard Shortcuts 338 + </DropdownMenuItem> 339 + <DropdownMenuItem> 340 + <LanguagesIcon 341 + /> 342 + Language 343 + </DropdownMenuItem> 344 + <DropdownMenuSub> 345 + <DropdownMenuSubTrigger> 346 + <BellIcon 347 + /> 348 + Notifications 349 + </DropdownMenuSubTrigger> 350 + <DropdownMenuPortal> 351 + <DropdownMenuSubContent> 352 + <DropdownMenuGroup> 353 + <DropdownMenuLabel> 354 + Notification Types 355 + </DropdownMenuLabel> 356 + <DropdownMenuCheckboxItem 357 + checked={notifications.push} 358 + onCheckedChange={(checked) => 359 + setNotifications({ 360 + ...notifications, 361 + push: checked === true, 362 + }) 363 + } 364 + > 365 + <BellIcon 366 + /> 367 + Push Notifications 368 + </DropdownMenuCheckboxItem> 369 + <DropdownMenuCheckboxItem 370 + checked={notifications.email} 371 + onCheckedChange={(checked) => 372 + setNotifications({ 373 + ...notifications, 374 + email: checked === true, 375 + }) 376 + } 377 + > 378 + <MailIcon 379 + /> 380 + Email Notifications 381 + </DropdownMenuCheckboxItem> 382 + </DropdownMenuGroup> 383 + </DropdownMenuSubContent> 384 + </DropdownMenuPortal> 385 + </DropdownMenuSub> 386 + </DropdownMenuGroup> 387 + <DropdownMenuSeparator /> 388 + <DropdownMenuGroup> 389 + <DropdownMenuItem> 390 + <ShieldIcon 391 + /> 392 + Privacy & Security 393 + </DropdownMenuItem> 394 + </DropdownMenuGroup> 395 + </DropdownMenuSubContent> 396 + </DropdownMenuPortal> 397 + </DropdownMenuSub> 398 + </DropdownMenuGroup> 399 + <DropdownMenuSeparator /> 400 + <DropdownMenuGroup> 401 + <DropdownMenuItem> 402 + <HelpCircleIcon 403 + /> 404 + Help & Support 405 + </DropdownMenuItem> 406 + <DropdownMenuItem> 407 + <FileTextIcon 408 + /> 409 + Documentation 410 + </DropdownMenuItem> 411 + </DropdownMenuGroup> 412 + <DropdownMenuSeparator /> 413 + <DropdownMenuGroup> 414 + <DropdownMenuItem variant="destructive"> 415 + <LogOutIcon 416 + /> 417 + Sign Out 418 + <DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut> 419 + </DropdownMenuItem> 420 + </DropdownMenuGroup> 421 + </DropdownMenuContent> 422 + </DropdownMenu> 423 + </CardAction> 424 + </CardHeader> 425 + <CardContent> 426 + <form> 427 + <FieldGroup> 428 + <div className="grid grid-cols-2 gap-4"> 429 + <Field> 430 + <FieldLabel htmlFor="small-form-name">Name</FieldLabel> 431 + <Input 432 + id="small-form-name" 433 + placeholder="Enter your name" 434 + required 435 + /> 436 + </Field> 437 + <Field> 438 + <FieldLabel htmlFor="small-form-role">Role</FieldLabel> 439 + <Select defaultValue=""> 440 + <SelectTrigger id="small-form-role"> 441 + <SelectValue placeholder="Select a role" /> 442 + </SelectTrigger> 443 + <SelectContent> 444 + <SelectGroup> 445 + <SelectItem value="developer">Developer</SelectItem> 446 + <SelectItem value="designer">Designer</SelectItem> 447 + <SelectItem value="manager">Manager</SelectItem> 448 + <SelectItem value="other">Other</SelectItem> 449 + </SelectGroup> 450 + </SelectContent> 451 + </Select> 452 + </Field> 453 + </div> 454 + <Field> 455 + <FieldLabel htmlFor="small-form-framework"> 456 + Framework 457 + </FieldLabel> 458 + <Combobox items={frameworks}> 459 + <ComboboxInput 460 + id="small-form-framework" 461 + placeholder="Select a framework" 462 + required 463 + /> 464 + <ComboboxContent> 465 + <ComboboxEmpty>No frameworks found.</ComboboxEmpty> 466 + <ComboboxList> 467 + {(item) => ( 468 + <ComboboxItem key={item} value={item}> 469 + {item} 470 + </ComboboxItem> 471 + )} 472 + </ComboboxList> 473 + </ComboboxContent> 474 + </Combobox> 475 + </Field> 476 + <Field> 477 + <FieldLabel htmlFor="small-form-comments">Comments</FieldLabel> 478 + <Textarea 479 + id="small-form-comments" 480 + placeholder="Add any additional comments" 481 + /> 482 + </Field> 483 + <Field orientation="horizontal"> 484 + <Button type="submit">Submit</Button> 485 + <Button variant="outline" type="button"> 486 + Cancel 487 + </Button> 488 + </Field> 489 + </FieldGroup> 490 + </form> 491 + </CardContent> 492 + </Card> 493 + </Example> 494 + ) 495 + }
+55
app/actions/components/example.tsx
··· 1 + import { cn } from "@/actions/lib/utils" 2 + 3 + function ExampleWrapper({ className, ...props }: React.ComponentProps<"div">) { 4 + return ( 5 + <div className="w-full bg-background"> 6 + <div 7 + data-slot="example-wrapper" 8 + className={cn( 9 + "mx-auto grid min-h-screen w-full max-w-5xl min-w-0 content-center items-start gap-8 p-4 pt-2 sm:gap-12 sm:p-6 md:grid-cols-2 md:gap-8 lg:p-12 2xl:max-w-6xl", 10 + className 11 + )} 12 + {...props} 13 + /> 14 + </div> 15 + ) 16 + } 17 + 18 + function Example({ 19 + title, 20 + children, 21 + className, 22 + containerClassName, 23 + ...props 24 + }: React.ComponentProps<"div"> & { 25 + title?: string 26 + containerClassName?: string 27 + }) { 28 + return ( 29 + <div 30 + data-slot="example" 31 + className={cn( 32 + "mx-auto flex w-full max-w-lg min-w-0 flex-col gap-1 self-stretch lg:max-w-none", 33 + containerClassName 34 + )} 35 + {...props} 36 + > 37 + {title && ( 38 + <div className="px-1.5 py-2 text-xs font-medium text-muted-foreground"> 39 + {title} 40 + </div> 41 + )} 42 + <div 43 + data-slot="example-content" 44 + className={cn( 45 + "flex min-w-0 flex-1 flex-col items-start gap-6 border border-dashed bg-background p-4 text-foreground sm:p-6 *:[div:not([class*='w-'])]:w-full", 46 + className 47 + )} 48 + > 49 + {children} 50 + </div> 51 + </div> 52 + ) 53 + } 54 + 55 + export { ExampleWrapper, Example }
+199
app/actions/components/ui/alert-dialog.tsx
··· 1 + "use client" 2 + 3 + import * as React from "react" 4 + import { AlertDialog as AlertDialogPrimitive } from "radix-ui" 5 + 6 + import { cn } from "@/actions/lib/utils" 7 + import { Button } from "@/actions/components/ui/button" 8 + 9 + function AlertDialog({ 10 + ...props 11 + }: React.ComponentProps<typeof AlertDialogPrimitive.Root>) { 12 + return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} /> 13 + } 14 + 15 + function AlertDialogTrigger({ 16 + ...props 17 + }: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) { 18 + return ( 19 + <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} /> 20 + ) 21 + } 22 + 23 + function AlertDialogPortal({ 24 + ...props 25 + }: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) { 26 + return ( 27 + <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} /> 28 + ) 29 + } 30 + 31 + function AlertDialogOverlay({ 32 + className, 33 + ...props 34 + }: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) { 35 + return ( 36 + <AlertDialogPrimitive.Overlay 37 + data-slot="alert-dialog-overlay" 38 + className={cn( 39 + "fixed inset-0 z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0", 40 + className 41 + )} 42 + {...props} 43 + /> 44 + ) 45 + } 46 + 47 + function AlertDialogContent({ 48 + className, 49 + size = "default", 50 + ...props 51 + }: React.ComponentProps<typeof AlertDialogPrimitive.Content> & { 52 + size?: "default" | "sm" 53 + }) { 54 + return ( 55 + <AlertDialogPortal> 56 + <AlertDialogOverlay /> 57 + <AlertDialogPrimitive.Content 58 + data-slot="alert-dialog-content" 59 + data-size={size} 60 + className={cn( 61 + "group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-background p-4 ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", 62 + className 63 + )} 64 + {...props} 65 + /> 66 + </AlertDialogPortal> 67 + ) 68 + } 69 + 70 + function AlertDialogHeader({ 71 + className, 72 + ...props 73 + }: React.ComponentProps<"div">) { 74 + return ( 75 + <div 76 + data-slot="alert-dialog-header" 77 + className={cn( 78 + "grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]", 79 + className 80 + )} 81 + {...props} 82 + /> 83 + ) 84 + } 85 + 86 + function AlertDialogFooter({ 87 + className, 88 + ...props 89 + }: React.ComponentProps<"div">) { 90 + return ( 91 + <div 92 + data-slot="alert-dialog-footer" 93 + className={cn( 94 + "-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end", 95 + className 96 + )} 97 + {...props} 98 + /> 99 + ) 100 + } 101 + 102 + function AlertDialogMedia({ 103 + className, 104 + ...props 105 + }: React.ComponentProps<"div">) { 106 + return ( 107 + <div 108 + data-slot="alert-dialog-media" 109 + className={cn( 110 + "mb-2 inline-flex size-10 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6", 111 + className 112 + )} 113 + {...props} 114 + /> 115 + ) 116 + } 117 + 118 + function AlertDialogTitle({ 119 + className, 120 + ...props 121 + }: React.ComponentProps<typeof AlertDialogPrimitive.Title>) { 122 + return ( 123 + <AlertDialogPrimitive.Title 124 + data-slot="alert-dialog-title" 125 + className={cn( 126 + "text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2", 127 + className 128 + )} 129 + {...props} 130 + /> 131 + ) 132 + } 133 + 134 + function AlertDialogDescription({ 135 + className, 136 + ...props 137 + }: React.ComponentProps<typeof AlertDialogPrimitive.Description>) { 138 + return ( 139 + <AlertDialogPrimitive.Description 140 + data-slot="alert-dialog-description" 141 + className={cn( 142 + "text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground", 143 + className 144 + )} 145 + {...props} 146 + /> 147 + ) 148 + } 149 + 150 + function AlertDialogAction({ 151 + className, 152 + variant = "default", 153 + size = "default", 154 + ...props 155 + }: React.ComponentProps<typeof AlertDialogPrimitive.Action> & 156 + Pick<React.ComponentProps<typeof Button>, "variant" | "size">) { 157 + return ( 158 + <Button variant={variant} size={size} asChild> 159 + <AlertDialogPrimitive.Action 160 + data-slot="alert-dialog-action" 161 + className={cn(className)} 162 + {...props} 163 + /> 164 + </Button> 165 + ) 166 + } 167 + 168 + function AlertDialogCancel({ 169 + className, 170 + variant = "outline", 171 + size = "default", 172 + ...props 173 + }: React.ComponentProps<typeof AlertDialogPrimitive.Cancel> & 174 + Pick<React.ComponentProps<typeof Button>, "variant" | "size">) { 175 + return ( 176 + <Button variant={variant} size={size} asChild> 177 + <AlertDialogPrimitive.Cancel 178 + data-slot="alert-dialog-cancel" 179 + className={cn(className)} 180 + {...props} 181 + /> 182 + </Button> 183 + ) 184 + } 185 + 186 + export { 187 + AlertDialog, 188 + AlertDialogAction, 189 + AlertDialogCancel, 190 + AlertDialogContent, 191 + AlertDialogDescription, 192 + AlertDialogFooter, 193 + AlertDialogHeader, 194 + AlertDialogMedia, 195 + AlertDialogOverlay, 196 + AlertDialogPortal, 197 + AlertDialogTitle, 198 + AlertDialogTrigger, 199 + }
+53
app/actions/components/ui/badge.tsx
··· 1 + import * as React from "react" 2 + import { cva, type VariantProps } from "class-variance-authority" 3 + import { Slot } from "@radix-ui/react-slot" 4 + 5 + import { cn } from "@/actions/lib/utils" 6 + 7 + const badgeVariants = cva( 8 + "group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!", 9 + { 10 + variants: { 11 + variant: { 12 + default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80", 13 + secondary: 14 + "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80", 15 + destructive: 16 + "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20", 17 + outline: 18 + "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground", 19 + ghost: 20 + "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50", 21 + link: "text-primary underline-offset-4 hover:underline", 22 + }, 23 + }, 24 + defaultVariants: { 25 + variant: "default", 26 + }, 27 + } 28 + ) 29 + 30 + type BadgeProps = React.HTMLAttributes<HTMLSpanElement> & 31 + VariantProps<typeof badgeVariants> & { 32 + asChild?: boolean 33 + } 34 + 35 + const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>( 36 + ({ className, variant = "default", asChild = false, ...props }, ref) => { 37 + const Comp = asChild ? Slot : "span" 38 + 39 + return ( 40 + <Comp 41 + data-slot="badge" 42 + data-variant={variant} 43 + className={cn(badgeVariants({ variant }), className)} 44 + ref={ref} 45 + {...props} 46 + /> 47 + ) 48 + } 49 + ) 50 + 51 + Badge.displayName = "Badge" 52 + 53 + export { Badge, badgeVariants }
+68
app/actions/components/ui/button.tsx
··· 1 + import * as React from "react" 2 + import { cva, type VariantProps } from "class-variance-authority" 3 + import { Slot } from "@radix-ui/react-slot" 4 + 5 + import { cn } from "@/actions/lib/utils" 6 + 7 + const buttonVariants = cva( 8 + "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none cursor-pointer focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", 9 + { 10 + variants: { 11 + variant: { 12 + default: "bg-primary text-primary-foreground", 13 + outline: 14 + "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50", 15 + secondary: 16 + "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground", 17 + ghost: 18 + "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50", 19 + destructive: 20 + "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40", 21 + link: "text-primary underline-offset-4 hover:underline", 22 + }, 23 + size: { 24 + default: 25 + "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2", 26 + xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3", 27 + sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5", 28 + lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3", 29 + icon: "size-8", 30 + "icon-xs": 31 + "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3", 32 + "icon-sm": 33 + "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg", 34 + "icon-lg": "size-9", 35 + }, 36 + }, 37 + defaultVariants: { 38 + variant: "default", 39 + size: "default", 40 + }, 41 + } 42 + ) 43 + 44 + type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & 45 + VariantProps<typeof buttonVariants> & { 46 + asChild?: boolean 47 + } 48 + 49 + const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( 50 + ({ className, variant = "default", size = "default", asChild = false, ...props }, ref) => { 51 + const Comp = asChild ? Slot : "button" 52 + 53 + return ( 54 + <Comp 55 + data-slot="button" 56 + data-variant={variant} 57 + data-size={size} 58 + className={cn(buttonVariants({ variant, size, className }))} 59 + ref={ref} 60 + {...props} 61 + /> 62 + ) 63 + } 64 + ) 65 + 66 + Button.displayName = "Button" 67 + 68 + export { Button, buttonVariants }
+103
app/actions/components/ui/card.tsx
··· 1 + import * as React from "react"; 2 + 3 + import { cn } from "@/actions/lib/utils"; 4 + 5 + function Card({ 6 + className, 7 + size = "default", 8 + ...props 9 + }: React.ComponentProps<"div"> & { size?: "default" | "sm" }) { 10 + return ( 11 + <div 12 + data-slot="card" 13 + data-size={size} 14 + className={cn( 15 + "group/card flex flex-col gap-4 overflow-hidden rounded-xl border border-white/10 bg-white/5 py-4 text-sm text-white shadow-[0_0_40px_rgba(15,23,42,0.85)] backdrop-blur-xl has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl", 16 + className, 17 + )} 18 + {...props} 19 + /> 20 + ); 21 + } 22 + 23 + function CardHeader({ className, ...props }: React.ComponentProps<"div">) { 24 + return ( 25 + <div 26 + data-slot="card-header" 27 + className={cn( 28 + "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3", 29 + className, 30 + )} 31 + {...props} 32 + /> 33 + ); 34 + } 35 + 36 + function CardTitle({ className, ...props }: React.ComponentProps<"div">) { 37 + return ( 38 + <div 39 + data-slot="card-title" 40 + className={cn( 41 + "text-base leading-snug font-semibold text-white group-data-[size=sm]/card:text-sm", 42 + className, 43 + )} 44 + {...props} 45 + /> 46 + ); 47 + } 48 + 49 + function CardDescription({ className, ...props }: React.ComponentProps<"div">) { 50 + return ( 51 + <div 52 + data-slot="card-description" 53 + className={cn("text-sm text-white/70", className)} 54 + {...props} 55 + /> 56 + ); 57 + } 58 + 59 + function CardAction({ className, ...props }: React.ComponentProps<"div">) { 60 + return ( 61 + <div 62 + data-slot="card-action" 63 + className={cn( 64 + "col-start-2 row-span-2 row-start-1 self-start justify-self-end", 65 + className, 66 + )} 67 + {...props} 68 + /> 69 + ); 70 + } 71 + 72 + function CardContent({ className, ...props }: React.ComponentProps<"div">) { 73 + return ( 74 + <div 75 + data-slot="card-content" 76 + className={cn("px-4 group-data-[size=sm]/card:px-3", className)} 77 + {...props} 78 + /> 79 + ); 80 + } 81 + 82 + function CardFooter({ className, ...props }: React.ComponentProps<"div">) { 83 + return ( 84 + <div 85 + data-slot="card-footer" 86 + className={cn( 87 + "flex items-center rounded-b-xl border-t border-white/10 bg-white/5 p-4 text-white group-data-[size=sm]/card:p-3", 88 + className, 89 + )} 90 + {...props} 91 + /> 92 + ); 93 + } 94 + 95 + export { 96 + Card, 97 + CardHeader, 98 + CardFooter, 99 + CardTitle, 100 + CardAction, 101 + CardDescription, 102 + CardContent, 103 + };
+299
app/actions/components/ui/combobox.tsx
··· 1 + "use client" 2 + 3 + import * as React from "react" 4 + import { Combobox as ComboboxPrimitive } from "@base-ui/react" 5 + 6 + import { cn } from "@/actions/lib/utils" 7 + import { Button } from "@/actions/components/ui/button" 8 + import { 9 + InputGroup, 10 + InputGroupAddon, 11 + InputGroupButton, 12 + InputGroupInput, 13 + } from "@/actions/components/ui/input-group" 14 + import { ChevronDownIcon, XIcon, CheckIcon } from "lucide-react" 15 + 16 + const Combobox = ComboboxPrimitive.Root 17 + 18 + function ComboboxValue({ ...props }: ComboboxPrimitive.Value.Props) { 19 + return <ComboboxPrimitive.Value data-slot="combobox-value" {...props} /> 20 + } 21 + 22 + function ComboboxTrigger({ 23 + className, 24 + children, 25 + ...props 26 + }: ComboboxPrimitive.Trigger.Props) { 27 + return ( 28 + <ComboboxPrimitive.Trigger 29 + data-slot="combobox-trigger" 30 + className={cn("[&_svg:not([class*='size-'])]:size-4", className)} 31 + {...props} 32 + > 33 + {children} 34 + <ChevronDownIcon className="pointer-events-none size-4 text-muted-foreground" /> 35 + </ComboboxPrimitive.Trigger> 36 + ) 37 + } 38 + 39 + function ComboboxClear({ className, ...props }: ComboboxPrimitive.Clear.Props) { 40 + return ( 41 + <ComboboxPrimitive.Clear 42 + data-slot="combobox-clear" 43 + render={<InputGroupButton variant="ghost" size="icon-xs" />} 44 + className={cn(className)} 45 + {...props} 46 + > 47 + <XIcon className="pointer-events-none" /> 48 + </ComboboxPrimitive.Clear> 49 + ) 50 + } 51 + 52 + function ComboboxInput({ 53 + className, 54 + children, 55 + disabled = false, 56 + showTrigger = true, 57 + showClear = false, 58 + ...props 59 + }: ComboboxPrimitive.Input.Props & { 60 + showTrigger?: boolean 61 + showClear?: boolean 62 + }) { 63 + return ( 64 + <InputGroup className={cn("w-auto", className)}> 65 + <ComboboxPrimitive.Input 66 + render={<InputGroupInput disabled={disabled} />} 67 + {...props} 68 + /> 69 + <InputGroupAddon align="inline-end"> 70 + {showTrigger && ( 71 + <InputGroupButton 72 + size="icon-xs" 73 + variant="ghost" 74 + asChild 75 + data-slot="input-group-button" 76 + className="group-has-data-[slot=combobox-clear]/input-group:hidden data-pressed:bg-transparent" 77 + disabled={disabled} 78 + > 79 + <ComboboxTrigger /> 80 + </InputGroupButton> 81 + )} 82 + {showClear && <ComboboxClear disabled={disabled} />} 83 + </InputGroupAddon> 84 + {children} 85 + </InputGroup> 86 + ) 87 + } 88 + 89 + function ComboboxContent({ 90 + className, 91 + side = "bottom", 92 + sideOffset = 6, 93 + align = "start", 94 + alignOffset = 0, 95 + anchor, 96 + ...props 97 + }: ComboboxPrimitive.Popup.Props & 98 + Pick< 99 + ComboboxPrimitive.Positioner.Props, 100 + "side" | "align" | "sideOffset" | "alignOffset" | "anchor" 101 + >) { 102 + return ( 103 + <ComboboxPrimitive.Portal> 104 + <ComboboxPrimitive.Positioner 105 + side={side} 106 + sideOffset={sideOffset} 107 + align={align} 108 + alignOffset={alignOffset} 109 + anchor={anchor} 110 + className="isolate z-50" 111 + > 112 + <ComboboxPrimitive.Popup 113 + data-slot="combobox-content" 114 + data-chips={!!anchor} 115 + className={cn("group/combobox-content relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) overflow-hidden rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[chips=true]:min-w-(--anchor-width) data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 *:data-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-8 *:data-[slot=input-group]:border-input/30 *:data-[slot=input-group]:bg-input/30 *:data-[slot=input-group]:shadow-none data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className )} 116 + {...props} 117 + /> 118 + </ComboboxPrimitive.Positioner> 119 + </ComboboxPrimitive.Portal> 120 + ) 121 + } 122 + 123 + function ComboboxList({ className, ...props }: ComboboxPrimitive.List.Props) { 124 + return ( 125 + <ComboboxPrimitive.List 126 + data-slot="combobox-list" 127 + className={cn( 128 + "no-scrollbar max-h-[min(calc(--spacing(72)---spacing(9)),calc(var(--available-height)---spacing(9)))] scroll-py-1 overflow-y-auto overscroll-contain p-1 data-empty:p-0", 129 + className 130 + )} 131 + {...props} 132 + /> 133 + ) 134 + } 135 + 136 + function ComboboxItem({ 137 + className, 138 + children, 139 + ...props 140 + }: ComboboxPrimitive.Item.Props) { 141 + return ( 142 + <ComboboxPrimitive.Item 143 + data-slot="combobox-item" 144 + className={cn( 145 + "relative flex w-full cursor-default items-center gap-2 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none data-highlighted:bg-accent data-highlighted:text-accent-foreground not-data-[variant=destructive]:data-highlighted:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", 146 + className 147 + )} 148 + {...props} 149 + > 150 + {children} 151 + <ComboboxPrimitive.ItemIndicator 152 + render={ 153 + <span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center" /> 154 + } 155 + > 156 + <CheckIcon className="pointer-events-none" /> 157 + </ComboboxPrimitive.ItemIndicator> 158 + </ComboboxPrimitive.Item> 159 + ) 160 + } 161 + 162 + function ComboboxGroup({ className, ...props }: ComboboxPrimitive.Group.Props) { 163 + return ( 164 + <ComboboxPrimitive.Group 165 + data-slot="combobox-group" 166 + className={cn(className)} 167 + {...props} 168 + /> 169 + ) 170 + } 171 + 172 + function ComboboxLabel({ 173 + className, 174 + ...props 175 + }: ComboboxPrimitive.GroupLabel.Props) { 176 + return ( 177 + <ComboboxPrimitive.GroupLabel 178 + data-slot="combobox-label" 179 + className={cn("px-2 py-1.5 text-xs text-muted-foreground", className)} 180 + {...props} 181 + /> 182 + ) 183 + } 184 + 185 + function ComboboxCollection({ ...props }: ComboboxPrimitive.Collection.Props) { 186 + return ( 187 + <ComboboxPrimitive.Collection data-slot="combobox-collection" {...props} /> 188 + ) 189 + } 190 + 191 + function ComboboxEmpty({ className, ...props }: ComboboxPrimitive.Empty.Props) { 192 + return ( 193 + <ComboboxPrimitive.Empty 194 + data-slot="combobox-empty" 195 + className={cn( 196 + "hidden w-full justify-center py-2 text-center text-sm text-muted-foreground group-data-empty/combobox-content:flex", 197 + className 198 + )} 199 + {...props} 200 + /> 201 + ) 202 + } 203 + 204 + function ComboboxSeparator({ 205 + className, 206 + ...props 207 + }: ComboboxPrimitive.Separator.Props) { 208 + return ( 209 + <ComboboxPrimitive.Separator 210 + data-slot="combobox-separator" 211 + className={cn("-mx-1 my-1 h-px bg-border", className)} 212 + {...props} 213 + /> 214 + ) 215 + } 216 + 217 + function ComboboxChips({ 218 + className, 219 + ...props 220 + }: React.ComponentPropsWithRef<typeof ComboboxPrimitive.Chips> & 221 + ComboboxPrimitive.Chips.Props) { 222 + return ( 223 + <ComboboxPrimitive.Chips 224 + data-slot="combobox-chips" 225 + className={cn( 226 + "flex min-h-8 flex-wrap items-center gap-1 rounded-lg border border-input bg-transparent bg-clip-padding px-2.5 py-1 text-sm transition-colors focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50 has-aria-invalid:border-destructive has-aria-invalid:ring-3 has-aria-invalid:ring-destructive/20 has-data-[slot=combobox-chip]:px-1 dark:bg-input/30 dark:has-aria-invalid:border-destructive/50 dark:has-aria-invalid:ring-destructive/40", 227 + className 228 + )} 229 + {...props} 230 + /> 231 + ) 232 + } 233 + 234 + function ComboboxChip({ 235 + className, 236 + children, 237 + showRemove = true, 238 + ...props 239 + }: ComboboxPrimitive.Chip.Props & { 240 + showRemove?: boolean 241 + }) { 242 + return ( 243 + <ComboboxPrimitive.Chip 244 + data-slot="combobox-chip" 245 + className={cn( 246 + "flex h-[calc(--spacing(5.25))] w-fit items-center justify-center gap-1 rounded-sm bg-muted px-1.5 text-xs font-medium whitespace-nowrap text-foreground has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50 has-data-[slot=combobox-chip-remove]:pr-0", 247 + className 248 + )} 249 + {...props} 250 + > 251 + {children} 252 + {showRemove && ( 253 + <ComboboxPrimitive.ChipRemove 254 + render={<Button variant="ghost" size="icon-xs" />} 255 + className="-ml-1 opacity-50 hover:opacity-100" 256 + data-slot="combobox-chip-remove" 257 + > 258 + <XIcon className="pointer-events-none" /> 259 + </ComboboxPrimitive.ChipRemove> 260 + )} 261 + </ComboboxPrimitive.Chip> 262 + ) 263 + } 264 + 265 + function ComboboxChipsInput({ 266 + className, 267 + ...props 268 + }: ComboboxPrimitive.Input.Props) { 269 + return ( 270 + <ComboboxPrimitive.Input 271 + data-slot="combobox-chip-input" 272 + className={cn("min-w-16 flex-1 outline-none", className)} 273 + {...props} 274 + /> 275 + ) 276 + } 277 + 278 + function useComboboxAnchor() { 279 + return React.useRef<HTMLDivElement | null>(null) 280 + } 281 + 282 + export { 283 + Combobox, 284 + ComboboxInput, 285 + ComboboxContent, 286 + ComboboxList, 287 + ComboboxItem, 288 + ComboboxGroup, 289 + ComboboxLabel, 290 + ComboboxCollection, 291 + ComboboxEmpty, 292 + ComboboxSeparator, 293 + ComboboxChips, 294 + ComboboxChip, 295 + ComboboxChipsInput, 296 + ComboboxTrigger, 297 + ComboboxValue, 298 + useComboboxAnchor, 299 + }
+269
app/actions/components/ui/dropdown-menu.tsx
··· 1 + "use client" 2 + 3 + import * as React from "react" 4 + import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui" 5 + 6 + import { cn } from "@/actions/lib/utils" 7 + import { CheckIcon, ChevronRightIcon } from "lucide-react" 8 + 9 + function DropdownMenu({ 10 + ...props 11 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) { 12 + return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} /> 13 + } 14 + 15 + function DropdownMenuPortal({ 16 + ...props 17 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) { 18 + return ( 19 + <DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} /> 20 + ) 21 + } 22 + 23 + function DropdownMenuTrigger({ 24 + ...props 25 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) { 26 + return ( 27 + <DropdownMenuPrimitive.Trigger 28 + data-slot="dropdown-menu-trigger" 29 + {...props} 30 + /> 31 + ) 32 + } 33 + 34 + function DropdownMenuContent({ 35 + className, 36 + align = "start", 37 + sideOffset = 4, 38 + ...props 39 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) { 40 + return ( 41 + <DropdownMenuPrimitive.Portal> 42 + <DropdownMenuPrimitive.Content 43 + data-slot="dropdown-menu-content" 44 + sideOffset={sideOffset} 45 + align={align} 46 + className={cn("z-50 max-h-(--radix-dropdown-menu-content-available-height) w-(--radix-dropdown-menu-trigger-width) min-w-32 origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:overflow-hidden data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className )} 47 + {...props} 48 + /> 49 + </DropdownMenuPrimitive.Portal> 50 + ) 51 + } 52 + 53 + function DropdownMenuGroup({ 54 + ...props 55 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) { 56 + return ( 57 + <DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} /> 58 + ) 59 + } 60 + 61 + function DropdownMenuItem({ 62 + className, 63 + inset, 64 + variant = "default", 65 + ...props 66 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & { 67 + inset?: boolean 68 + variant?: "default" | "destructive" 69 + }) { 70 + return ( 71 + <DropdownMenuPrimitive.Item 72 + data-slot="dropdown-menu-item" 73 + data-inset={inset} 74 + data-variant={variant} 75 + className={cn( 76 + "group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive", 77 + className 78 + )} 79 + {...props} 80 + /> 81 + ) 82 + } 83 + 84 + function DropdownMenuCheckboxItem({ 85 + className, 86 + children, 87 + checked, 88 + inset, 89 + ...props 90 + }: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem> & { 91 + inset?: boolean 92 + }) { 93 + return ( 94 + <DropdownMenuPrimitive.CheckboxItem 95 + data-slot="dropdown-menu-checkbox-item" 96 + data-inset={inset} 97 + className={cn( 98 + "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", 99 + className 100 + )} 101 + checked={checked} 102 + {...props} 103 + > 104 + <span 105 + className="pointer-events-none absolute right-2 flex items-center justify-center" 106 + data-slot="dropdown-menu-checkbox-item-indicator" 107 + > 108 + <DropdownMenuPrimitive.ItemIndicator> 109 + <CheckIcon 110 + /> 111 + </DropdownMenuPrimitive.ItemIndicator> 112 + </span> 113 + {children} 114 + </DropdownMenuPrimitive.CheckboxItem> 115 + ) 116 + } 117 + 118 + function DropdownMenuRadioGroup({ 119 + ...props 120 + }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) { 121 + return ( 122 + <DropdownMenuPrimitive.RadioGroup 123 + data-slot="dropdown-menu-radio-group" 124 + {...props} 125 + /> 126 + ) 127 + } 128 + 129 + function DropdownMenuRadioItem({ 130 + className, 131 + children, 132 + inset, 133 + ...props 134 + }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem> & { 135 + inset?: boolean 136 + }) { 137 + return ( 138 + <DropdownMenuPrimitive.RadioItem 139 + data-slot="dropdown-menu-radio-item" 140 + data-inset={inset} 141 + className={cn( 142 + "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", 143 + className 144 + )} 145 + {...props} 146 + > 147 + <span 148 + className="pointer-events-none absolute right-2 flex items-center justify-center" 149 + data-slot="dropdown-menu-radio-item-indicator" 150 + > 151 + <DropdownMenuPrimitive.ItemIndicator> 152 + <CheckIcon 153 + /> 154 + </DropdownMenuPrimitive.ItemIndicator> 155 + </span> 156 + {children} 157 + </DropdownMenuPrimitive.RadioItem> 158 + ) 159 + } 160 + 161 + function DropdownMenuLabel({ 162 + className, 163 + inset, 164 + ...props 165 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & { 166 + inset?: boolean 167 + }) { 168 + return ( 169 + <DropdownMenuPrimitive.Label 170 + data-slot="dropdown-menu-label" 171 + data-inset={inset} 172 + className={cn( 173 + "px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7", 174 + className 175 + )} 176 + {...props} 177 + /> 178 + ) 179 + } 180 + 181 + function DropdownMenuSeparator({ 182 + className, 183 + ...props 184 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) { 185 + return ( 186 + <DropdownMenuPrimitive.Separator 187 + data-slot="dropdown-menu-separator" 188 + className={cn("-mx-1 my-1 h-px bg-border", className)} 189 + {...props} 190 + /> 191 + ) 192 + } 193 + 194 + function DropdownMenuShortcut({ 195 + className, 196 + ...props 197 + }: React.ComponentProps<"span">) { 198 + return ( 199 + <span 200 + data-slot="dropdown-menu-shortcut" 201 + className={cn( 202 + "ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground", 203 + className 204 + )} 205 + {...props} 206 + /> 207 + ) 208 + } 209 + 210 + function DropdownMenuSub({ 211 + ...props 212 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) { 213 + return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} /> 214 + } 215 + 216 + function DropdownMenuSubTrigger({ 217 + className, 218 + inset, 219 + children, 220 + ...props 221 + }: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & { 222 + inset?: boolean 223 + }) { 224 + return ( 225 + <DropdownMenuPrimitive.SubTrigger 226 + data-slot="dropdown-menu-sub-trigger" 227 + data-inset={inset} 228 + className={cn( 229 + "flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", 230 + className 231 + )} 232 + {...props} 233 + > 234 + {children} 235 + <ChevronRightIcon className="ml-auto" /> 236 + </DropdownMenuPrimitive.SubTrigger> 237 + ) 238 + } 239 + 240 + function DropdownMenuSubContent({ 241 + className, 242 + ...props 243 + }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) { 244 + return ( 245 + <DropdownMenuPrimitive.SubContent 246 + data-slot="dropdown-menu-sub-content" 247 + className={cn("z-50 min-w-[96px] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-lg bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className )} 248 + {...props} 249 + /> 250 + ) 251 + } 252 + 253 + export { 254 + DropdownMenu, 255 + DropdownMenuPortal, 256 + DropdownMenuTrigger, 257 + DropdownMenuContent, 258 + DropdownMenuGroup, 259 + DropdownMenuLabel, 260 + DropdownMenuItem, 261 + DropdownMenuCheckboxItem, 262 + DropdownMenuRadioGroup, 263 + DropdownMenuRadioItem, 264 + DropdownMenuSeparator, 265 + DropdownMenuShortcut, 266 + DropdownMenuSub, 267 + DropdownMenuSubTrigger, 268 + DropdownMenuSubContent, 269 + }
+238
app/actions/components/ui/field.tsx
··· 1 + "use client" 2 + 3 + import { useMemo } from "react" 4 + import { cva, type VariantProps } from "class-variance-authority" 5 + 6 + import { cn } from "@/actions/lib/utils" 7 + import { Label } from "@/actions/components/ui/label" 8 + import { Separator } from "@/actions/components/ui/separator" 9 + 10 + function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) { 11 + return ( 12 + <fieldset 13 + data-slot="field-set" 14 + className={cn( 15 + "flex flex-col gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3", 16 + className 17 + )} 18 + {...props} 19 + /> 20 + ) 21 + } 22 + 23 + function FieldLegend({ 24 + className, 25 + variant = "legend", 26 + ...props 27 + }: React.ComponentProps<"legend"> & { variant?: "legend" | "label" }) { 28 + return ( 29 + <legend 30 + data-slot="field-legend" 31 + data-variant={variant} 32 + className={cn( 33 + "mb-1.5 font-medium data-[variant=label]:text-sm data-[variant=legend]:text-base", 34 + className 35 + )} 36 + {...props} 37 + /> 38 + ) 39 + } 40 + 41 + function FieldGroup({ className, ...props }: React.ComponentProps<"div">) { 42 + return ( 43 + <div 44 + data-slot="field-group" 45 + className={cn( 46 + "group/field-group @container/field-group flex w-full flex-col gap-5 data-[slot=checkbox-group]:gap-3 *:data-[slot=field-group]:gap-4", 47 + className 48 + )} 49 + {...props} 50 + /> 51 + ) 52 + } 53 + 54 + const fieldVariants = cva( 55 + "group/field flex w-full gap-2 data-[invalid=true]:text-destructive", 56 + { 57 + variants: { 58 + orientation: { 59 + vertical: "flex-col *:w-full [&>.sr-only]:w-auto", 60 + horizontal: 61 + "flex-row items-center has-[>[data-slot=field-content]]:items-start *:data-[slot=field-label]:flex-auto has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px", 62 + responsive: 63 + "flex-col *:w-full @md/field-group:flex-row @md/field-group:items-center @md/field-group:*:w-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:*:data-[slot=field-label]:flex-auto [&>.sr-only]:w-auto @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px", 64 + }, 65 + }, 66 + defaultVariants: { 67 + orientation: "vertical", 68 + }, 69 + } 70 + ) 71 + 72 + function Field({ 73 + className, 74 + orientation = "vertical", 75 + ...props 76 + }: React.ComponentProps<"div"> & VariantProps<typeof fieldVariants>) { 77 + return ( 78 + <div 79 + role="group" 80 + data-slot="field" 81 + data-orientation={orientation} 82 + className={cn(fieldVariants({ orientation }), className)} 83 + {...props} 84 + /> 85 + ) 86 + } 87 + 88 + function FieldContent({ className, ...props }: React.ComponentProps<"div">) { 89 + return ( 90 + <div 91 + data-slot="field-content" 92 + className={cn( 93 + "group/field-content flex flex-1 flex-col gap-0.5 leading-snug", 94 + className 95 + )} 96 + {...props} 97 + /> 98 + ) 99 + } 100 + 101 + function FieldLabel({ 102 + className, 103 + ...props 104 + }: React.ComponentProps<typeof Label>) { 105 + return ( 106 + <Label 107 + data-slot="field-label" 108 + className={cn( 109 + "group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50 has-data-checked:border-primary/30 has-data-checked:bg-primary/5 has-[>[data-slot=field]]:rounded-lg has-[>[data-slot=field]]:border *:data-[slot=field]:p-2.5 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10", 110 + "has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col", 111 + className 112 + )} 113 + {...props} 114 + /> 115 + ) 116 + } 117 + 118 + function FieldTitle({ className, ...props }: React.ComponentProps<"div">) { 119 + return ( 120 + <div 121 + data-slot="field-label" 122 + className={cn( 123 + "flex w-fit items-center gap-2 text-sm leading-snug font-medium group-data-[disabled=true]/field:opacity-50", 124 + className 125 + )} 126 + {...props} 127 + /> 128 + ) 129 + } 130 + 131 + function FieldDescription({ className, ...props }: React.ComponentProps<"p">) { 132 + return ( 133 + <p 134 + data-slot="field-description" 135 + className={cn( 136 + "text-left text-sm leading-normal font-normal text-muted-foreground group-has-data-horizontal/field:text-balance [[data-variant=legend]+&]:-mt-1.5", 137 + "last:mt-0 nth-last-2:-mt-1", 138 + "[&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary", 139 + className 140 + )} 141 + {...props} 142 + /> 143 + ) 144 + } 145 + 146 + function FieldSeparator({ 147 + children, 148 + className, 149 + ...props 150 + }: React.ComponentProps<"div"> & { 151 + children?: React.ReactNode 152 + }) { 153 + return ( 154 + <div 155 + data-slot="field-separator" 156 + data-content={!!children} 157 + className={cn( 158 + "relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2", 159 + className 160 + )} 161 + {...props} 162 + > 163 + <Separator className="absolute inset-0 top-1/2" /> 164 + {children && ( 165 + <span 166 + className="relative mx-auto block w-fit bg-background px-2 text-muted-foreground" 167 + data-slot="field-separator-content" 168 + > 169 + {children} 170 + </span> 171 + )} 172 + </div> 173 + ) 174 + } 175 + 176 + function FieldError({ 177 + className, 178 + children, 179 + errors, 180 + ...props 181 + }: React.ComponentProps<"div"> & { 182 + errors?: Array<{ message?: string } | undefined> 183 + }) { 184 + const content = useMemo(() => { 185 + if (children) { 186 + return children 187 + } 188 + 189 + if (!errors?.length) { 190 + return null 191 + } 192 + 193 + const uniqueErrors = [ 194 + ...new Map(errors.map((error) => [error?.message, error])).values(), 195 + ] 196 + 197 + if (uniqueErrors?.length == 1) { 198 + return uniqueErrors[0]?.message 199 + } 200 + 201 + return ( 202 + <ul className="ml-4 flex list-disc flex-col gap-1"> 203 + {uniqueErrors.map( 204 + (error, index) => 205 + error?.message && <li key={index}>{error.message}</li> 206 + )} 207 + </ul> 208 + ) 209 + }, [children, errors]) 210 + 211 + if (!content) { 212 + return null 213 + } 214 + 215 + return ( 216 + <div 217 + role="alert" 218 + data-slot="field-error" 219 + className={cn("text-sm font-normal text-destructive", className)} 220 + {...props} 221 + > 222 + {content} 223 + </div> 224 + ) 225 + } 226 + 227 + export { 228 + Field, 229 + FieldLabel, 230 + FieldDescription, 231 + FieldError, 232 + FieldGroup, 233 + FieldLegend, 234 + FieldSeparator, 235 + FieldSet, 236 + FieldContent, 237 + FieldTitle, 238 + }
+156
app/actions/components/ui/input-group.tsx
··· 1 + "use client" 2 + 3 + import * as React from "react" 4 + import { cva, type VariantProps } from "class-variance-authority" 5 + 6 + import { cn } from "@/actions/lib/utils" 7 + import { Button } from "@/actions/components/ui/button" 8 + import { Input } from "@/actions/components/ui/input" 9 + import { Textarea } from "@/actions/components/ui/textarea" 10 + 11 + function InputGroup({ className, ...props }: React.ComponentProps<"div">) { 12 + return ( 13 + <div 14 + data-slot="input-group" 15 + role="group" 16 + className={cn( 17 + "group/input-group relative flex h-8 w-full min-w-0 items-center rounded-lg border border-input transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:bg-input/50 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-disabled:bg-input/80 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5", 18 + className 19 + )} 20 + {...props} 21 + /> 22 + ) 23 + } 24 + 25 + const inputGroupAddonVariants = cva( 26 + "flex h-auto cursor-pointer items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4", 27 + { 28 + variants: { 29 + align: { 30 + "inline-start": 31 + "order-first pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem]", 32 + "inline-end": 33 + "order-last pr-2 has-[>button]:mr-[-0.3rem] has-[>kbd]:mr-[-0.15rem]", 34 + "block-start": 35 + "order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2", 36 + "block-end": 37 + "order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2", 38 + }, 39 + }, 40 + defaultVariants: { 41 + align: "inline-start", 42 + }, 43 + } 44 + ) 45 + 46 + function InputGroupAddon({ 47 + className, 48 + align = "inline-start", 49 + ...props 50 + }: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) { 51 + return ( 52 + <div 53 + role="group" 54 + data-slot="input-group-addon" 55 + data-align={align} 56 + className={cn(inputGroupAddonVariants({ align }), className)} 57 + onClick={(e) => { 58 + if ((e.target as HTMLElement).closest("button")) { 59 + return 60 + } 61 + e.currentTarget.parentElement?.querySelector("input")?.focus() 62 + }} 63 + {...props} 64 + /> 65 + ) 66 + } 67 + 68 + const inputGroupButtonVariants = cva( 69 + "flex items-center gap-2 text-sm shadow-none", 70 + { 71 + variants: { 72 + size: { 73 + xs: "h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5", 74 + sm: "", 75 + "icon-xs": 76 + "size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0", 77 + "icon-sm": "size-8 p-0 has-[>svg]:p-0", 78 + }, 79 + }, 80 + defaultVariants: { 81 + size: "xs", 82 + }, 83 + } 84 + ) 85 + 86 + function InputGroupButton({ 87 + className, 88 + type = "button", 89 + variant = "ghost", 90 + size = "xs", 91 + ...props 92 + }: Omit<React.ComponentProps<typeof Button>, "size"> & 93 + VariantProps<typeof inputGroupButtonVariants>) { 94 + return ( 95 + <Button 96 + type={type} 97 + data-size={size} 98 + variant={variant} 99 + className={cn(inputGroupButtonVariants({ size }), className)} 100 + {...props} 101 + /> 102 + ) 103 + } 104 + 105 + function InputGroupText({ className, ...props }: React.ComponentProps<"span">) { 106 + return ( 107 + <span 108 + className={cn( 109 + "flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4", 110 + className 111 + )} 112 + {...props} 113 + /> 114 + ) 115 + } 116 + 117 + function InputGroupInput({ 118 + className, 119 + ...props 120 + }: React.ComponentProps<"input">) { 121 + return ( 122 + <Input 123 + data-slot="input-group-control" 124 + className={cn( 125 + "flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent", 126 + className 127 + )} 128 + {...props} 129 + /> 130 + ) 131 + } 132 + 133 + function InputGroupTextarea({ 134 + className, 135 + ...props 136 + }: React.ComponentProps<"textarea">) { 137 + return ( 138 + <Textarea 139 + data-slot="input-group-control" 140 + className={cn( 141 + "flex-1 resize-none rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent", 142 + className 143 + )} 144 + {...props} 145 + /> 146 + ) 147 + } 148 + 149 + export { 150 + InputGroup, 151 + InputGroupAddon, 152 + InputGroupButton, 153 + InputGroupText, 154 + InputGroupInput, 155 + InputGroupTextarea, 156 + }
+19
app/actions/components/ui/input.tsx
··· 1 + import * as React from "react" 2 + 3 + import { cn } from "@/actions/lib/utils" 4 + 5 + function Input({ className, type, ...props }: React.ComponentProps<"input">) { 6 + return ( 7 + <input 8 + type={type} 9 + data-slot="input" 10 + className={cn( 11 + "h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40", 12 + className 13 + )} 14 + {...props} 15 + /> 16 + ) 17 + } 18 + 19 + export { Input }
+24
app/actions/components/ui/label.tsx
··· 1 + "use client" 2 + 3 + import * as React from "react" 4 + import { Label as LabelPrimitive } from "radix-ui" 5 + 6 + import { cn } from "@/actions/lib/utils" 7 + 8 + function Label({ 9 + className, 10 + ...props 11 + }: React.ComponentProps<typeof LabelPrimitive.Root>) { 12 + return ( 13 + <LabelPrimitive.Root 14 + data-slot="label" 15 + className={cn( 16 + "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", 17 + className 18 + )} 19 + {...props} 20 + /> 21 + ) 22 + } 23 + 24 + export { Label }
+164
app/actions/components/ui/navigation-menu.tsx
··· 1 + import * as React from "react" 2 + import { cva } from "class-variance-authority" 3 + import { NavigationMenu as NavigationMenuPrimitive } from "radix-ui" 4 + 5 + import { cn } from "@/actions/lib/utils" 6 + import { ChevronDownIcon } from "lucide-react" 7 + 8 + function NavigationMenu({ 9 + className, 10 + children, 11 + viewport = true, 12 + ...props 13 + }: React.ComponentProps<typeof NavigationMenuPrimitive.Root> & { 14 + viewport?: boolean 15 + }) { 16 + return ( 17 + <NavigationMenuPrimitive.Root 18 + data-slot="navigation-menu" 19 + data-viewport={viewport} 20 + className={cn( 21 + "group/navigation-menu relative flex max-w-max flex-1 items-center justify-center", 22 + className 23 + )} 24 + {...props} 25 + > 26 + {children} 27 + {viewport && <NavigationMenuViewport />} 28 + </NavigationMenuPrimitive.Root> 29 + ) 30 + } 31 + 32 + function NavigationMenuList({ 33 + className, 34 + ...props 35 + }: React.ComponentProps<typeof NavigationMenuPrimitive.List>) { 36 + return ( 37 + <NavigationMenuPrimitive.List 38 + data-slot="navigation-menu-list" 39 + className={cn( 40 + "group flex flex-1 list-none items-center justify-center gap-0", 41 + className 42 + )} 43 + {...props} 44 + /> 45 + ) 46 + } 47 + 48 + function NavigationMenuItem({ 49 + className, 50 + ...props 51 + }: React.ComponentProps<typeof NavigationMenuPrimitive.Item>) { 52 + return ( 53 + <NavigationMenuPrimitive.Item 54 + data-slot="navigation-menu-item" 55 + className={cn("relative", className)} 56 + {...props} 57 + /> 58 + ) 59 + } 60 + 61 + const navigationMenuTriggerStyle = cva( 62 + "group/navigation-menu-trigger inline-flex h-9 w-max items-center justify-center rounded-lg bg-background px-2.5 py-1.5 text-sm font-medium transition-all outline-none hover:bg-muted focus:bg-muted focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-popup-open:bg-muted/50 data-popup-open:hover:bg-muted data-open:bg-muted/50 data-open:hover:bg-muted data-open:focus:bg-muted" 63 + ) 64 + 65 + function NavigationMenuTrigger({ 66 + className, 67 + children, 68 + ...props 69 + }: React.ComponentProps<typeof NavigationMenuPrimitive.Trigger>) { 70 + return ( 71 + <NavigationMenuPrimitive.Trigger 72 + data-slot="navigation-menu-trigger" 73 + className={cn(navigationMenuTriggerStyle(), "group", className)} 74 + {...props} 75 + > 76 + {children}{" "} 77 + <ChevronDownIcon className="relative top-px ml-1 size-3 transition duration-300 group-data-popup-open/navigation-menu-trigger:rotate-180 group-data-open/navigation-menu-trigger:rotate-180" aria-hidden="true" /> 78 + </NavigationMenuPrimitive.Trigger> 79 + ) 80 + } 81 + 82 + function NavigationMenuContent({ 83 + className, 84 + ...props 85 + }: React.ComponentProps<typeof NavigationMenuPrimitive.Content>) { 86 + return ( 87 + <NavigationMenuPrimitive.Content 88 + data-slot="navigation-menu-content" 89 + className={cn( 90 + "top-0 left-0 w-full p-1 ease-[cubic-bezier(0.22,1,0.36,1)] group-data-[viewport=false]/navigation-menu:top-full group-data-[viewport=false]/navigation-menu:mt-1.5 group-data-[viewport=false]/navigation-menu:overflow-hidden group-data-[viewport=false]/navigation-menu:rounded-lg group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:shadow group-data-[viewport=false]/navigation-menu:ring-1 group-data-[viewport=false]/navigation-menu:ring-foreground/10 group-data-[viewport=false]/navigation-menu:duration-300 data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 data-[motion^=from-]:animate-in data-[motion^=from-]:fade-in data-[motion^=to-]:animate-out data-[motion^=to-]:fade-out **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none md:absolute md:w-auto group-data-[viewport=false]/navigation-menu:data-open:animate-in group-data-[viewport=false]/navigation-menu:data-open:fade-in-0 group-data-[viewport=false]/navigation-menu:data-open:zoom-in-95 group-data-[viewport=false]/navigation-menu:data-closed:animate-out group-data-[viewport=false]/navigation-menu:data-closed:fade-out-0 group-data-[viewport=false]/navigation-menu:data-closed:zoom-out-95", 91 + className 92 + )} 93 + {...props} 94 + /> 95 + ) 96 + } 97 + 98 + function NavigationMenuViewport({ 99 + className, 100 + ...props 101 + }: React.ComponentProps<typeof NavigationMenuPrimitive.Viewport>) { 102 + return ( 103 + <div 104 + className={cn( 105 + "absolute top-full left-0 isolate z-50 flex justify-center" 106 + )} 107 + > 108 + <NavigationMenuPrimitive.Viewport 109 + data-slot="navigation-menu-viewport" 110 + className={cn( 111 + "origin-top-center relative mt-1.5 h-(--radix-navigation-menu-viewport-height) w-full overflow-hidden rounded-lg bg-popover text-popover-foreground shadow ring-1 ring-foreground/10 duration-100 md:w-(--radix-navigation-menu-viewport-width) data-open:animate-in data-open:zoom-in-90 data-closed:animate-out data-closed:zoom-out-95", 112 + className 113 + )} 114 + {...props} 115 + /> 116 + </div> 117 + ) 118 + } 119 + 120 + function NavigationMenuLink({ 121 + className, 122 + ...props 123 + }: React.ComponentProps<typeof NavigationMenuPrimitive.Link>) { 124 + return ( 125 + <NavigationMenuPrimitive.Link 126 + data-slot="navigation-menu-link" 127 + className={cn( 128 + "flex items-center gap-2 rounded-lg p-2 text-sm transition-all outline-none hover:bg-muted focus:bg-muted focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-1 in-data-[slot=navigation-menu-content]:rounded-md data-active:bg-muted/50 data-active:hover:bg-muted data-active:focus:bg-muted [&_svg:not([class*='size-'])]:size-4", 129 + className 130 + )} 131 + {...props} 132 + /> 133 + ) 134 + } 135 + 136 + function NavigationMenuIndicator({ 137 + className, 138 + ...props 139 + }: React.ComponentProps<typeof NavigationMenuPrimitive.Indicator>) { 140 + return ( 141 + <NavigationMenuPrimitive.Indicator 142 + data-slot="navigation-menu-indicator" 143 + className={cn( 144 + "top-full z-1 flex h-1.5 items-end justify-center overflow-hidden data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:animate-in data-[state=visible]:fade-in", 145 + className 146 + )} 147 + {...props} 148 + > 149 + <div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" /> 150 + </NavigationMenuPrimitive.Indicator> 151 + ) 152 + } 153 + 154 + export { 155 + NavigationMenu, 156 + NavigationMenuList, 157 + NavigationMenuItem, 158 + NavigationMenuContent, 159 + NavigationMenuTrigger, 160 + NavigationMenuLink, 161 + NavigationMenuIndicator, 162 + NavigationMenuViewport, 163 + navigationMenuTriggerStyle, 164 + }
+192
app/actions/components/ui/select.tsx
··· 1 + "use client" 2 + 3 + import * as React from "react" 4 + import { Select as SelectPrimitive } from "radix-ui" 5 + 6 + import { cn } from "@/actions/lib/utils" 7 + import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react" 8 + 9 + function Select({ 10 + ...props 11 + }: React.ComponentProps<typeof SelectPrimitive.Root>) { 12 + return <SelectPrimitive.Root data-slot="select" {...props} /> 13 + } 14 + 15 + function SelectGroup({ 16 + className, 17 + ...props 18 + }: React.ComponentProps<typeof SelectPrimitive.Group>) { 19 + return ( 20 + <SelectPrimitive.Group 21 + data-slot="select-group" 22 + className={cn("scroll-my-1 p-1", className)} 23 + {...props} 24 + /> 25 + ) 26 + } 27 + 28 + function SelectValue({ 29 + ...props 30 + }: React.ComponentProps<typeof SelectPrimitive.Value>) { 31 + return <SelectPrimitive.Value data-slot="select-value" {...props} /> 32 + } 33 + 34 + function SelectTrigger({ 35 + className, 36 + size = "default", 37 + children, 38 + ...props 39 + }: React.ComponentProps<typeof SelectPrimitive.Trigger> & { 40 + size?: "sm" | "default" 41 + }) { 42 + return ( 43 + <SelectPrimitive.Trigger 44 + data-slot="select-trigger" 45 + data-size={size} 46 + className={cn( 47 + "flex w-fit items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", 48 + className 49 + )} 50 + {...props} 51 + > 52 + {children} 53 + <SelectPrimitive.Icon asChild> 54 + <ChevronDownIcon className="pointer-events-none size-4 text-muted-foreground" /> 55 + </SelectPrimitive.Icon> 56 + </SelectPrimitive.Trigger> 57 + ) 58 + } 59 + 60 + function SelectContent({ 61 + className, 62 + children, 63 + position = "item-aligned", 64 + align = "center", 65 + ...props 66 + }: React.ComponentProps<typeof SelectPrimitive.Content>) { 67 + return ( 68 + <SelectPrimitive.Portal> 69 + <SelectPrimitive.Content 70 + data-slot="select-content" 71 + data-align-trigger={position === "item-aligned"} 72 + className={cn("relative z-50 max-h-(--radix-select-content-available-height) min-w-36 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", position ==="popper"&&"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className )} 73 + position={position} 74 + align={align} 75 + {...props} 76 + > 77 + <SelectScrollUpButton /> 78 + <SelectPrimitive.Viewport 79 + data-position={position} 80 + className={cn( 81 + "data-[position=popper]:h-(--radix-select-trigger-height) data-[position=popper]:w-full data-[position=popper]:min-w-(--radix-select-trigger-width)", 82 + position === "popper" && "" 83 + )} 84 + > 85 + {children} 86 + </SelectPrimitive.Viewport> 87 + <SelectScrollDownButton /> 88 + </SelectPrimitive.Content> 89 + </SelectPrimitive.Portal> 90 + ) 91 + } 92 + 93 + function SelectLabel({ 94 + className, 95 + ...props 96 + }: React.ComponentProps<typeof SelectPrimitive.Label>) { 97 + return ( 98 + <SelectPrimitive.Label 99 + data-slot="select-label" 100 + className={cn("px-1.5 py-1 text-xs text-muted-foreground", className)} 101 + {...props} 102 + /> 103 + ) 104 + } 105 + 106 + function SelectItem({ 107 + className, 108 + children, 109 + ...props 110 + }: React.ComponentProps<typeof SelectPrimitive.Item>) { 111 + return ( 112 + <SelectPrimitive.Item 113 + data-slot="select-item" 114 + className={cn( 115 + "relative flex w-full cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2", 116 + className 117 + )} 118 + {...props} 119 + > 120 + <span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center"> 121 + <SelectPrimitive.ItemIndicator> 122 + <CheckIcon className="pointer-events-none" /> 123 + </SelectPrimitive.ItemIndicator> 124 + </span> 125 + <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText> 126 + </SelectPrimitive.Item> 127 + ) 128 + } 129 + 130 + function SelectSeparator({ 131 + className, 132 + ...props 133 + }: React.ComponentProps<typeof SelectPrimitive.Separator>) { 134 + return ( 135 + <SelectPrimitive.Separator 136 + data-slot="select-separator" 137 + className={cn("pointer-events-none -mx-1 my-1 h-px bg-border", className)} 138 + {...props} 139 + /> 140 + ) 141 + } 142 + 143 + function SelectScrollUpButton({ 144 + className, 145 + ...props 146 + }: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) { 147 + return ( 148 + <SelectPrimitive.ScrollUpButton 149 + data-slot="select-scroll-up-button" 150 + className={cn( 151 + "z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4", 152 + className 153 + )} 154 + {...props} 155 + > 156 + <ChevronUpIcon 157 + /> 158 + </SelectPrimitive.ScrollUpButton> 159 + ) 160 + } 161 + 162 + function SelectScrollDownButton({ 163 + className, 164 + ...props 165 + }: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) { 166 + return ( 167 + <SelectPrimitive.ScrollDownButton 168 + data-slot="select-scroll-down-button" 169 + className={cn( 170 + "z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4", 171 + className 172 + )} 173 + {...props} 174 + > 175 + <ChevronDownIcon 176 + /> 177 + </SelectPrimitive.ScrollDownButton> 178 + ) 179 + } 180 + 181 + export { 182 + Select, 183 + SelectContent, 184 + SelectGroup, 185 + SelectItem, 186 + SelectLabel, 187 + SelectScrollDownButton, 188 + SelectScrollUpButton, 189 + SelectSeparator, 190 + SelectTrigger, 191 + SelectValue, 192 + }
+28
app/actions/components/ui/separator.tsx
··· 1 + "use client" 2 + 3 + import * as React from "react" 4 + import { Separator as SeparatorPrimitive } from "radix-ui" 5 + 6 + import { cn } from "@/actions/lib/utils" 7 + 8 + function Separator({ 9 + className, 10 + orientation = "horizontal", 11 + decorative = true, 12 + ...props 13 + }: React.ComponentProps<typeof SeparatorPrimitive.Root>) { 14 + return ( 15 + <SeparatorPrimitive.Root 16 + data-slot="separator" 17 + decorative={decorative} 18 + orientation={orientation} 19 + className={cn( 20 + "shrink-0 bg-border data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch", 21 + className 22 + )} 23 + {...props} 24 + /> 25 + ) 26 + } 27 + 28 + export { Separator }
+18
app/actions/components/ui/textarea.tsx
··· 1 + import * as React from "react" 2 + 3 + import { cn } from "@/actions/lib/utils" 4 + 5 + function Textarea({ className, ...props }: React.ComponentProps<"textarea">) { 6 + return ( 7 + <textarea 8 + data-slot="textarea" 9 + className={cn( 10 + "flex field-sizing-content min-h-16 w-full rounded-lg border border-input bg-transparent px-2.5 py-2 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40", 11 + className 12 + )} 13 + {...props} 14 + /> 15 + ) 16 + } 17 + 18 + export { Textarea }
-80
app/actions/stripe.ts
··· 1 - "use server"; 2 - 3 - import type { Stripe } from "stripe"; 4 - 5 - import { headers } from "next/headers"; 6 - 7 - import { CURRENCY } from "@/config"; 8 - import { formatAmountForStripe } from "@/utils/stripe-helpers"; 9 - import { stripe } from "@/lib/stripe"; 10 - 11 - export async function createCheckoutSession( 12 - data: FormData 13 - ): Promise<{ client_secret: string | null; url: string | null }> { 14 - const ui_mode = data.get( 15 - "uiMode" 16 - ) as Stripe.Checkout.SessionCreateParams.UiMode; 17 - 18 - const headersList = await headers(); 19 - const originHeader = headersList.get("origin"); 20 - const hostHeader = headersList.get("host"); 21 - 22 - let origin: string; 23 - if (originHeader) { 24 - origin = originHeader; 25 - } else if (hostHeader) { 26 - origin = `https://${hostHeader}`; 27 - } else { 28 - origin = process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000"; 29 - } 30 - 31 - const checkoutSession: Stripe.Checkout.Session = 32 - await stripe.checkout.sessions.create({ 33 - mode: "payment", 34 - submit_type: "pay", 35 - line_items: [ 36 - { 37 - quantity: 1, 38 - price_data: { 39 - currency: CURRENCY, 40 - product_data: { 41 - name: "Hosting Service", 42 - }, 43 - unit_amount: formatAmountForStripe( 44 - Number(data.get("customDonation") as string), 45 - CURRENCY 46 - ), 47 - }, 48 - }, 49 - ], 50 - ...(ui_mode === "hosted" && { 51 - success_url: `${origin}/checkout/result?session_id={CHECKOUT_SESSION_ID}`, 52 - cancel_url: `${origin}/checkout`, 53 - }), 54 - ...(ui_mode === "embedded" && { 55 - return_url: `${origin}/checkout/result?session_id={CHECKOUT_SESSION_ID}`, 56 - }), 57 - ui_mode, 58 - }); 59 - 60 - return { 61 - client_secret: checkoutSession.client_secret, 62 - url: checkoutSession.url, 63 - }; 64 - } 65 - 66 - export async function createPaymentIntent( 67 - data: FormData 68 - ): Promise<{ client_secret: string }> { 69 - const paymentIntent: Stripe.PaymentIntent = 70 - await stripe.paymentIntents.create({ 71 - amount: formatAmountForStripe( 72 - Number(data.get("customDonation") as string), 73 - CURRENCY 74 - ), 75 - automatic_payment_methods: { enabled: true }, 76 - currency: CURRENCY, 77 - }); 78 - 79 - return { client_secret: paymentIntent.client_secret as string }; 80 - }
+367
app/actions/subscription.ts
··· 1 + "use server"; 2 + 3 + import { createClient } from "@/lib/supabase/server"; 4 + import { createAdminClient } from "@/lib/supabase/admin"; 5 + import { stripe } from "@/lib/stripe"; 6 + import { headers } from "next/headers"; 7 + import type { Stripe } from "stripe"; 8 + 9 + function normalizeSlug(value: string) { 10 + return value 11 + .toLowerCase() 12 + .replace(/[^a-z0-9-]/g, "-") 13 + .replace(/^-+/, "") 14 + .replace(/-+$/, "") 15 + .slice(0, 63); 16 + } 17 + 18 + type PdsCheckoutOptions = { 19 + username?: string; 20 + hostname?: string; 21 + disksizeGb?: number; 22 + }; 23 + 24 + /** 25 + * Get user's Stripe customer ID from database (minimal storage) 26 + */ 27 + async function getStripeCustomerId(): Promise<string | null> { 28 + const supabase = await createClient(); 29 + const { 30 + data: { user }, 31 + } = await supabase.auth.getUser(); 32 + 33 + if (!user) { 34 + return null; 35 + } 36 + 37 + const { data: subscription } = await supabase 38 + .from("subscriptions") 39 + .select("stripe_customer_id") 40 + .eq("user_id", user.id) 41 + .limit(1) 42 + .maybeSingle(); 43 + 44 + return subscription?.stripe_customer_id || null; 45 + } 46 + 47 + /** 48 + * Get active subscription directly from Stripe (source of truth) 49 + */ 50 + export async function getActiveSubscription(): Promise<Stripe.Subscription | null> { 51 + const customerId = await getStripeCustomerId(); 52 + if (!customerId) { 53 + return null; 54 + } 55 + 56 + try { 57 + // Get all subscriptions for this customer 58 + const subscriptions = await stripe.subscriptions.list({ 59 + customer: customerId, 60 + status: "all", 61 + limit: 10, 62 + }); 63 + 64 + // Find active or trialing subscription (still counts as subscribed even if cancel_at_period_end) 65 + const activeSubscription = subscriptions.data.find( 66 + (sub) => 67 + sub.status === "active" || sub.status === "trialing" 68 + ); 69 + 70 + return activeSubscription || null; 71 + } catch (error) { 72 + console.error("Error fetching subscription from Stripe:", error); 73 + return null; 74 + } 75 + } 76 + 77 + /** 78 + * Get latest subscription for UI (shows canceled history too) 79 + */ 80 + export async function getSubscriptionStatus() { 81 + const customerId = await getStripeCustomerId(); 82 + if (!customerId) { 83 + return { 84 + subscribed: false, 85 + subscription: null, 86 + }; 87 + } 88 + 89 + try { 90 + const subscriptions = await stripe.subscriptions.list({ 91 + customer: customerId, 92 + status: "all", 93 + limit: 10, 94 + }); 95 + 96 + if (!subscriptions.data.length) { 97 + return { 98 + subscribed: false, 99 + subscription: null, 100 + }; 101 + } 102 + 103 + // Pick the most recently created subscription 104 + const latest = subscriptions.data.reduce<Stripe.Subscription | null>( 105 + (acc, sub) => { 106 + if (!acc) return sub; 107 + return sub.created > acc.created ? sub : acc; 108 + }, 109 + null 110 + ); 111 + 112 + if (!latest) { 113 + return { 114 + subscribed: false, 115 + subscription: null, 116 + }; 117 + } 118 + 119 + const isCurrentlySubscribed = 120 + (latest.status === "active" || latest.status === "trialing") && 121 + latest.cancel_at_period_end === false; 122 + 123 + return { 124 + subscribed: isCurrentlySubscribed, 125 + subscription: { 126 + status: latest.status, 127 + cancel_at_period_end: latest.cancel_at_period_end, 128 + current_period_end: new Date( 129 + latest.current_period_end * 1000 130 + ).toISOString(), 131 + current_period_start: new Date( 132 + latest.current_period_start * 1000 133 + ).toISOString(), 134 + }, 135 + }; 136 + } catch (error) { 137 + console.error("Error fetching subscription status from Stripe:", error); 138 + return { 139 + subscribed: false, 140 + subscription: null, 141 + }; 142 + } 143 + } 144 + 145 + /** 146 + * Verify active subscription for protected routes (always checks Stripe) 147 + */ 148 + export async function verifyActiveSubscription(): Promise<{ 149 + active: boolean; 150 + subscription: Stripe.Subscription | null; 151 + }> { 152 + const subscription = await getActiveSubscription(); 153 + 154 + return { 155 + active: !!subscription, 156 + subscription, 157 + }; 158 + } 159 + 160 + /** 161 + * Create checkout session for new subscription 162 + */ 163 + export async function createSubscriptionCheckout( 164 + priceId: string, 165 + options?: PdsCheckoutOptions, 166 + ) { 167 + const supabase = await createClient(); 168 + const { 169 + data: { user }, 170 + } = await supabase.auth.getUser(); 171 + 172 + if (!user) { 173 + throw new Error("User must be authenticated"); 174 + } 175 + 176 + // Get or create Stripe customer 177 + let customerId = await getStripeCustomerId(); 178 + 179 + if (!customerId) { 180 + const customer = await stripe.customers.create({ 181 + email: user.email!, 182 + metadata: { 183 + supabase_user_id: user.id, 184 + }, 185 + }); 186 + customerId = customer.id; 187 + 188 + // Store only customer ID in database (minimal) 189 + const { data: existingSub } = await supabase 190 + .from("subscriptions") 191 + .select("id") 192 + .eq("user_id", user.id) 193 + .limit(1) 194 + .maybeSingle(); 195 + 196 + if (!existingSub) { 197 + const { error } = await supabase.from("subscriptions").insert({ 198 + user_id: user.id, 199 + stripe_customer_id: customerId, 200 + }); 201 + if (error) throw error; 202 + } 203 + } 204 + 205 + const headersList = await headers(); 206 + const originHeader = headersList.get("origin"); 207 + const hostHeader = headersList.get("host"); 208 + const origin = 209 + originHeader || 210 + `https://${hostHeader}` || 211 + process.env.NEXT_PUBLIC_APP_URL || 212 + "http://localhost:3000"; 213 + 214 + const checkoutSession = await stripe.checkout.sessions.create({ 215 + // Used later in the Stripe webhook to provision the user's PDS 216 + // with user-selected settings. 217 + metadata: (() => { 218 + const fallbackUsername = normalizeSlug(user.email!.split("@")[0] || "pds"); 219 + const pdsUsername = normalizeSlug(options?.username || fallbackUsername); 220 + const pdsDisksizeGb = Number(options?.disksizeGb); 221 + const normalizedDisksize = 222 + Number.isFinite(pdsDisksizeGb) && pdsDisksizeGb > 0 223 + ? String(Math.floor(pdsDisksizeGb)) 224 + : "10"; 225 + 226 + const requestedHostname = (options?.hostname || "").trim(); 227 + const cleanedHostname = requestedHostname 228 + .replace(/^https?:\/\//i, "") 229 + .replace(/\/.*$/, ""); 230 + const pdsHostnameBase = cleanedHostname || `${pdsUsername}.eny.k8s.frx.pub`; 231 + 232 + return { 233 + user_id: user.id, 234 + user_email: user.email!, 235 + pds_username: pdsUsername, 236 + pds_disksize_gb: normalizedDisksize, 237 + pds_hostname_base: pdsHostnameBase, 238 + }; 239 + })(), 240 + customer: customerId, 241 + mode: "subscription", 242 + payment_method_types: ["card"], 243 + line_items: [ 244 + { 245 + price: priceId, 246 + quantity: 1, 247 + }, 248 + ], 249 + success_url: `${origin}/dashboard?session_id={CHECKOUT_SESSION_ID}`, 250 + cancel_url: `${origin}/dashboard`, 251 + }); 252 + 253 + return { url: checkoutSession.url }; 254 + } 255 + 256 + /** 257 + * Cancel subscription (sets cancel_at_period_end) 258 + */ 259 + export async function cancelSubscription() { 260 + const subscription = await getActiveSubscription(); 261 + 262 + if (!subscription) { 263 + return { success: false, error: "No active subscription found" }; 264 + } 265 + 266 + try { 267 + await stripe.subscriptions.update(subscription.id, { 268 + cancel_at_period_end: true, 269 + }); 270 + 271 + return { success: true }; 272 + } catch (error) { 273 + console.error("Error canceling subscription:", error); 274 + return { 275 + success: false, 276 + error: 277 + error instanceof Error 278 + ? error.message 279 + : "Failed to cancel subscription", 280 + }; 281 + } 282 + } 283 + 284 + /** 285 + * Resume subscription (removes cancel_at_period_end) 286 + */ 287 + export async function resumeSubscription() { 288 + const customerId = await getStripeCustomerId(); 289 + if (!customerId) { 290 + return { success: false, error: "No subscription found" }; 291 + } 292 + 293 + try { 294 + // Find subscription that's scheduled for cancellation 295 + const subscriptions = await stripe.subscriptions.list({ 296 + customer: customerId, 297 + status: "all", 298 + limit: 10, 299 + }); 300 + 301 + const cancelingSubscription = subscriptions.data.find( 302 + (sub) => 303 + sub.cancel_at_period_end === true && 304 + (sub.status === "active" || sub.status === "trialing") 305 + ); 306 + 307 + if (!cancelingSubscription) { 308 + return { 309 + success: false, 310 + error: "No subscription scheduled for cancellation found", 311 + }; 312 + } 313 + 314 + await stripe.subscriptions.update(cancelingSubscription.id, { 315 + cancel_at_period_end: false, 316 + }); 317 + 318 + return { success: true }; 319 + } catch (error) { 320 + console.error("Error resuming subscription:", error); 321 + return { 322 + success: false, 323 + error: 324 + error instanceof Error 325 + ? error.message 326 + : "Failed to resume subscription", 327 + }; 328 + } 329 + } 330 + 331 + /** 332 + * Create billing portal session 333 + */ 334 + export async function createBillingPortalSession() { 335 + const customerId = await getStripeCustomerId(); 336 + 337 + if (!customerId) { 338 + return { success: false, error: "No subscription found" }; 339 + } 340 + 341 + const headersList = await headers(); 342 + const originHeader = headersList.get("origin"); 343 + const hostHeader = headersList.get("host"); 344 + const origin = 345 + originHeader || 346 + `https://${hostHeader}` || 347 + process.env.NEXT_PUBLIC_APP_URL || 348 + "http://localhost:3000"; 349 + 350 + try { 351 + const session = await stripe.billingPortal.sessions.create({ 352 + customer: customerId, 353 + return_url: `${origin}/dashboard`, 354 + }); 355 + 356 + return { success: true, url: session.url }; 357 + } catch (error) { 358 + console.error("Error creating billing portal session:", error); 359 + return { 360 + success: false, 361 + error: 362 + error instanceof Error 363 + ? error.message 364 + : "Failed to create billing portal session", 365 + }; 366 + } 367 + }
+106
app/api/pds/atproto/create-account/route.ts
··· 1 + import { NextResponse } from "next/server"; 2 + 3 + import { createClient } from "@/lib/supabase/server"; 4 + 5 + import { 6 + getPdsBaseUrlFromService, 7 + getPdsServiceForCurrentUser, 8 + } from "../helpers"; 9 + 10 + export async function POST(req: Request) { 11 + try { 12 + const body = (await req.json()) as { 13 + email?: string; 14 + handle: string; 15 + password: string; 16 + inviteCode: string; 17 + }; 18 + 19 + if (!body?.handle || !body?.password || !body?.inviteCode) { 20 + return NextResponse.json( 21 + { message: "Missing required fields: handle, password, inviteCode" }, 22 + { status: 400 }, 23 + ); 24 + } 25 + 26 + const { service, pdsServiceId } = await getPdsServiceForCurrentUser(); 27 + 28 + const requiredServiceIdRaw = process.env.NEXT_PUBLIC_PDS_TEST_SERVICE_ID; 29 + if (requiredServiceIdRaw) { 30 + const requiredServiceId = Number(requiredServiceIdRaw); 31 + if (pdsServiceId !== requiredServiceId) { 32 + return NextResponse.json( 33 + { 34 + message: `PDS service id mismatch: expected ${requiredServiceId}, got ${pdsServiceId}`, 35 + }, 36 + { status: 409 }, 37 + ); 38 + } 39 + } 40 + 41 + // Ensure we always have `https://...` for fetch 42 + const pdsBaseUrl = getPdsBaseUrlFromService(service); 43 + 44 + let emailToUse = body.email; 45 + if (!emailToUse) { 46 + // Reuse the user's own Supabase email for testing, but add a +alias suffix 47 + // to avoid collisions if the backend enforces uniqueness. 48 + const supabase = await createClient(); 49 + const { 50 + data: { user }, 51 + } = await supabase.auth.getUser(); 52 + 53 + if (!user?.email) { 54 + return NextResponse.json( 55 + { message: "Missing email (neither request body nor Supabase user email found)" }, 56 + { status: 400 }, 57 + ); 58 + } 59 + 60 + const baseEmail = user.email; 61 + const [local, domain] = baseEmail.split("@"); 62 + const alias = `${local}+atproto-test-${Date.now()}`; 63 + emailToUse = `${alias}@${domain}`; 64 + } 65 + 66 + const res = await fetch( 67 + `${pdsBaseUrl}/xrpc/com.atproto.server.createAccount`, 68 + { 69 + method: "POST", 70 + headers: { 71 + "Content-Type": "application/json", 72 + }, 73 + body: JSON.stringify({ 74 + email: emailToUse, 75 + handle: body.handle, 76 + password: body.password, 77 + inviteCode: body.inviteCode, 78 + }), 79 + }, 80 + ); 81 + 82 + const contentType = res.headers.get("content-type") || ""; 83 + const payload = contentType.includes("application/json") 84 + ? await res.json() 85 + : await res.text().catch(() => ""); 86 + 87 + if (!res.ok) { 88 + return NextResponse.json( 89 + { message: "Failed to create account", status: res.status, payload }, 90 + { status: 502 }, 91 + ); 92 + } 93 + 94 + // Return the email that we used, so the UI mirrors the real admin workflow. 95 + if (payload && typeof payload === "object") { 96 + return NextResponse.json({ ...(payload as any), emailUsed: emailToUse }); 97 + } 98 + 99 + return NextResponse.json({ payload, emailUsed: emailToUse }); 100 + } catch (error) { 101 + const message = error instanceof Error ? error.message : "Unknown error"; 102 + const status = (error as any)?.status ?? 500; 103 + return NextResponse.json({ message }, { status }); 104 + } 105 + } 106 +
+72
app/api/pds/atproto/create-session/route.ts
··· 1 + import { NextResponse } from "next/server"; 2 + 3 + import { 4 + getPdsBaseUrlFromService, 5 + getPdsServiceForCurrentUser, 6 + } from "../helpers"; 7 + 8 + export async function POST(req: Request) { 9 + try { 10 + const body = (await req.json()) as { 11 + identifier: string; 12 + password: string; 13 + }; 14 + 15 + if (!body?.identifier || !body?.password) { 16 + return NextResponse.json( 17 + { message: "Missing required fields: identifier, password" }, 18 + { status: 400 }, 19 + ); 20 + } 21 + 22 + const { service, pdsServiceId } = await getPdsServiceForCurrentUser(); 23 + 24 + const requiredServiceIdRaw = process.env.NEXT_PUBLIC_PDS_TEST_SERVICE_ID; 25 + if (requiredServiceIdRaw) { 26 + const requiredServiceId = Number(requiredServiceIdRaw); 27 + if (pdsServiceId !== requiredServiceId) { 28 + return NextResponse.json( 29 + { 30 + message: `PDS service id mismatch: expected ${requiredServiceId}, got ${pdsServiceId}`, 31 + }, 32 + { status: 409 }, 33 + ); 34 + } 35 + } 36 + 37 + const pdsBaseUrl = getPdsBaseUrlFromService(service); 38 + 39 + const res = await fetch( 40 + `${pdsBaseUrl}/xrpc/com.atproto.server.createSession`, 41 + { 42 + method: "POST", 43 + headers: { 44 + "Content-Type": "application/json", 45 + }, 46 + body: JSON.stringify({ 47 + identifier: body.identifier, 48 + password: body.password, 49 + }), 50 + }, 51 + ); 52 + 53 + const contentType = res.headers.get("content-type") || ""; 54 + const payload = contentType.includes("application/json") 55 + ? await res.json() 56 + : await res.text().catch(() => ""); 57 + 58 + if (!res.ok) { 59 + return NextResponse.json( 60 + { message: "Failed to create session", status: res.status, payload }, 61 + { status: 502 }, 62 + ); 63 + } 64 + 65 + return NextResponse.json(payload); 66 + } catch (error) { 67 + const message = error instanceof Error ? error.message : "Unknown error"; 68 + const status = (error as any)?.status ?? 500; 69 + return NextResponse.json({ message }, { status }); 70 + } 71 + } 72 +
+105
app/api/pds/atproto/helpers.ts
··· 1 + import { createClient } from "@/lib/supabase/server"; 2 + 3 + const PDS_API_BASE_URL = "https://k8s-pds.frx.pub/api/v1"; 4 + 5 + function parseMaybeDoubleEncodedJson(input: unknown) { 6 + if (typeof input === "string") { 7 + try { 8 + return JSON.parse(input); 9 + } catch { 10 + return input; 11 + } 12 + } 13 + return input; 14 + } 15 + 16 + export async function getPdsServiceForCurrentUser(): Promise<{ 17 + pdsServiceId: number; 18 + service: any; 19 + }> { 20 + const supabase = await createClient(); 21 + const { 22 + data: { user }, 23 + } = await supabase.auth.getUser(); 24 + 25 + if (!user) { 26 + return Promise.reject(Object.assign(new Error("Unauthorized"), { status: 401 })); 27 + } 28 + 29 + const { data: pdsServiceRow } = await supabase 30 + .from("pds_services") 31 + .select("pds_service_id") 32 + .eq("user_id", user.id) 33 + .maybeSingle(); 34 + 35 + const forcedServiceIdRaw = 36 + process.env.PDS_FORCE_SERVICE_ID === "true" 37 + ? process.env.PDS_TEST_SERVICE_ID 38 + : undefined; 39 + const forcedServiceId = forcedServiceIdRaw ? Number(forcedServiceIdRaw) : null; 40 + 41 + const pdsServiceId = (forcedServiceId !== null && Number.isFinite(forcedServiceId) 42 + ? forcedServiceId 43 + : pdsServiceRow?.pds_service_id) as number | null | undefined; 44 + 45 + if (!pdsServiceId) { 46 + return Promise.reject( 47 + Object.assign(new Error("No provisioned PDS found for this user"), { status: 404 }), 48 + ); 49 + } 50 + 51 + const apiToken = process.env.PDS_API_TOKEN; 52 + if (!apiToken) { 53 + return Promise.reject( 54 + Object.assign(new Error("Missing PDS_API_TOKEN env var"), { status: 500 }), 55 + ); 56 + } 57 + 58 + const res = await fetch(`${PDS_API_BASE_URL}/service/${pdsServiceId}`, { 59 + cache: "no-store", 60 + headers: { 61 + Accept: "application/json", 62 + "X-Requested-With": "XMLHttpRequest", 63 + Authorization: `Bearer ${apiToken}`, 64 + }, 65 + }); 66 + 67 + const contentType = res.headers.get("content-type") || ""; 68 + if (!res.ok) { 69 + let body: unknown = null; 70 + try { 71 + body = await res.json(); 72 + } catch { 73 + body = await res.text().catch(() => ""); 74 + } 75 + return Promise.reject( 76 + Object.assign( 77 + new Error(`Upstream PDS service fetch failed (${res.status})`), 78 + { status: 502, body: parseMaybeDoubleEncodedJson(body), contentType }, 79 + ), 80 + ); 81 + } 82 + 83 + if (!contentType.includes("application/json")) { 84 + return Promise.reject( 85 + Object.assign(new Error("Upstream did not return JSON"), { status: 502 }), 86 + ); 87 + } 88 + 89 + const dataRaw: unknown = await res.json(); 90 + const service = parseMaybeDoubleEncodedJson(dataRaw); 91 + 92 + return { pdsServiceId: Number(pdsServiceId), service }; 93 + } 94 + 95 + export function getPdsBaseUrlFromService(service: any): string { 96 + const raw = service?.encrypted_config?.hostname as string | undefined; 97 + if (!raw) { 98 + throw new Error("Missing PDS host"); 99 + } 100 + 101 + // Backend might return either `https://host` or just `host`. 102 + const withScheme = /^https?:\/\//i.test(raw) ? raw : `https://${raw}`; 103 + return withScheme.replace(/\/+$/, ""); 104 + } 105 +
+82
app/api/pds/atproto/invite/route.ts
··· 1 + import { NextResponse } from "next/server"; 2 + 3 + import { createHash } from "crypto"; 4 + 5 + import { getPdsBaseUrlFromService, getPdsServiceForCurrentUser } from "../helpers"; 6 + 7 + function toBasicAuth(user: string, pass: string) { 8 + return `Basic ${Buffer.from(`${user}:${pass}`).toString("base64")}`; 9 + } 10 + 11 + export async function POST(req: Request) { 12 + try { 13 + const { useCount } = (await req.json()) as { useCount?: number }; 14 + 15 + const { service, pdsServiceId } = await getPdsServiceForCurrentUser(); 16 + const requiredServiceIdRaw = process.env.NEXT_PUBLIC_PDS_TEST_SERVICE_ID; 17 + if (requiredServiceIdRaw) { 18 + const requiredServiceId = Number(requiredServiceIdRaw); 19 + if (pdsServiceId !== requiredServiceId) { 20 + return NextResponse.json( 21 + { 22 + message: `PDS service id mismatch: expected ${requiredServiceId}, got ${pdsServiceId}`, 23 + }, 24 + { status: 409 }, 25 + ); 26 + } 27 + } 28 + 29 + const adminPassword = service?.encrypted_config?.adminPassword as 30 + | string 31 + | undefined; 32 + 33 + if (!service?.encrypted_config || !adminPassword) { 34 + return NextResponse.json( 35 + { message: "Missing PDS host/admin credentials" }, 36 + { status: 500 }, 37 + ); 38 + } 39 + 40 + const trimmedAdminPassword = String(adminPassword).trim(); 41 + const adminPasswordHashPrefix = createHash("sha256") 42 + .update(trimmedAdminPassword) 43 + .digest("hex") 44 + .slice(0, 10); 45 + 46 + // PDS scripts use `admin:${PDS_ADMIN_PASSWORD}` 47 + const authHeader = toBasicAuth("admin", trimmedAdminPassword); 48 + 49 + const pdsBaseUrl = getPdsBaseUrlFromService(service); 50 + 51 + const res = await fetch( 52 + `${pdsBaseUrl}/xrpc/com.atproto.server.createInviteCode`, 53 + { 54 + method: "POST", 55 + headers: { 56 + "Content-Type": "application/json", 57 + Authorization: authHeader, 58 + }, 59 + body: JSON.stringify({ useCount: useCount ?? 1 }), 60 + }, 61 + ); 62 + 63 + const contentType = res.headers.get("content-type") || ""; 64 + const payload = contentType.includes("application/json") 65 + ? await res.json() 66 + : await res.text().catch(() => ""); 67 + 68 + if (!res.ok) { 69 + return NextResponse.json( 70 + { message: "Failed to create invite", status: res.status, payload }, 71 + { status: 502 }, 72 + ); 73 + } 74 + 75 + return NextResponse.json(payload); 76 + } catch (error) { 77 + const message = error instanceof Error ? error.message : "Unknown error"; 78 + const status = (error as any)?.status ?? 500; 79 + return NextResponse.json({ message }, { status }); 80 + } 81 + } 82 +
+224
app/api/pds/service/route.ts
··· 1 + import { NextResponse } from "next/server"; 2 + 3 + import { createClient } from "@/lib/supabase/server"; 4 + 5 + const PDS_API_BASE_URL = "https://k8s-pds.frx.pub/api/v1"; 6 + 7 + function getMockService() { 8 + const now = new Date(); 9 + const iso = (d: Date) => d.toISOString(); 10 + 11 + const storageAllocatedBytes = 10 * 1024 ** 3; // 10 GiB 12 + const storageUsedBytes = Math.floor(2.8 * 1024 ** 3); // ~2.8 GiB 13 + const bandwidthLimitBytesPerMonth = 100 * 1024 ** 3; // 100 GiB 14 + const bandwidthUsedBytesThisMonth = Math.floor(14.7 * 1024 ** 3); // ~14.7 GiB 15 + const cpuUsagePercent = 23; 16 + const ramUsagePercent = 41; 17 + const userSlotsUsed = 1; 18 + const userSlotsTotal = 10; 19 + 20 + const storageUsedDailyLast30d = Array.from({ length: 30 }).map((_, i) => { 21 + const d = new Date(now); 22 + d.setUTCDate(d.getUTCDate() - (29 - i)); 23 + const base = Math.floor(1.9 * 1024 ** 3); 24 + const growth = Math.floor(i * (34 * 1024 ** 2)); // ~34 MiB/day 25 + const noise = Math.floor(((i % 5) - 2) * (6 * 1024 ** 2)); 26 + return { date: iso(d).slice(0, 10), usedBytes: base + growth + noise }; 27 + }); 28 + 29 + const requestsPerHourLast24h = Array.from({ length: 24 }).map((_, i) => { 30 + const d = new Date(now); 31 + d.setUTCHours(d.getUTCHours() - (23 - i), 0, 0, 0); 32 + const wave = 260 + Math.floor(180 * Math.sin((i / 24) * Math.PI * 2)); 33 + const jitter = (i % 3) * 17; 34 + return { hour: iso(d), count: Math.max(40, wave + jitter) }; 35 + }); 36 + 37 + const failedRequestsLast24h = 42; 38 + const successfulRequestsLast24h = requestsPerHourLast24h.reduce( 39 + (sum, p) => sum + p.count, 40 + 0 41 + ); 42 + 43 + return { 44 + id: 1, 45 + name: "test1-pds", 46 + service: "bluesky-pds", 47 + namespace: "kd0186-test1-pds", 48 + encrypted_config: { 49 + hostname: "test1.eny.space", 50 + adminPassword: "zoidberg", 51 + emailSmtpUrl: "smtps://max@mustermann.de:s3cr3t@smtp.mustermann.de:465/", 52 + pdsEmailFromAddress: "test1@example.com", 53 + dataStorage: { 54 + size: "10Gi", 55 + }, 56 + }, 57 + install_cmd: 58 + "export KUBECONFIG={kubeconfig}\n" + 59 + "helm repo add nerkho https://charts.nerkho.ch\n" + 60 + "helm repo update\n" + 61 + "helm install bluesky-pds nerkho/bluesky-pds --namespace {namespace} -f {values}\n" + 62 + 'export KUBECONFIG=""', 63 + state: 0, 64 + kubeconfig_id: 1, 65 + created_at: "2026-03-17T15:05:40.000000Z", 66 + updated_at: "2026-03-17T15:05:40.000000Z", 67 + stats: { 68 + cpuUsagePercent, 69 + ramUsagePercent, 70 + storageUsedBytes, 71 + storageAllocatedBytes, 72 + storageObjectsCount: 12345, 73 + storageUsedDailyLast30d, 74 + bandwidthUsedBytesThisMonth, 75 + bandwidthLimitBytesPerMonth, 76 + requestsLast24h: successfulRequestsLast24h, 77 + requestsPerHourLast24h, 78 + activeUsers: 3, 79 + uniqueUsersLast30d: 27, 80 + userSlotsUsed, 81 + userSlotsTotal, 82 + uptimeSeconds: 987654, 83 + lastBackupAt: new Date(now.getTime() - 6 * 60 * 60 * 1000).toISOString(), 84 + failedRequestsLast24h, 85 + successfulRequestsLast24h, 86 + }, 87 + }; 88 + } 89 + 90 + export async function GET() { 91 + try { 92 + const useMock = process.env.PDS_USE_MOCK === "true"; 93 + if (useMock) { 94 + return NextResponse.json(getMockService()); 95 + } 96 + 97 + const apiToken = process.env.PDS_API_TOKEN; 98 + 99 + if (!apiToken) { 100 + return NextResponse.json( 101 + { 102 + error: 103 + "Missing PDS_API_TOKEN env variable for authenticating with PDS API", 104 + }, 105 + { status: 500 } 106 + ); 107 + } 108 + 109 + const supabase = await createClient(); 110 + const { 111 + data: { user }, 112 + } = await supabase.auth.getUser(); 113 + 114 + if (!user) { 115 + return NextResponse.json({ message: "Unauthorized" }, { status: 401 }); 116 + } 117 + 118 + const { data: pdsServiceRow } = await supabase 119 + .from("pds_services") 120 + .select("pds_service_id") 121 + .eq("user_id", user.id) 122 + .maybeSingle(); 123 + 124 + const forcedServiceIdRaw = 125 + process.env.PDS_FORCE_SERVICE_ID === "true" 126 + ? process.env.PDS_TEST_SERVICE_ID 127 + : undefined; 128 + const forcedServiceId = forcedServiceIdRaw 129 + ? Number(forcedServiceIdRaw) 130 + : null; 131 + 132 + const pdsServiceId = ( 133 + forcedServiceId !== null && Number.isFinite(forcedServiceId) 134 + ? forcedServiceId 135 + : pdsServiceRow?.pds_service_id 136 + ) as number | null | undefined; 137 + 138 + if (!pdsServiceId) { 139 + return NextResponse.json( 140 + { message: "No provisioned PDS found for this user yet" }, 141 + { status: 404 } 142 + ); 143 + } 144 + 145 + const pdsServiceUrl = `${PDS_API_BASE_URL}/service/${pdsServiceId}`; 146 + 147 + const res = await fetch(pdsServiceUrl, { 148 + // Ensure this runs server-side only and is not cached aggressively 149 + cache: "no-store", 150 + headers: { 151 + Accept: "application/json", 152 + "X-Requested-With": "XMLHttpRequest", 153 + Authorization: `Bearer ${apiToken}`, 154 + }, 155 + }); 156 + 157 + const contentType = res.headers.get("content-type") || ""; 158 + 159 + // Try to parse JSON if it looks like JSON, otherwise fall back to text 160 + if (contentType.includes("application/json")) { 161 + let data: unknown = await res.json(); 162 + 163 + // Some backends double-encode JSON as a string; handle that gracefully. 164 + if (typeof data === "string") { 165 + try { 166 + data = JSON.parse(data); 167 + } catch { 168 + // keep as string if it isn't valid JSON 169 + } 170 + } 171 + 172 + if (!res.ok) { 173 + return NextResponse.json( 174 + { 175 + error: "Upstream request failed", 176 + status: res.status, 177 + body: data, 178 + }, 179 + { status: 502 } 180 + ); 181 + } 182 + 183 + // Redact sensitive secrets before sending to the browser. 184 + if (data && typeof data === "object") { 185 + const d: any = data; 186 + if (d.encrypted_config && typeof d.encrypted_config === "object") { 187 + if ("adminPassword" in d.encrypted_config) { 188 + d.encrypted_config.adminPassword = "redacted"; 189 + } 190 + if ("jwtSecret" in d.encrypted_config) { 191 + d.encrypted_config.jwtSecret = "redacted"; 192 + } 193 + if ("plcRotationKey" in d.encrypted_config) { 194 + d.encrypted_config.plcRotationKey = "redacted"; 195 + } 196 + } 197 + } 198 + 199 + return NextResponse.json(data); 200 + } 201 + 202 + const bodyText = await res.text(); 203 + 204 + // Return diagnostics so we can see what the upstream is sending 205 + return NextResponse.json( 206 + { 207 + error: "Upstream did not return JSON", 208 + status: res.status, 209 + contentType, 210 + bodyPreview: bodyText.slice(0, 500), 211 + }, 212 + { status: 502 } 213 + ); 214 + } catch (error) { 215 + console.error("Error proxying PDS service request", error); 216 + return NextResponse.json( 217 + { 218 + error: "Failed to reach PDS service endpoint", 219 + detail: error instanceof Error ? error.message : String(error), 220 + }, 221 + { status: 500 } 222 + ); 223 + } 224 + }
+224 -35
app/api/webhooks/route.ts
··· 2 2 3 3 import { NextResponse } from "next/server"; 4 4 5 + import { randomBytes } from "crypto"; 6 + 5 7 import { stripe } from "@/lib/stripe"; 8 + import { createAdminClient } from "@/lib/supabase/admin"; 9 + 10 + const PDS_API_BASE_URL = "https://k8s-pds.frx.pub/api/v1"; 11 + 12 + function normalizeSlug(value: string) { 13 + return value 14 + .toLowerCase() 15 + .replace(/[^a-z0-9-]/g, "-") 16 + .replace(/^-+/, "") 17 + .replace(/-+$/, "") 18 + .slice(0, 63); 19 + } 20 + 21 + function normalizeDeployHostname(raw: string) { 22 + let h = raw.trim(); 23 + h = h.replace(/^https?:\/\//i, ""); 24 + h = h.replace(/\/.*$/, ""); 25 + return h.replace(/\/$/, ""); 26 + } 27 + 28 + function isValidFqdn(host: string) { 29 + if (!host || host.length > 253) return false; 30 + if (host.endsWith(".")) return false; 31 + const parts = host.split("."); 32 + if (parts.length < 2) return false; 33 + return parts.every((label) => { 34 + if (!label || label.length > 63) return false; 35 + if (!/^[a-z0-9-]+$/i.test(label)) return false; 36 + if (label.startsWith("-") || label.endsWith("-")) return false; 37 + return true; 38 + }); 39 + } 40 + 41 + async function provisionPdsForUser({ 42 + userId, 43 + userEmail, 44 + pdsUsername, 45 + pdsHostnameBase, 46 + disksizeGb, 47 + }: { 48 + userId: string; 49 + userEmail: string; 50 + pdsUsername: string; 51 + pdsHostnameBase: string; 52 + disksizeGb: string; 53 + }) { 54 + const apiToken = process.env.PDS_API_TOKEN; 55 + if (!apiToken) { 56 + throw new Error("Missing PDS_API_TOKEN env var"); 57 + } 58 + 59 + const password = randomBytes(16).toString("base64url"); 60 + const hostname = normalizeDeployHostname(pdsHostnameBase); 61 + if (!isValidFqdn(hostname)) { 62 + throw new Error( 63 + `Invalid hostname for deploy after normalization: "${hostname}" (raw="${pdsHostnameBase}")`, 64 + ); 65 + } 66 + 67 + const disksizeParsed = Number(disksizeGb); 68 + if (!Number.isFinite(disksizeParsed) || disksizeParsed <= 0) { 69 + throw new Error( 70 + `Invalid pds_disksize_gb metadata value: "${disksizeGb}". Expected a positive number.`, 71 + ); 72 + } 73 + const disksize = Math.floor(disksizeParsed); 74 + 75 + const supabase = createAdminClient(); 76 + 77 + // Idempotency: if we already have a service_id stored, don't redeploy 78 + const { data: existing } = await supabase 79 + .from("pds_services") 80 + .select("pds_service_id,status") 81 + .eq("user_id", userId) 82 + .maybeSingle(); 83 + 84 + if (existing) { 85 + if (existing.pds_service_id) { 86 + return { skipped: true, pds_service_id: existing.pds_service_id }; 87 + } 88 + // Retry deploy for known retryable states where id may be missing. 89 + // Keep skipping for everything else to avoid duplicate provisioning. 90 + const retryableStatuses = new Set([ 91 + "deploy_failed", 92 + "deploy_succeeded_no_id", 93 + ]); 94 + if (existing.status && !retryableStatuses.has(existing.status)) { 95 + return { skipped: true, pds_service_id: null }; 96 + } 97 + } 98 + 99 + const deployRes = await fetch(`${PDS_API_BASE_URL}/deploy`, { 100 + method: "POST", 101 + headers: { 102 + Accept: "application/json", 103 + "Content-Type": "application/json", 104 + Authorization: `Bearer ${apiToken}`, 105 + }, 106 + body: JSON.stringify({ 107 + username: pdsUsername, 108 + password, 109 + email: userEmail, 110 + hostname, 111 + disksize, 112 + }), 113 + }); 114 + 115 + const deployContentType = deployRes.headers.get("content-type") || ""; 116 + const deployBody = deployContentType.includes("application/json") 117 + ? await deployRes.json() 118 + : await deployRes.text(); 119 + 120 + if (!deployRes.ok) { 121 + // Persist failure status for easier debugging 122 + await supabase.from("pds_services").upsert({ 123 + user_id: userId, 124 + hostname, 125 + status: "deploy_failed", 126 + }); 127 + throw new Error( 128 + `PDS deploy failed (${deployRes.status}) for hostname "${hostname}": ${ 129 + typeof deployBody === "string" ? deployBody : JSON.stringify(deployBody) 130 + }`, 131 + ); 132 + } 133 + 134 + const maybeServiceId = 135 + (typeof deployBody === "object" && deployBody !== null 136 + ? ((deployBody as any).service_id ?? 137 + (deployBody as any).serviceId ?? 138 + (deployBody as any).id ?? 139 + (deployBody as any).service?.id ?? 140 + (deployBody as any).data?.id ?? 141 + (deployBody as any).data?.serviceId) 142 + : undefined) ?? null; 143 + 144 + const pds_service_id = 145 + typeof maybeServiceId === "string" || typeof maybeServiceId === "number" 146 + ? Number(maybeServiceId) 147 + : null; 148 + 149 + await supabase.from("pds_services").upsert({ 150 + user_id: userId, 151 + pds_service_id, 152 + hostname, 153 + status: pds_service_id ? "provisioning" : "deploy_succeeded_no_id", 154 + }); 155 + 156 + return { skipped: false, pds_service_id }; 157 + } 6 158 7 159 export async function POST(req: Request) { 8 160 let event: Stripe.Event; ··· 15 167 ); 16 168 } catch (err) { 17 169 const errorMessage = err instanceof Error ? err.message : "Unknown error"; 18 - // On error, log and return the error message. 19 - if (!(err instanceof Error)) console.log(err); 20 - console.log(`❌ Error message: ${errorMessage}`); 170 + console.log(`❌ Webhook Error: ${errorMessage}`); 21 171 return NextResponse.json( 22 172 { message: `Webhook Error: ${errorMessage}` }, 23 173 { status: 400 }, 24 174 ); 25 175 } 26 176 27 - // Successfully constructed event. 28 - console.log("✅ Success:", event.id); 177 + console.log("✅ Webhook received:", event.type); 178 + 179 + const supabase = createAdminClient(); 180 + 181 + // Only handle checkout completion to store customer_id 182 + if (event.type === "checkout.session.completed") { 183 + const session = event.data.object as Stripe.Checkout.Session; 29 184 30 - const permittedEvents: string[] = [ 31 - "checkout.session.completed", 32 - "payment_intent.succeeded", 33 - "payment_intent.payment_failed", 34 - ]; 185 + if (session.mode === "subscription" && session.customer) { 186 + const userId = session.metadata?.user_id; 187 + const userEmail = session.metadata?.user_email; 188 + const customerId = 189 + typeof session.customer === "string" 190 + ? session.customer 191 + : session.customer.id; 192 + 193 + if (userId && customerId) { 194 + // Store user_id -> stripe_customer_id mapping (minimal) 195 + // Avoid creating duplicate rows if the webhook is delivered more than once. 196 + const { data: existingSub } = await supabase 197 + .from("subscriptions") 198 + .select("id") 199 + .eq("user_id", userId) 200 + .limit(1) 201 + .maybeSingle(); 202 + 203 + if (!existingSub) { 204 + const { error } = await supabase 205 + .from("subscriptions") 206 + .insert({ user_id: userId, stripe_customer_id: customerId }); 207 + if (error) console.error("Error inserting customer ID:", error); 208 + else console.log(`✅ Customer ID stored for user ${userId}`); 209 + } else { 210 + const { error } = await supabase 211 + .from("subscriptions") 212 + .update({ stripe_customer_id: customerId }) 213 + .eq("id", existingSub.id); 214 + if (error) console.error("Error updating customer ID:", error); 215 + } 35 216 36 - if (permittedEvents.includes(event.type)) { 37 - let data; 217 + // Next step: provision the user's PDS 218 + if (userEmail) { 219 + const fallbackUsername = normalizeSlug( 220 + userEmail.split("@")[0] || "pds", 221 + ); 222 + const pdsUsername = normalizeSlug( 223 + session.metadata?.pds_username || fallbackUsername, 224 + ); 225 + const pdsHostnameBase = 226 + session.metadata?.pds_hostname_base || 227 + `${pdsUsername}.eny.k8s.frx.pub`; 228 + const disksizeGb = session.metadata?.pds_disksize_gb || "10"; 38 229 39 - try { 40 - switch (event.type) { 41 - case "checkout.session.completed": 42 - data = event.data.object as Stripe.Checkout.Session; 43 - console.log(`💰 CheckoutSession status: ${data.payment_status}`); 44 - break; 45 - case "payment_intent.payment_failed": 46 - data = event.data.object as Stripe.PaymentIntent; 47 - console.log(`❌ Payment failed: ${data.last_payment_error?.message}`); 48 - break; 49 - case "payment_intent.succeeded": 50 - data = event.data.object as Stripe.PaymentIntent; 51 - console.log(`💰 PaymentIntent status: ${data.status}`); 52 - break; 53 - default: 54 - throw new Error(`Unhandled event: ${event.type}`); 230 + try { 231 + console.log(`✅ Provisioning PDS for user ${userId}...`); 232 + await provisionPdsForUser({ 233 + userId, 234 + userEmail, 235 + pdsUsername, 236 + pdsHostnameBase, 237 + disksizeGb, 238 + }); 239 + } catch (e) { 240 + console.error(`❌ Provisioning PDS failed for ${userId}:`, e); 241 + } 242 + } else { 243 + console.warn( 244 + `⚠️ Missing user_email metadata in checkout session for user ${userId}.`, 245 + ); 246 + } 55 247 } 56 - } catch (error) { 57 - console.log(error); 58 - return NextResponse.json( 59 - { message: "Webhook handler failed" }, 60 - { status: 500 }, 61 - ); 62 248 } 63 249 } 64 - // Return a response to acknowledge receipt of the event. 250 + 251 + // All other subscription events are handled by querying Stripe directly 252 + // No need to sync subscription details to database 253 + 65 254 return NextResponse.json({ message: "Received" }, { status: 200 }); 66 255 }
+15
app/auth/callback/route.ts
··· 1 + import { createClient } from "@/lib/supabase/server"; 2 + import { NextResponse } from "next/server"; 3 + 4 + export async function GET(request: Request) { 5 + const requestUrl = new URL(request.url); 6 + const code = requestUrl.searchParams.get("code"); 7 + const next = requestUrl.searchParams.get("next") || "/dashboard"; 8 + 9 + if (code) { 10 + const supabase = await createClient(); 11 + await supabase.auth.exchangeCodeForSession(code); 12 + } 13 + 14 + return NextResponse.redirect(new URL(next, request.url)); 15 + }
-17
app/checkout/page.tsx
··· 1 - import type { Metadata } from "next"; 2 - 3 - import CheckoutForm from "@/components/CheckoutForm"; 4 - 5 - export const metadata: Metadata = { 6 - title: "Purchase Hosting", 7 - }; 8 - 9 - export default function DonatePage(): JSX.Element { 10 - return ( 11 - <div className="page-container"> 12 - <h1>Purchase Hosting Service</h1> 13 - <p>Select your hosting plan and complete your purchase</p> 14 - <CheckoutForm uiMode="hosted" /> 15 - </div> 16 - ); 17 - }
-5
app/checkout/result/error.tsx
··· 1 - "use client"; 2 - 3 - export default function Error({ error }: { error: Error }) { 4 - return <h2>{error.message}</h2>; 5 - }
-18
app/checkout/result/layout.tsx
··· 1 - import type { Metadata } from "next"; 2 - 3 - export const metadata: Metadata = { 4 - title: "Checkout Session Result", 5 - }; 6 - 7 - export default function ResultLayout({ 8 - children, 9 - }: { 10 - children: React.ReactNode; 11 - }): JSX.Element { 12 - return ( 13 - <div className="page-container"> 14 - <h1>Checkout Session Result</h1> 15 - {children} 16 - </div> 17 - ); 18 - }
-82
app/checkout/result/page.tsx
··· 1 - import type { Stripe } from "stripe"; 2 - 3 - import PrintObject from "@/components/PrintObject"; 4 - import { stripe } from "@/lib/stripe"; 5 - 6 - import Link from "next/link"; 7 - 8 - export default async function ResultPage({ 9 - searchParams, 10 - }: { 11 - searchParams: Promise<{ session_id?: string | string[] }>; 12 - }): Promise<JSX.Element> { 13 - const params = await searchParams; 14 - const sessionId = Array.isArray(params.session_id) 15 - ? params.session_id[0] 16 - : params.session_id; 17 - 18 - if (!sessionId) { 19 - return ( 20 - <div className="page-container"> 21 - <h2>No session found</h2> 22 - <p> 23 - It looks like you didn't complete a checkout session, or the session 24 - information is missing. 25 - </p> 26 - <Link 27 - href="/checkout" 28 - style={{ 29 - display: "inline-block", 30 - padding: "12px 24px", 31 - borderRadius: "6px", 32 - marginTop: "16px", 33 - backgroundColor: "#8f6ed5", 34 - color: "#fff", 35 - textDecoration: "none", 36 - }} 37 - > 38 - Return to purchase page 39 - </Link> 40 - </div> 41 - ); 42 - } 43 - 44 - try { 45 - const checkoutSession: Stripe.Checkout.Session = 46 - await stripe.checkout.sessions.retrieve(sessionId, { 47 - expand: ["line_items", "payment_intent"], 48 - }); 49 - 50 - const paymentIntent = 51 - checkoutSession.payment_intent as Stripe.PaymentIntent; 52 - 53 - return ( 54 - <> 55 - <h2>Status: {paymentIntent.status}</h2> 56 - <h3>Checkout Session response:</h3> 57 - <PrintObject content={checkoutSession} /> 58 - </> 59 - ); 60 - } catch (error) { 61 - return ( 62 - <div className="page-container"> 63 - <h2>Error retrieving session</h2> 64 - <p>The checkout session could not be retrieved. Please try again.</p> 65 - <Link 66 - href="/checkout" 67 - style={{ 68 - display: "inline-block", 69 - padding: "12px 24px", 70 - borderRadius: "6px", 71 - marginTop: "16px", 72 - backgroundColor: "#8f6ed5", 73 - color: "#fff", 74 - textDecoration: "none", 75 - }} 76 - > 77 - Return to purchase page 78 - </Link> 79 - </div> 80 - ); 81 - } 82 - }
-83
app/components/CheckoutForm.tsx
··· 1 - "use client"; 2 - 3 - import type Stripe from "stripe"; 4 - 5 - import React, { useState } from "react"; 6 - 7 - import CustomDonationInput from "@/components/CustomDonationInput"; 8 - import TestCards from "@/components/TestCards"; 9 - 10 - import { formatAmountForDisplay } from "@/utils/stripe-helpers"; 11 - import * as config from "@/config"; 12 - import { createCheckoutSession } from "@/actions/stripe"; 13 - import getStripe from "@/utils/get-stripejs"; 14 - import { 15 - EmbeddedCheckout, 16 - EmbeddedCheckoutProvider, 17 - } from "@stripe/react-stripe-js"; 18 - 19 - interface CheckoutFormProps { 20 - uiMode: Stripe.Checkout.SessionCreateParams.UiMode; 21 - } 22 - 23 - export default function CheckoutForm(props: CheckoutFormProps): JSX.Element { 24 - const [loading] = useState<boolean>(false); 25 - const [input, setInput] = useState<{ customDonation: number }>({ 26 - customDonation: Math.round(config.MAX_AMOUNT / config.AMOUNT_STEP), 27 - }); 28 - const [clientSecret, setClientSecret] = useState<string | null>(null); 29 - 30 - const handleInputChange: React.ChangeEventHandler<HTMLInputElement> = ( 31 - e 32 - ): void => 33 - setInput({ 34 - ...input, 35 - [e.currentTarget.name]: e.currentTarget.value, 36 - }); 37 - 38 - const formAction = async (data: FormData): Promise<void> => { 39 - const uiMode = data.get( 40 - "uiMode" 41 - ) as Stripe.Checkout.SessionCreateParams.UiMode; 42 - const { client_secret, url } = await createCheckoutSession(data); 43 - 44 - if (uiMode === "embedded") return setClientSecret(client_secret); 45 - 46 - window.location.assign(url as string); 47 - }; 48 - 49 - return ( 50 - <> 51 - <form action={formAction}> 52 - <input type="hidden" name="uiMode" value={props.uiMode} /> 53 - <CustomDonationInput 54 - className="checkout-style" 55 - name="customDonation" 56 - min={config.MIN_AMOUNT} 57 - max={config.MAX_AMOUNT} 58 - step={config.AMOUNT_STEP} 59 - currency={config.CURRENCY} 60 - onChange={handleInputChange} 61 - value={input.customDonation} 62 - /> 63 - <TestCards /> 64 - <button 65 - className="checkout-style-background" 66 - type="submit" 67 - disabled={loading} 68 - > 69 - Purchase{" "} 70 - {formatAmountForDisplay(input.customDonation, config.CURRENCY)} 71 - </button> 72 - </form> 73 - {clientSecret ? ( 74 - <EmbeddedCheckoutProvider 75 - stripe={getStripe()} 76 - options={{ clientSecret }} 77 - > 78 - <EmbeddedCheckout /> 79 - </EmbeddedCheckoutProvider> 80 - ) : null} 81 - </> 82 - ); 83 - }
-38
app/components/CustomDonationInput.tsx
··· 1 - import { formatAmountForDisplay } from "@/utils/stripe-helpers"; 2 - 3 - export default function CustomDonationInput({ 4 - name, 5 - min, 6 - max, 7 - currency, 8 - step, 9 - onChange, 10 - value, 11 - className, 12 - }: { 13 - name: string; 14 - min: number; 15 - max: number; 16 - currency: string; 17 - step: number; 18 - onChange: (e: React.ChangeEvent<HTMLInputElement>) => void; 19 - value: number; 20 - className?: string; 21 - }): JSX.Element { 22 - return ( 23 - <label> 24 - Service amount ({formatAmountForDisplay(min, currency)}- 25 - {formatAmountForDisplay(max, currency)}): 26 - <input 27 - type="range" 28 - name={name} 29 - min={min} 30 - max={max} 31 - step={step} 32 - onChange={onChange} 33 - value={value} 34 - className={className} 35 - ></input> 36 - </label> 37 - ); 38 - }
-10
app/components/PrintObject.tsx
··· 1 - import type { Stripe } from "stripe"; 2 - 3 - export default function PrintObject({ 4 - content, 5 - }: { 6 - content: Stripe.PaymentIntent | Stripe.Checkout.Session; 7 - }): JSX.Element { 8 - const formattedContent: string = JSON.stringify(content, null, 2); 9 - return <pre>{formattedContent}</pre>; 10 - }
-11
app/components/TestCards.tsx
··· 1 - export default function TestCards(): JSX.Element { 2 - return ( 3 - <div className="test-card-notice"> 4 - Use test cards for testing, e.g.{" "} 5 - <div className="card-number"> 6 - 4242<span></span>4242<span></span>4242<span></span>4242 7 - </div> 8 - . 9 - </div> 10 - ); 11 - }
+29
app/components/button-link.tsx
··· 1 + import Link from "next/link"; 2 + import { cn } from "@/actions/lib/utils"; 3 + 4 + interface ButtonLinkProps { 5 + href: string; 6 + children: React.ReactNode; 7 + className?: string; 8 + endIcon?: React.ReactNode; 9 + } 10 + 11 + export function ButtonLink({ 12 + href, 13 + children, 14 + className, 15 + endIcon, 16 + }: ButtonLinkProps) { 17 + return ( 18 + <Link 19 + href={href} 20 + className={cn( 21 + "inline-flex h-11 items-center justify-center gap-2 rounded-full px-5 py-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2", 22 + className 23 + )} 24 + > 25 + {children} 26 + {endIcon} 27 + </Link> 28 + ); 29 + }
+44
app/components/cta/cta-section.tsx
··· 1 + import { ButtonLink } from "@/components/button-link"; 2 + import { Heading } from "@/components/heading"; 3 + import { Paragraph } from "@/components/paragraph"; 4 + import { ArrowRightIcon } from "lucide-react"; 5 + import { prelaunch } from "@/lib/prelaunch"; 6 + 7 + export function CTASection() { 8 + return ( 9 + <section className="relative w-full px-4 py-16 sm:px-6 sm:py-20"> 10 + <div className="mx-auto flex max-w-5xl flex-col items-center gap-6 text-center sm:gap-7"> 11 + <Heading 12 + as="h2" 13 + className="text-2xl font-semibold tracking-tight text-white sm:text-3xl md:text-4xl" 14 + > 15 + Explore your PDS like a real space, not just an API. 16 + </Heading> 17 + <Paragraph className="max-w-2xl text-sm text-white/70 sm:text-base"> 18 + Spin up a managed PDS in a few clicks and explore it through a clean, 19 + browser-based UI. See your posts, files and collections instead of raw 20 + JSON—then upgrade to dedicated hosting when you're ready. 21 + </Paragraph> 22 + 23 + {!prelaunch && ( 24 + <div className="mt-2 flex flex-wrap items-center justify-center gap-3"> 25 + <ButtonLink 26 + href="/demo" 27 + className="border border-white/30 bg-transparent px-6 text-xs font-semibold uppercase tracking-wide text-white hover:border-white hover:bg-white/10" 28 + endIcon={<ArrowRightIcon className="size-4" aria-hidden />} 29 + > 30 + Open PDS UI demo 31 + </ButtonLink> 32 + <ButtonLink 33 + href="/signup" 34 + className="px-6 text-xs font-semibold uppercase tracking-wide text-neutral-950 shadow-[0_0_40px_rgba(232,121,249,0.45)] bg-fuchsia-400 hover:bg-fuchsia-300" 35 + endIcon={<ArrowRightIcon className="size-4" aria-hidden />} 36 + > 37 + Start free trial 38 + </ButtonLink> 39 + </div> 40 + )} 41 + </div> 42 + </section> 43 + ); 44 + }
+2
app/components/cta/index.ts
··· 1 + export { CTASection } from "./cta-section"; 2 +
+114
app/components/faq/faq-section.tsx
··· 1 + "use client"; 2 + 3 + import { useState } from "react"; 4 + import { Heading } from "@/components/heading"; 5 + import { Paragraph } from "@/components/paragraph"; 6 + import { MinusIcon, PlusIcon } from "lucide-react"; 7 + 8 + type FaqItem = { 9 + id: string; 10 + question: string; 11 + answer: string; 12 + }; 13 + 14 + const FAQ_ITEMS: FaqItem[] = [ 15 + { 16 + id: "what-is-pds", 17 + question: "What is a Personal Data Server (PDS)?", 18 + answer: 19 + "A PDS is the place where your data and identity for the AT Protocol live. Instead of being locked into one platform, your posts, media and profile are stored on a server you control - and eny.space makes running that server manageable through a simple dashboard.", 20 + }, 21 + { 22 + id: "do-i-need-own-server", 23 + question: "Do I need to understand Kubernetes, Docker or cloud hosting?", 24 + answer: 25 + "No. The whole point of eny.space is managed PDS hosting: you click to create a PDS and we take care of the underlying infrastructure. You can still bring your own domain and adjust settings, but you never have to touch kubectl or obscure cloud dashboards.", 26 + }, 27 + { 28 + id: "pds-browser-free", 29 + question: "Is the PDS browser UI free to use?", 30 + answer: 31 + "The PDS explorer UI is designed to be freely accessible for browsing public data on your PDS - similar to how you might explore content on Bluesky today. Managed hosting, dedicated resources and custom domains sit on top as paid features when you want your own isolated space.", 32 + }, 33 + { 34 + id: "billing-and-payments", 35 + question: "How do billing and payments work for eny.space?", 36 + answer: 37 + "We integrate with modern payment providers so you can subscribe in a few clicks. Behind the scenes, we handle invoices, taxes and payouts for you, so you only see a clear monthly charge for your plan instead of having to reconcile every PDS user manually.", 38 + }, 39 + { 40 + id: "who-is-it-for", 41 + question: "Who is eny.space built for?", 42 + answer: 43 + "eny.space is aimed at AT Protocol and Bluesky power users, indie developers and communities who want their own PDS without becoming infrastructure engineers. If you care about owning your data and having a clear UI to manage it, you are our target audience.", 44 + }, 45 + ]; 46 + 47 + export function FAQSection() { 48 + const [openId, setOpenId] = useState<string | null>(FAQ_ITEMS[0]?.id ?? null); 49 + 50 + return ( 51 + <section id="faq" className="relative w-full px-4 py-20 sm:px-6 sm:py-24"> 52 + <div className="mx-auto max-w-4xl text-center"> 53 + <Heading 54 + as="h2" 55 + className="text-2xl font-semibold tracking-tight text-white sm:text-3xl md:text-4xl" 56 + > 57 + Frequently Asked Questions 58 + </Heading> 59 + <Paragraph className="mt-4 text-sm text-white/70 sm:text-base"> 60 + answers to the most common questions about managed PDS hosting and the 61 + eny.space PDS browser. If you can't find what you're looking for, feel 62 + free to{" "} 63 + <a 64 + href="mailto:hello@krekeny.com" 65 + className="font-semibold text-white underline underline-offset-2 hover:text-white/80" 66 + > 67 + reach out to our friendly team 68 + </a> 69 + . 70 + </Paragraph> 71 + </div> 72 + 73 + <div className="mx-auto mt-10 max-w-3xl space-y-3 sm:mt-12"> 74 + {FAQ_ITEMS.map((item) => { 75 + const isOpen = openId === item.id; 76 + 77 + return ( 78 + <div 79 + key={item.id} 80 + className={[ 81 + "overflow-hidden rounded-2xl border border-white/10 bg-neutral-900/40 transition-colors", 82 + isOpen ? "bg-neutral-900/80" : "hover:bg-neutral-900/60", 83 + ].join(" ")} 84 + > 85 + <button 86 + type="button" 87 + onClick={() => setOpenId(isOpen ? null : item.id)} 88 + className="flex w-full cursor-pointer items-center justify-between gap-4 px-5 py-4 text-left" 89 + aria-expanded={isOpen} 90 + > 91 + <span className="text-sm font-medium text-white sm:text-base"> 92 + {item.question} 93 + </span> 94 + <span className="flex size-7 items-center justify-center rounded-full bg-white/8 text-white"> 95 + {isOpen ? ( 96 + <MinusIcon className="size-4" aria-hidden /> 97 + ) : ( 98 + <PlusIcon className="size-4" aria-hidden /> 99 + )} 100 + </span> 101 + </button> 102 + 103 + {isOpen && ( 104 + <div className="border-t border-white/10 px-5 pb-5 pt-3 text-sm text-white/75"> 105 + {item.answer} 106 + </div> 107 + )} 108 + </div> 109 + ); 110 + })} 111 + </div> 112 + </section> 113 + ); 114 + }
+2
app/components/faq/index.ts
··· 1 + export { FAQSection } from "./faq-section"; 2 +
+39
app/components/features/feature-card.tsx
··· 1 + import { cn } from "@/actions/lib/utils"; 2 + import { Heading } from "@/components/heading"; 3 + import { Paragraph } from "@/components/paragraph"; 4 + 5 + interface FeatureCardProps { 6 + icon: React.ReactNode; 7 + title: string; 8 + description: string; 9 + className?: string; 10 + } 11 + 12 + export function FeatureCard({ 13 + icon, 14 + title, 15 + description, 16 + className, 17 + }: FeatureCardProps) { 18 + return ( 19 + <div 20 + className={cn( 21 + "relative flex flex-col items-center gap-3 rounded-2xl bg-neutral-900/80 px-5 py-6 shadow-[0_0_40px_rgba(0,0,0,0.6)] ring-1 ring-white/5", 22 + className, 23 + )} 24 + > 25 + <div className="mb-1 inline-flex size-10 items-center justify-center rounded-xl bg-fuchsia-400/15 text-fuchsia-300 shadow-[0_0_30px_rgba(232,121,249,0.6)]"> 26 + {icon} 27 + </div> 28 + <Heading 29 + as="h3" 30 + className="text-base font-semibold text-white text-center" 31 + > 32 + {title} 33 + </Heading> 34 + <Paragraph className="text-sm leading-relaxed text-white/70 text-center"> 35 + {description} 36 + </Paragraph> 37 + </div> 38 + ); 39 + }
+79
app/components/features/features-section.tsx
··· 1 + import { 2 + CloudIcon, 3 + NetworkIcon, 4 + ScaleIcon, 5 + ShieldCheckIcon, 6 + ZapIcon, 7 + RocketIcon, 8 + } from "lucide-react"; 9 + import { Heading } from "@/components/heading"; 10 + import { Paragraph } from "@/components/paragraph"; 11 + import { FeatureCard } from "./feature-card"; 12 + 13 + const FEATURES = [ 14 + { 15 + title: "One‑click managed PDS.", 16 + description: 17 + "Create a Personal Data Server directly from the eny.space UI—no Kubernetes clusters, Docker images or cloud consoles to wire up. Choose your settings, attach a domain and go live in minutes.", 18 + icon: <NetworkIcon className="size-5" aria-hidden />, 19 + }, 20 + { 21 + title: "Dashboard‑first administration.", 22 + description: 23 + "Invite users to your PDS, manage access and roles, and handle tasks you would normally script on the command line from a clear web dashboard.", 24 + icon: <CloudIcon className="size-5" aria-hidden />, 25 + }, 26 + { 27 + title: "Live resource insights.", 28 + description: 29 + "Track active users, storage, CPU and RAM as intuitive percentages so you instantly see how loaded your server is, instead of digging through logs.", 30 + icon: <ScaleIcon className="size-5" aria-hidden />, 31 + }, 32 + { 33 + title: "AT Protocol‑native access.", 34 + description: 35 + "Built for AT Protocol and Bluesky power users who arrive with an email and handle, not yet another social login. Your PDS becomes your social cloud space.", 36 + icon: <ShieldCheckIcon className="size-5" aria-hidden />, 37 + }, 38 + { 39 + title: "PDS explorer UI.", 40 + description: 41 + "Browse everything on your PDS like a file explorer—posts, images, PDFs and collections. See what’s stored, which apps use it and treat your PDS as a real, visual space.", 42 + icon: <ZapIcon className="size-5" aria-hidden />, 43 + }, 44 + ]; 45 + 46 + export function FeaturesSection() { 47 + return ( 48 + <section 49 + id="features" 50 + className="relative w-full px-4 py-16 sm:px-6 sm:py-20" 51 + > 52 + <div className="mx-auto max-w-5xl text-center"> 53 + <Heading 54 + as="h2" 55 + className="text-2xl font-semibold tracking-tight text-white sm:text-3xl md:text-4xl" 56 + > 57 + Managed PDS hosting for AT Protocol power users. 58 + </Heading> 59 + <Paragraph className="mt-4 text-sm text-white/70 sm:text-base"> 60 + Create, monitor and manage your Personal Data Server from a single 61 + dashboard. eny.space automates the infrastructure so you can focus on 62 + your data, apps and community. 63 + </Paragraph> 64 + </div> 65 + 66 + <div className="mx-auto mt-10 flex max-w-6xl flex-wrap justify-center gap-6 sm:mt-12"> 67 + {FEATURES.map((feature) => ( 68 + <FeatureCard 69 + key={feature.title} 70 + icon={feature.icon} 71 + title={feature.title} 72 + description={feature.description} 73 + className="basis-[min(100%,320px)]" 74 + /> 75 + ))} 76 + </div> 77 + </section> 78 + ); 79 + }
+3
app/components/features/index.ts
··· 1 + export { FeatureCard } from "./feature-card"; 2 + export { FeaturesSection } from "./features-section"; 3 +
+46
app/components/footer/footer.tsx
··· 1 + import Link from "next/link"; 2 + import Image from "next/image"; 3 + import { Paragraph } from "@/components/paragraph"; 4 + import { prelaunch } from "@/lib/prelaunch"; 5 + 6 + export function Footer() { 7 + const year = new Date().getFullYear(); 8 + 9 + return ( 10 + <footer className="w-full border-t border-white/10 bg-slate-950/90"> 11 + <div className="mx-auto flex max-w-7xl flex-col gap-6 px-4 py-8 sm:flex-row sm:items-center sm:justify-between sm:px-6"> 12 + <div className="flex items-center gap-3"> 13 + <Image 14 + src="/logo.svg" 15 + alt="eny.space" 16 + width={32} 17 + height={32} 18 + className="shrink-0" 19 + /> 20 + <div className="flex flex-col"> 21 + <span className="text-sm font-semibold text-white">eny.space</span> 22 + <Paragraph className="text-xs text-white/60"> 23 + © {year} eny.space. All rights reserved. 24 + </Paragraph> 25 + </div> 26 + </div> 27 + 28 + <div className="flex flex-wrap items-center gap-4 text-xs text-white/60"> 29 + <nav className="flex flex-wrap items-center gap-4"> 30 + <Link href="/#features" className="hover:text-white"> 31 + Features 32 + </Link> 33 + {!prelaunch && ( 34 + <Link href="/#pricing" className="hover:text-white"> 35 + Pricing 36 + </Link> 37 + )} 38 + <Link href="/#faq" className="hover:text-white"> 39 + FAQ 40 + </Link> 41 + </nav> 42 + </div> 43 + </div> 44 + </footer> 45 + ); 46 + }
+2
app/components/footer/index.ts
··· 1 + export { Footer } from "./footer"; 2 +
+13
app/components/heading.tsx
··· 1 + import { cn } from "@/actions/lib/utils"; 2 + 3 + type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6"; 4 + 5 + interface HeadingProps { 6 + as?: HeadingLevel; 7 + children: React.ReactNode; 8 + className?: string; 9 + } 10 + 11 + export function Heading({ as: Tag = "h1", children, className }: HeadingProps) { 12 + return <Tag className={cn("font-heading", className)}>{children}</Tag>; 13 + }
+193
app/components/hero/hero-background.tsx
··· 1 + /* eslint-disable tailwindcss/no-custom-classname */ 2 + "use client"; 3 + 4 + import Image from "next/image"; 5 + import { motion, useScroll, useTransform } from "framer-motion"; 6 + 7 + export function HeroBackground({ 8 + showPlanets = true, 9 + }: { 10 + showPlanets?: boolean; 11 + }) { 12 + const { scrollYProgress } = useScroll(); 13 + 14 + // Parallax ratios (approximate 10%, 30%, 80%) 15 + const deepStarsY = useTransform(scrollYProgress, [0, 1], ["0%", "-10%"]); 16 + const midOrbsY = useTransform(scrollYProgress, [0, 1], ["0%", "-30%"]); 17 + const planetY = useTransform( 18 + scrollYProgress, 19 + [0, 0.6, 1], 20 + ["0%", "-48%", "-64%"], 21 + ); 22 + 23 + // "Camera angle" milestone – planets grow and shift between 0.4–0.6 24 + const planetScale = useTransform( 25 + scrollYProgress, 26 + [0, 0.4, 0.6, 1], 27 + [1, 1, 2, 2.4], 28 + ); 29 + const planetX = useTransform( 30 + scrollYProgress, 31 + [0, 0.4, 0.6, 1], 32 + ["0%", "0%", "-10%", "-14%"], 33 + ); 34 + const planetRotate = useTransform( 35 + scrollYProgress, 36 + [0, 0.5, 1], 37 + ["-16deg", "0deg", "16deg"], 38 + ); 39 + 40 + return ( 41 + <> 42 + {/* Base fixed gradient background */} 43 + <div 44 + className="pointer-events-none fixed inset-0 -z-20 bg-slate-950" 45 + aria-hidden 46 + > 47 + <div 48 + className="absolute inset-0 opacity-80" 49 + style={{ 50 + background: 51 + "radial-gradient(circle at 20% -10%, oklch(0.78 0.15 260 / 0.45) 0, transparent 55%)", 52 + }} 53 + /> 54 + <div 55 + className="absolute inset-0 opacity-[0.035] mix-blend-overlay" 56 + style={{ 57 + backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.4' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.9'/%3E%3C/svg%3E")`, 58 + }} 59 + /> 60 + </div> 61 + 62 + {/* LAYER 1 – Deep tiny stars */} 63 + <motion.div 64 + className="pointer-events-none fixed inset-0 -z-10" 65 + style={{ y: deepStarsY }} 66 + aria-hidden 67 + > 68 + <svg 69 + className="h-full w-full" 70 + viewBox="0 0 1440 900" 71 + preserveAspectRatio="xMidYMid slice" 72 + > 73 + <defs> 74 + <radialGradient id="starGradient" r="1"> 75 + <stop offset="0%" stopColor="white" stopOpacity="0.9" /> 76 + <stop offset="100%" stopColor="white" stopOpacity="0" /> 77 + </radialGradient> 78 + </defs> 79 + 80 + {Array.from({ length: 90 }).map((_, i) => { 81 + const radius = Math.random() * 1.3 + 0.4; 82 + const blur = i % 7 === 0 ? 1.5 : 0; 83 + return ( 84 + <circle 85 + key={i} 86 + cx={Math.random() * 1440} 87 + cy={Math.random() * 900} 88 + r={radius} 89 + fill="url(#starGradient)" 90 + opacity={0.5 + Math.random() * 0.4} 91 + style={{ 92 + filter: blur ? `blur(${blur}px)` : undefined, 93 + }} 94 + /> 95 + ); 96 + })} 97 + </svg> 98 + </motion.div> 99 + 100 + {/* LAYER 2 – Mid orbs / energy fields */} 101 + <motion.div 102 + className="pointer-events-none fixed inset-0 -z-5" 103 + style={{ y: midOrbsY }} 104 + aria-hidden 105 + > 106 + <div className="pointer-events-none fixed inset-0 -z-5 [mask-image:linear-gradient(to_bottom,transparent,black_14%,black_86%,transparent)] [-webkit-mask-image:linear-gradient(to_bottom,transparent,black_14%,black_86%,transparent)]"> 107 + <div className="absolute left-[12%] top-[18%] h-40 w-40 rounded-full bg-sky-400/10 blur-3xl shadow-[0_0_120px_rgba(56,189,248,0.55)]" /> 108 + <div className="absolute right-[10%] top-[35%] h-56 w-56 rounded-full bg-fuchsia-400/15 blur-3xl shadow-[0_0_160px_rgba(244,114,182,0.65)]" /> 109 + <div className="absolute left-[30%] bottom-[20%] h-48 w-64 rounded-[999px] bg-indigo-400/10 blur-[80px] shadow-[0_0_180px_rgba(129,140,248,0.6)]" /> 110 + <div className="absolute right-[26%] bottom-[8%] h-32 w-32 rounded-full bg-amber-300/15 blur-3xl shadow-[0_0_130px_rgba(252,211,77,0.7)]" /> 111 + 112 + {/* Soft vignette */} 113 + <div className="pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_center,transparent_0,transparent_55%,rgba(0,0,0,0.55)_100%)]" /> 114 + </div> 115 + </motion.div> 116 + 117 + {showPlanets && ( 118 + <> 119 + {/* LAYER 3 – Foreground planet (Jupiter image) */} 120 + <motion.div 121 + className="pointer-events-none fixed inset-0 -z-[1]" 122 + style={{ 123 + y: planetY, 124 + scale: planetScale, 125 + x: planetX, 126 + rotate: planetRotate, 127 + }} 128 + aria-hidden 129 + > 130 + <div className="absolute bottom-[-22%] right-[2%] h-[360px] w-[360px] overflow-hidden rounded-full opacity-80"> 131 + <Image 132 + src="/jupiter2.png" 133 + alt="Gas giant planet" 134 + fill 135 + priority 136 + className="object-cover object-center" 137 + /> 138 + </div> 139 + </motion.div> 140 + 141 + {/* LAYER 3b – Secondary planets (Earth, Mars, Venus, Neptune images) */} 142 + <motion.div 143 + className="pointer-events-none fixed inset-0 -z-[1]" 144 + style={{ 145 + y: planetY, 146 + scale: planetScale, 147 + x: planetX, 148 + rotate: planetRotate, 149 + }} 150 + aria-hidden 151 + > 152 + <div className="absolute bottom-[10%] left-[6%] h-[220px] w-[220px] overflow-hidden rounded-full"> 153 + <Image 154 + src="/earth.png" 155 + alt="Blue planet" 156 + fill 157 + priority={false} 158 + className="object-cover object-center" 159 + /> 160 + </div> 161 + <div className="absolute top-[54%] right-[30%] h-[120px] w-[120px] overflow-hidden rounded-full opacity-80"> 162 + <Image 163 + src="/mars.png" 164 + alt="Red planet" 165 + fill 166 + priority={false} 167 + className="object-cover object-center" 168 + /> 169 + </div> 170 + <div className="absolute top-[50%] right-[20%] h-[70px] w-[100px] overflow-hidden rounded-full opacity-80"> 171 + <Image 172 + src="/venus.png" 173 + alt="Yellow planet" 174 + fill 175 + priority={false} 176 + className="object-cover object-center" 177 + /> 178 + </div> 179 + <div className="absolute top-[30%] left-[35%] h-[60px] w-[60px] overflow-hidden rounded-full opacity-80"> 180 + <Image 181 + src="/neptune.png" 182 + alt="Blue planet" 183 + fill 184 + priority={false} 185 + className="object-cover object-center" 186 + /> 187 + </div> 188 + </motion.div> 189 + </> 190 + )} 191 + </> 192 + ); 193 + }
+30
app/components/hero/hero-left.tsx
··· 1 + import { ButtonLink } from "@/components/button-link"; 2 + import { Heading } from "@/components/heading"; 3 + import { Paragraph } from "@/components/paragraph"; 4 + import { ArrowUpRightIcon } from "lucide-react"; 5 + 6 + export function HeroLeft() { 7 + return ( 8 + <div className="flex max-w-xl flex-col gap-6"> 9 + <Heading 10 + as="h1" 11 + className="font-heading text-4xl leading-tight tracking-tight text-white sm:text-5xl md:text-6xl" 12 + > 13 + Managed PDS hosting, launching soon. 14 + </Heading> 15 + <Paragraph className="text-lg text-white/90 sm:text-xl"> 16 + eny.space will let you run your own Personal Data Server with a real UI. 17 + For now, sign up and we&apos;ll notify you when packages go live. 18 + </Paragraph> 19 + <div className="flex flex-wrap gap-3"> 20 + <ButtonLink 21 + href="/signup" 22 + className="border border-white/80 bg-transparent uppercase tracking-wide text-white hover:bg-white/10 hover:border-white focus-visible:ring-white/50" 23 + endIcon={<ArrowUpRightIcon className="size-4" aria-hidden />} 24 + > 25 + Get started 26 + </ButtonLink> 27 + </div> 28 + </div> 29 + ); 30 + }
+35
app/components/hero/hero-right.tsx
··· 1 + import Link from "next/link"; 2 + import { ChevronDownIcon } from "lucide-react"; 3 + import { prelaunch } from "@/lib/prelaunch"; 4 + 5 + const navItems = [ 6 + { label: "Key features", href: "/#features" }, 7 + ...(!prelaunch ? [{ label: "Pricing", href: "/#pricing" }] : []), 8 + { label: "FAQs", href: "/#faq" }, 9 + ]; 10 + 11 + export function HeroRight() { 12 + return ( 13 + <nav className="flex flex-col gap-1"> 14 + <Link 15 + href="/#discover" 16 + className="border-b border-white/60 pb-1 text-sm font-medium uppercase tracking-wide text-white hover:border-white hover:text-white" 17 + > 18 + /// Discover eny.space 19 + </Link> 20 + <ul className="mt-4 flex flex-col gap-3"> 21 + {navItems.map((item) => ( 22 + <li key={item.href}> 23 + <Link 24 + href={item.href} 25 + className="inline-flex items-center gap-2 text-sm font-medium uppercase tracking-wide text-white/90 transition-colors hover:text-white" 26 + > 27 + {item.label} 28 + <ChevronDownIcon className="size-4" aria-hidden /> 29 + </Link> 30 + </li> 31 + ))} 32 + </ul> 33 + </nav> 34 + ); 35 + }
+27
app/components/hero/hero.tsx
··· 1 + import Image from "next/image"; 2 + import { HeroLeft } from "./hero-left"; 3 + import { HeroRight } from "./hero-right"; 4 + 5 + export function Hero() { 6 + return ( 7 + <section className="relative flex min-h-[calc(100vh-3.5rem)] w-full flex-col justify-end overflow-hidden px-4 pb-12 pt-16 sm:px-6 sm:pt-24"> 8 + {/* Centered hero logo, moved higher with -mt-24 (negative margin top) */} 9 + <div 10 + className="pointer-events-none absolute inset-0 flex items-center justify-center opacity-15 -mt-24" 11 + style={{ zIndex: 1 }} 12 + > 13 + <Image 14 + src="/logo.svg" 15 + alt="eny.space logo" 16 + width={520} 17 + height={520} 18 + className="shrink-0" 19 + /> 20 + </div> 21 + <div className="mx-auto grid w-full max-w-7xl gap-12 md:grid-cols-[1fr_auto] md:items-center md:gap-16"> 22 + <HeroLeft /> 23 + <HeroRight /> 24 + </div> 25 + </section> 26 + ); 27 + }
+4
app/components/hero/index.ts
··· 1 + export { Hero } from "./hero"; 2 + export { HeroBackground } from "./hero-background"; 3 + export { HeroLeft } from "./hero-left"; 4 + export { HeroRight } from "./hero-right";
+1
app/components/logo-bar/index.ts
··· 1 + export { LogoBar } from "./logo-bar";
+184
app/components/logo-bar/logo-bar.tsx
··· 1 + "use client"; 2 + 3 + import { useMemo } from "react"; 4 + import Link from "next/link"; 5 + import { Paragraph } from "@/components/paragraph"; 6 + 7 + const ATMOSPHERE_APPS: { label: string; href?: string; icon: string }[] = [ 8 + { 9 + label: "Anisota", 10 + href: "https://anisota.net", 11 + icon: "/atmosphere-icons/logo-anisota.svg", 12 + }, 13 + { 14 + label: "Blacksky", 15 + href: "https://blackskyweb.xyz", 16 + icon: "/atmosphere-icons/logo-blacksky.svg", 17 + }, 18 + { 19 + label: "Blento", 20 + href: "https://blento.app", 21 + icon: "/atmosphere-icons/logo-blento.svg", 22 + }, 23 + { 24 + label: "Bluesky", 25 + href: "https://bsky.app", 26 + icon: "/atmosphere-icons/logo-bluesky.svg", 27 + }, 28 + { 29 + label: "Bookhive", 30 + href: "https://bookhive.buzz", 31 + icon: "/atmosphere-icons/logo-bookhive.svg", 32 + }, 33 + { 34 + label: "Grain", 35 + href: "https://grain.social", 36 + icon: "/atmosphere-icons/logo-grain.svg", 37 + }, 38 + { 39 + label: "Graze", 40 + href: "https://graze.social", 41 + icon: "/atmosphere-icons/logo-graze.svg", 42 + }, 43 + { 44 + label: "Leaflet", 45 + href: "https://leaflet.pub", 46 + icon: "/atmosphere-icons/logo-leaflet.svg", 47 + }, 48 + { 49 + label: "Margin", 50 + href: "https://margin.at/", 51 + icon: "/atmosphere-icons/logo-margin.svg", 52 + }, 53 + { 54 + label: "Offprint", 55 + href: "https://offprint.app", 56 + icon: "/atmosphere-icons/logo-offprint.svg", 57 + }, 58 + { 59 + label: "Pckt", 60 + href: "https://pckt.blog", 61 + icon: "/atmosphere-icons/logo-pckt.svg", 62 + }, 63 + { 64 + label: "PDSls", 65 + href: "https://pdsls.dev", 66 + icon: "/atmosphere-icons/logo-pdsls.svg", 67 + }, 68 + { 69 + label: "Plyr.fm", 70 + href: "https://plyr.fm", 71 + icon: "/atmosphere-icons/logo-plyr.fm.svg", 72 + }, 73 + { 74 + label: "Popfeed", 75 + href: "https://popfeed.social", 76 + icon: "/atmosphere-icons/logo-popfeed.svg", 77 + }, 78 + { 79 + label: "Roomy", 80 + href: "https://a.roomy.space/", 81 + icon: "/atmosphere-icons/logo-roomy.svg", 82 + }, 83 + { 84 + label: "Semble", 85 + href: "https://semble.so/", 86 + icon: "/atmosphere-icons/logo-semble.svg", 87 + }, 88 + { 89 + label: "Sifa.id", 90 + href: "https://sifa.id", 91 + icon: "/atmosphere-icons/logo-sifa%20id.svg", 92 + }, 93 + { 94 + label: "Sill", 95 + href: "https://sill.social", 96 + icon: "/atmosphere-icons/logo-sill.svg", 97 + }, 98 + { 99 + label: "Spark", 100 + href: "https://sprk.so/", 101 + icon: "/atmosphere-icons/logo-spark.svg", 102 + }, 103 + { 104 + label: "Surf", 105 + href: "https://surf.social", 106 + icon: "/atmosphere-icons/logo-surf.svg", 107 + }, 108 + { 109 + label: "Tangled", 110 + href: "https://tangled.org", 111 + icon: "/atmosphere-icons/logo-tangled.svg", 112 + }, 113 + ]; 114 + 115 + function LogoBarItem({ item }: { item: (typeof ATMOSPHERE_APPS)[number] }) { 116 + const inner = ( 117 + <> 118 + <span className="flex size-10 shrink-0 items-center justify-center rounded-lg bg-white/15"> 119 + {/* eslint-disable-next-line @next/next/no-img-element */} 120 + <img src={item.icon} alt="" className="size-6" aria-hidden /> 121 + </span> 122 + {item.label} 123 + </> 124 + ); 125 + 126 + if (item.href) { 127 + return ( 128 + <Link 129 + href={item.href} 130 + target="_blank" 131 + rel="noopener noreferrer" 132 + className="flex shrink-0 items-center gap-3 text-base font-medium text-white/90 transition-colors hover:text-white" 133 + > 134 + {inner} 135 + </Link> 136 + ); 137 + } 138 + 139 + return ( 140 + <span className="flex shrink-0 items-center gap-3 text-base font-medium text-white/50 cursor-default"> 141 + {inner} 142 + </span> 143 + ); 144 + } 145 + 146 + function LogoBarScroll() { 147 + const shuffled = useMemo( 148 + () => [...ATMOSPHERE_APPS].sort(() => Math.random() - 0.5), 149 + [] 150 + ); 151 + 152 + return ( 153 + <div className="relative w-full overflow-hidden py-8 [mask-image:linear-gradient(to_right,transparent,black_12%,black_88%,transparent)]"> 154 + <div className="flex w-max animate-marquee items-center [transform:translateZ(0)]"> 155 + {["a", "b"].map((blockId) => ( 156 + <div 157 + key={blockId} 158 + className="flex shrink-0 items-center gap-16 whitespace-nowrap" 159 + > 160 + {shuffled.map((item, i) => ( 161 + <LogoBarItem key={`${blockId}-${i}`} item={item} /> 162 + ))} 163 + <span className="w-16 shrink-0" aria-hidden /> 164 + </div> 165 + ))} 166 + </div> 167 + </div> 168 + ); 169 + } 170 + 171 + export function LogoBar() { 172 + return ( 173 + <section className="w-full"> 174 + <div className="mx-auto max-w-7xl px-4 py-10 sm:px-6"> 175 + <Paragraph className="mx-auto max-w-2xl text-center text-base text-white/60"> 176 + Built for AT Protocol and Bluesky power users who want to see and 177 + manage their Personal Data Server through a modern interface instead 178 + of raw APIs and command‑line tools. 179 + </Paragraph> 180 + <LogoBarScroll /> 181 + </div> 182 + </section> 183 + ); 184 + }
+10
app/components/paragraph.tsx
··· 1 + import { cn } from "@/actions/lib/utils"; 2 + 3 + interface ParagraphProps { 4 + children: React.ReactNode; 5 + className?: string; 6 + } 7 + 8 + export function Paragraph({ children, className }: ParagraphProps) { 9 + return <p className={cn(className)}>{children}</p>; 10 + }
+1
app/components/prelaunch/index.ts
··· 1 + export { PrelaunchSection } from "./prelaunch-section";
+37
app/components/prelaunch/prelaunch-section.tsx
··· 1 + import { Heading } from "@/components/heading"; 2 + import { Paragraph } from "@/components/paragraph"; 3 + import { prelaunch } from "@/lib/prelaunch"; 4 + import { ButtonLink } from "@/components/button-link"; 5 + import { ArrowRightIcon } from "lucide-react"; 6 + 7 + export async function PrelaunchSection() { 8 + if (!prelaunch) return null; 9 + 10 + return ( 11 + <section 12 + id="prelaunch" 13 + className="relative w-full px-4 py-20 sm:px-6 sm:py-24" 14 + > 15 + <div className="mx-auto max-w-5xl text-center"> 16 + <Heading 17 + as="h2" 18 + className="text-2xl font-semibold tracking-tight text-white sm:text-3xl md:text-4xl" 19 + > 20 + Can't wait for the launch? 21 + </Heading> 22 + <Paragraph className="mt-4 text-sm text-white/70 sm:text-base"> 23 + Sign up for early access and we will update you the moment our service 24 + is available to the public. 25 + </Paragraph> 26 + 27 + <ButtonLink 28 + href="/signup" 29 + className="mt-6 px-6 uppercase tracking-wide text-neutral-950 shadow-[0_0_40px_rgba(232,121,249,0.45)] bg-fuchsia-400 hover:bg-fuchsia-300" 30 + endIcon={<ArrowRightIcon className="size-4" aria-hidden />} 31 + > 32 + Sign up 33 + </ButtonLink> 34 + </div> 35 + </section> 36 + ); 37 + }
+2
app/components/pricing/index.ts
··· 1 + export { PricingSection } from "./pricing-section"; 2 +
+223
app/components/pricing/pricing-section.tsx
··· 1 + import { 2 + Card, 3 + CardContent, 4 + CardHeader, 5 + CardTitle, 6 + } from "@/actions/components/ui/card"; 7 + import { ButtonLink } from "@/components/button-link"; 8 + import { Heading } from "@/components/heading"; 9 + import { Paragraph } from "@/components/paragraph"; 10 + import { prelaunch } from "@/lib/prelaunch"; 11 + import { getStripePlanAmounts, type PlanKey } from "@/lib/stripe-plans"; 12 + 13 + type PricingPlan = { 14 + key: string; 15 + name: string; 16 + price: string; 17 + period: string; 18 + badge?: string; 19 + description: string; 20 + highlight?: boolean; 21 + pdsDiskSizeGb: number; 22 + features: string[]; 23 + launchOnly?: boolean; 24 + }; 25 + 26 + const PLANS: PricingPlan[] = [ 27 + { 28 + key: "personal", 29 + name: "Personal", 30 + price: "$19", 31 + period: "per month", 32 + description: "Perfect for small projects.", 33 + pdsDiskSizeGb: 10, 34 + features: [ 35 + "1 GB storage", 36 + "5 app deployments", 37 + "Basic security protocols", 38 + "24/7 support access", 39 + ], 40 + }, 41 + { 42 + key: "community", 43 + name: "Community", 44 + price: "$49", 45 + period: "per month", 46 + badge: "Popular", 47 + description: "Scale without limits.", 48 + highlight: true, 49 + pdsDiskSizeGb: 50, 50 + features: [ 51 + "10 GB storage", 52 + "Unlimited app deployments", 53 + "Advanced security and encryption", 54 + "Priority support with dedicated manager", 55 + ], 56 + }, 57 + { 58 + key: "business", 59 + name: "Business", 60 + price: "$99", 61 + period: "per month", 62 + description: "Enterprise‑level performance.", 63 + pdsDiskSizeGb: 200, 64 + launchOnly: true, 65 + features: [ 66 + "Unlimited storage", 67 + "Custom domain support", 68 + "Dedicated node hosting", 69 + "Real‑time monitoring and analytics", 70 + "Premium 24/7 support with SLA", 71 + ], 72 + }, 73 + ]; 74 + 75 + function formatStripePrice(unitAmount: number | null, currency: string | null) { 76 + if (!unitAmount || !currency) return null; 77 + 78 + const normalized = currency.toLowerCase(); 79 + const zeroDecimalCurrencies = new Set([ 80 + "jpy", 81 + "krw", 82 + "clp", 83 + "vnd", 84 + "idr", 85 + "huf", 86 + "pyg", 87 + ]); 88 + const decimals = zeroDecimalCurrencies.has(normalized) ? 0 : 2; 89 + const major = unitAmount / 10 ** decimals; 90 + 91 + try { 92 + return new Intl.NumberFormat(undefined, { 93 + style: "currency", 94 + currency: normalized.toUpperCase(), 95 + maximumFractionDigits: decimals, 96 + }).format(major); 97 + } catch { 98 + return null; 99 + } 100 + } 101 + 102 + export async function PricingSection() { 103 + // Hide the pricing block entirely during prelaunch mode. 104 + // This keeps the "prelaunch vs launch" behavior controlled by one global flag. 105 + if (prelaunch) return null; 106 + 107 + const stripeAmounts = await getStripePlanAmounts(); 108 + 109 + return ( 110 + <section 111 + id="pricing" 112 + className="relative w-full px-4 py-20 sm:px-6 sm:py-24" 113 + > 114 + <div className="mx-auto max-w-5xl text-center"> 115 + <Heading 116 + as="h2" 117 + className="text-2xl font-semibold tracking-tight text-white sm:text-3xl md:text-4xl" 118 + > 119 + Simple Pricing for Individuals, Developers and Communities. 120 + </Heading> 121 + <Paragraph className="mt-4 text-sm text-white/70 sm:text-base"> 122 + Whether you're an indie developer, a power user, or running a 123 + community. 124 + <br /> 125 + Pick a plan that fits and own your data without managing 126 + infrastructure. 127 + </Paragraph> 128 + </div> 129 + 130 + <div className="mx-auto mt-12 grid max-w-6xl gap-6 md:grid-cols-3"> 131 + {PLANS.map((plan) => 132 + (() => { 133 + const params = new URLSearchParams({ 134 + auto_checkout: "1", 135 + pds_plan: plan.key, 136 + pds_disksize_gb: String(plan.pdsDiskSizeGb), 137 + }); 138 + const signupHref = `/signup?${params.toString()}`; 139 + 140 + return ( 141 + <Card 142 + key={plan.name} 143 + className={[ 144 + "flex h-full flex-col justify-between rounded-3xl border-none bg-gradient-to-b from-slate-900/65 to-slate-950/75 p-6 text-white shadow-xl/30", 145 + plan.highlight 146 + ? "relative bg-gradient-to-b from-fuchsia-500/65 via-fuchsia-500/55 to-fuchsia-600/70 text-white shadow-[0_0_36px_rgba(232,121,249,0.3)]" 147 + : "", 148 + ] 149 + .filter(Boolean) 150 + .join(" ")} 151 + > 152 + <CardHeader className="flex flex-col gap-2 px-0"> 153 + <div className="flex items-center justify-between gap-3"> 154 + <CardTitle className="text-sm font-semibold uppercase tracking-wide text-white"> 155 + {plan.name} 156 + </CardTitle> 157 + {plan.badge ? ( 158 + <span className="absolute right-[7%] rounded-full bg-neutral-900/80 px-3 py-1 text-xs font-medium uppercase tracking-wide text-fuchsia-300 md:text-[11px]"> 159 + {plan.badge} 160 + </span> 161 + ) : null} 162 + </div> 163 + <div className="mt-4 flex items-baseline gap-2"> 164 + <span className="text-4xl font-semibold sm:text-5xl text-white"> 165 + ?€ 166 + </span> 167 + <span className="text-sm font-medium opacity-80 text-white"> 168 + {plan.period} 169 + </span> 170 + </div> 171 + <Paragraph 172 + className={["mt-3 text-sm text-white/70"].join(" ")} 173 + > 174 + {plan.description} 175 + </Paragraph> 176 + </CardHeader> 177 + 178 + <CardContent className="mt-6 flex flex-1 flex-col gap-6 px-0"> 179 + <ButtonLink 180 + href={signupHref} 181 + className={[ 182 + "w-full rounded-full px-4 py-3 text-center text-sm font-semibold uppercase tracking-wide transition", 183 + plan.highlight 184 + ? "bg-neutral-950 text-fuchsia-200 hover:bg-neutral-900" 185 + : "bg-white text-neutral-950 hover:bg-neutral-200", 186 + ].join(" ")} 187 + > 188 + Get started 189 + </ButtonLink> 190 + 191 + <div className="pt-2 text-left"> 192 + <Paragraph 193 + className={[ 194 + "text-xs font-semibold uppercase tracking-[0.18em] text-white/60", 195 + ].join(" ")} 196 + > 197 + Key features on {plan.name.split(" ")[0]} 198 + </Paragraph> 199 + <ul className="mt-4 space-y-2 text-sm"> 200 + {plan.features.map((feature) => ( 201 + <li 202 + key={feature} 203 + className={[ 204 + "flex items-start gap-2 text-white/75", 205 + ].join(" ")} 206 + > 207 + <div className="inline-flex items-center gap-2"> 208 + <span className="inline-block size-1.5 rounded-full bg-fuchsia-400" /> 209 + <span>{feature}</span> 210 + </div> 211 + </li> 212 + ))} 213 + </ul> 214 + </div> 215 + </CardContent> 216 + </Card> 217 + ); 218 + })() 219 + )} 220 + </div> 221 + </section> 222 + ); 223 + }
+12
app/components/site-background.tsx
··· 1 + "use client"; 2 + 3 + import { usePathname } from "next/navigation"; 4 + import { HeroBackground } from "@/components/hero"; 5 + 6 + export function SiteBackground() { 7 + const pathname = usePathname(); 8 + const isLanding = pathname === "/"; 9 + 10 + return <HeroBackground showPlanets={isLanding} />; 11 + } 12 +
+2
app/components/site-header/index.ts
··· 1 + export { SiteHeader } from "./site-header"; 2 +
+49
app/components/site-header/mobile-menu.tsx
··· 1 + import Link from "next/link"; 2 + import type { User } from "@supabase/supabase-js"; 3 + 4 + import { signOut } from "@/actions/auth"; 5 + 6 + interface MobileMenuProps { 7 + user: User | null; 8 + open: boolean; 9 + onClose: () => void; 10 + } 11 + 12 + const mobileLinkClass = 13 + "block text-left text-base font-medium text-white/90 hover:text-white"; 14 + 15 + export function MobileMenu({ user, open, onClose }: MobileMenuProps) { 16 + if (!open) return null; 17 + 18 + return ( 19 + <div className="fixed right-3 top-14 z-40 max-h-[calc(100vh-3.5rem)] w-1/3 overflow-y-auto rounded-xl border border-fuchsia-300/30 bg-slate-900/75 px-4 pb-4 pt-3 shadow-[0_0_30px_rgba(232,121,249,0.2)] backdrop-blur-md md:hidden"> 20 + <nav className="flex flex-col gap-2"> 21 + {/* navigation intentionally hidden; CTA-only header */} 22 + </nav> 23 + 24 + <div className="mt-3 flex flex-col gap-2"> 25 + {user ? ( 26 + <> 27 + <Link href="/dashboard" onClick={onClose} className={mobileLinkClass}> 28 + Dashboard 29 + </Link> 30 + <form action={signOut}> 31 + <button type="submit" className={mobileLinkClass}> 32 + Sign out 33 + </button> 34 + </form> 35 + </> 36 + ) : ( 37 + <> 38 + <Link href="/login" onClick={onClose} className={mobileLinkClass}> 39 + Login 40 + </Link> 41 + <Link href="/signup" onClick={onClose} className={mobileLinkClass}> 42 + Get started 43 + </Link> 44 + </> 45 + )} 46 + </div> 47 + </div> 48 + ); 49 + }
+167
app/components/site-header/site-header.tsx
··· 1 + "use client"; 2 + 3 + import { useState, useEffect } from "react"; 4 + import Link from "next/link"; 5 + import Image from "next/image"; 6 + import { signOut } from "@/actions/auth"; 7 + import { Button } from "@/actions/components/ui/button"; 8 + import { ArrowUpRightIcon, MenuIcon, XIcon } from "lucide-react"; 9 + import type { User } from "@supabase/supabase-js"; 10 + import { MobileMenu } from "./mobile-menu"; 11 + 12 + interface SiteHeaderProps { 13 + user: User | null; 14 + } 15 + 16 + const headerCtaClass = 17 + "inline-flex items-center gap-1.5 rounded-full bg-white px-4 text-xs font-medium uppercase tracking-wide text-neutral-950 cursor-pointer hover:bg-primary/80"; 18 + 19 + export function SiteHeader({ user }: SiteHeaderProps) { 20 + const [mobileOpen, setMobileOpen] = useState(false); 21 + const [displayText, setDisplayText] = useState("."); 22 + const [isTyping, setIsTyping] = useState(false); 23 + 24 + useEffect(() => { 25 + let dotCycle = 1; 26 + let repeatCount = 0; 27 + const fullWord = "space"; 28 + let charIndex = 0; 29 + 30 + const DOT_SPEED = 400; 31 + const CURSOR_BLINK_SPEED = 500; 32 + const TYPE_SPEED = 200; 33 + 34 + const dotInterval = setInterval(() => { 35 + if (dotCycle < 3) { 36 + dotCycle++; 37 + } else { 38 + dotCycle = 1; 39 + repeatCount++; 40 + } 41 + 42 + if (repeatCount < 2) { 43 + setDisplayText(".".repeat(dotCycle)); 44 + } else { 45 + clearInterval(dotInterval); 46 + setDisplayText("."); 47 + 48 + let blinks = 0; 49 + const blinkInterval = setInterval(() => { 50 + setIsTyping((prev) => !prev); 51 + blinks++; 52 + 53 + if (blinks === 4) { 54 + clearInterval(blinkInterval); 55 + setIsTyping(true); 56 + 57 + const typeInterval = setInterval(() => { 58 + setDisplayText("." + fullWord.slice(0, charIndex + 1)); 59 + charIndex++; 60 + 61 + if (charIndex === fullWord.length) { 62 + clearInterval(typeInterval); 63 + setTimeout(() => setIsTyping(false), 400); 64 + } 65 + }, TYPE_SPEED); 66 + } 67 + }, CURSOR_BLINK_SPEED); 68 + } 69 + }, DOT_SPEED); 70 + 71 + return () => clearInterval(dotInterval); 72 + }, []); 73 + 74 + return ( 75 + <header className="sticky top-0 z-50 w-full border-b border-white/10 bg-slate-950/85"> 76 + <div className="mx-auto flex h-14 max-w-7xl items-center justify-between gap-4 px-4 sm:px-6"> 77 + <Link 78 + href="/" 79 + className="flex items-center gap-2 text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/30" 80 + onClick={() => setMobileOpen(false)} 81 + > 82 + <Image 83 + src="/logo.svg" 84 + alt="" 85 + width={32} 86 + height={32} 87 + className="shrink-0" 88 + /> 89 + 90 + {/* THE LAYOUT FIX IS HERE */} 91 + <div className="relative text-lg flex items-center tabular-nums"> 92 + {/* Hidden ghost text that reserves the full width of "eny.space" */} 93 + <span 94 + className="invisible pointer-events-none select-none" 95 + aria-hidden="true" 96 + > 97 + eny.space 98 + </span> 99 + 100 + {/* The actual visible animated text */} 101 + <div className="absolute left-0 flex items-center whitespace-nowrap"> 102 + <span>eny{displayText}</span> 103 + <span 104 + className={`ml-0.5 transition-opacity duration-100 ${isTyping ? "opacity-100" : "opacity-0"}`} 105 + > 106 + _ 107 + </span> 108 + </div> 109 + </div> 110 + </Link> 111 + 112 + <div className="hidden items-center gap-2 md:flex"> 113 + {!user ? ( 114 + <Button 115 + size="default" 116 + className={headerCtaClass} 117 + asChild 118 + > 119 + <Link href="/signup"> 120 + Get started 121 + <ArrowUpRightIcon className="ml-1 size-3.5" /> 122 + </Link> 123 + </Button> 124 + ) : ( 125 + <> 126 + <Button size="default" className={headerCtaClass} asChild> 127 + <Link href="/dashboard"> 128 + Dashboard 129 + <ArrowUpRightIcon className="ml-1 size-3.5" /> 130 + </Link> 131 + </Button> 132 + <form action={signOut}> 133 + <Button 134 + type="submit" 135 + size="default" 136 + className={headerCtaClass} 137 + > 138 + Sign out 139 + <ArrowUpRightIcon className="ml-0.5 size-3.5" /> 140 + </Button> 141 + </form> 142 + </> 143 + )} 144 + </div> 145 + 146 + <button 147 + type="button" 148 + aria-label="Toggle navigation" 149 + className="inline-flex h-9 w-9 cursor-pointer items-center justify-center text-white md:hidden" 150 + onClick={() => setMobileOpen((open) => !open)} 151 + > 152 + {mobileOpen ? ( 153 + <XIcon className="size-5" aria-hidden /> 154 + ) : ( 155 + <MenuIcon className="size-5" aria-hidden /> 156 + )} 157 + </button> 158 + </div> 159 + 160 + <MobileMenu 161 + user={user} 162 + open={mobileOpen} 163 + onClose={() => setMobileOpen(false)} 164 + /> 165 + </header> 166 + ); 167 + }
+2
app/components/testimonials/index.ts
··· 1 + export { TestimonialsSection } from "./testimonials-section"; 2 +
+108
app/components/testimonials/testimonials-section.tsx
··· 1 + import { Card, CardHeader, CardFooter } from "@/actions/components/ui/card"; 2 + import { Heading } from "@/components/heading"; 3 + import { Paragraph } from "@/components/paragraph"; 4 + import { SparklesIcon } from "lucide-react"; 5 + 6 + type Testimonial = { 7 + quote: string; 8 + name: string; 9 + role: string; 10 + company: string; 11 + }; 12 + 13 + const TESTIMONIALS: Testimonial[] = [ 14 + { 15 + quote: 16 + "Switching to eny.space was the best decision for our DeFi platform. Uptime and performance are unmatched.", 17 + name: "Isagi Yoichi", 18 + role: "Chief Technology Officer", 19 + company: "3Portals", 20 + }, 21 + { 22 + quote: 23 + "We can finally deploy smart contracts confidently without worrying about central servers failing.", 24 + name: "Oliver Aiku", 25 + role: "Digital Community Lead", 26 + company: "Acme Corp", 27 + }, 28 + { 29 + quote: 30 + "The migration was seamless and our team now ships faster than ever, with full visibility into our data.", 31 + name: "Alex Rivera", 32 + role: "Head of Engineering", 33 + company: "Nebula Labs", 34 + }, 35 + ]; 36 + 37 + function TestimonialCard({ testimonial }: { testimonial: Testimonial }) { 38 + return ( 39 + <Card className="flex h-full min-w-[280px] max-w-sm flex-col justify-between rounded-3xl border-none bg-gradient-to-b from-neutral-900/80 to-neutral-950/90 p-6 text-white/90 shadow-xl/30 whitespace-normal"> 40 + <CardHeader className="px-0"> 41 + <Paragraph className="text-sm text-white/80"> 42 + {testimonial.quote} 43 + </Paragraph> 44 + </CardHeader> 45 + 46 + <CardFooter className="mt-4 items-center justify-between gap-4 border-t border-white/10 bg-transparent px-0 pt-4"> 47 + <div className="flex items-center gap-3"> 48 + <div className="flex size-9 items-center justify-center rounded-full bg-white/10 text-xs font-semibold uppercase tracking-wide text-white/90"> 49 + {testimonial.name 50 + .split(" ") 51 + .map((part) => part[0]) 52 + .join("")} 53 + </div> 54 + <div className="flex flex-col"> 55 + <span className="text-sm font-medium text-white"> 56 + {testimonial.name} 57 + </span> 58 + <span className="text-xs text-white/60">{testimonial.role}</span> 59 + </div> 60 + </div> 61 + <div className="flex items-center gap-2 text-sm font-semibold text-white/85"> 62 + <span className="flex size-6 items-center justify-center rounded-full bg-fuchsia-400/15"> 63 + <SparklesIcon className="size-3.5 text-fuchsia-300" aria-hidden /> 64 + </span> 65 + <span>{testimonial.company}</span> 66 + </div> 67 + </CardFooter> 68 + </Card> 69 + ); 70 + } 71 + 72 + export function TestimonialsSection() { 73 + return ( 74 + <section className="relative w-full px-4 py-20 sm:px-6 sm:py-24"> 75 + <div className="mx-auto max-w-5xl text-center"> 76 + <Heading 77 + as="h2" 78 + className="text-2xl font-semibold tracking-tight text-white sm:text-3xl md:text-4xl" 79 + > 80 + Trusted by Innovators Worldwide. 81 + </Heading> 82 + <Paragraph className="mt-4 text-sm text-white/70 sm:text-base"> 83 + Hear first-hand from our incredible community of customers. 84 + </Paragraph> 85 + </div> 86 + 87 + <div className="mx-auto mt-12 max-w-6xl"> 88 + <div className="relative w-full overflow-hidden pt-4 pb-8 [mask-image:linear-gradient(to_right,transparent,black_10%,black_90%,transparent)]"> 89 + <div className="flex w-max animate-marquee items-stretch gap-6 [transform:translateZ(0)]"> 90 + {["a", "b"].map((blockId) => ( 91 + <div 92 + key={blockId} 93 + className="flex shrink-0 items-stretch gap-6 whitespace-nowrap" 94 + > 95 + {TESTIMONIALS.map((testimonial) => ( 96 + <TestimonialCard 97 + key={`${blockId}-${testimonial.name}`} 98 + testimonial={testimonial} 99 + /> 100 + ))} 101 + </div> 102 + ))} 103 + </div> 104 + </div> 105 + </div> 106 + </section> 107 + ); 108 + }
+289
app/dashboard/atproto-test-client.tsx
··· 1 + "use client"; 2 + 3 + import { useEffect, useMemo, useState } from "react"; 4 + import { Heading } from "@/components/heading"; 5 + import { Paragraph } from "@/components/paragraph"; 6 + import { Button } from "@/actions/components/ui/button"; 7 + 8 + type ServiceResponse = { 9 + encrypted_config?: { 10 + hostname?: string; 11 + }; 12 + state?: number | string; 13 + }; 14 + 15 + function redactJwt(token: string | undefined) { 16 + if (!token) return ""; 17 + if (token.length <= 20) return token; 18 + return `${token.slice(0, 15)}...${token.slice(-10)}`; 19 + } 20 + 21 + function stripScheme(hostname?: string) { 22 + if (!hostname) return ""; 23 + return hostname.replace(/^https?:\/\//i, "").replace(/\/.*$/, ""); 24 + } 25 + 26 + export function AtprotoTestClient() { 27 + const [pdsHost, setPdsHost] = useState<string>(""); 28 + const [pdsState, setPdsState] = useState<number | string | null>(null); 29 + const [inviteCode, setInviteCode] = useState<string>(""); 30 + 31 + const [email, setEmail] = useState<string>(""); 32 + const [handle, setHandle] = useState<string>(""); 33 + const [newPassword, setNewPassword] = useState<string>(""); 34 + 35 + const [sessionIdentifier, setSessionIdentifier] = useState<string>(""); 36 + const [sessionPassword, setSessionPassword] = useState<string>(""); 37 + 38 + const [loading, setLoading] = useState(false); 39 + const [output, setOutput] = useState<any>(null); 40 + const [error, setError] = useState<string | null>(null); 41 + 42 + const pdsBareHost = useMemo(() => stripScheme(pdsHost), [pdsHost]); 43 + const pdsStateNum = useMemo(() => { 44 + if (pdsState === null) return null; 45 + const n = typeof pdsState === "number" ? pdsState : Number(pdsState); 46 + return Number.isFinite(n) ? n : null; 47 + }, [pdsState]); 48 + const isPdsReady = pdsStateNum !== null && pdsStateNum >= 3; 49 + const createAccountDisabled = 50 + loading || !inviteCode || !handle || !newPassword || !isPdsReady; 51 + const createSessionDisabled = 52 + loading || !handle || !newPassword || !isPdsReady; 53 + 54 + useEffect(() => { 55 + const load = async () => { 56 + try { 57 + const res = await fetch("/api/pds/service", { method: "GET" }); 58 + if (!res.ok) throw new Error(`Failed to load service (${res.status})`); 59 + const data = (await res.json()) as ServiceResponse; 60 + const host = data?.encrypted_config?.hostname || ""; 61 + setPdsHost(host); 62 + setPdsState(data?.state ?? null); 63 + 64 + if (!handle && host) { 65 + const bare = stripScheme(host); 66 + setHandle(`user1.${bare}`); 67 + setSessionIdentifier(`user1.${bare}`); 68 + } 69 + } catch (e) { 70 + setError(e instanceof Error ? e.message : "Unknown error"); 71 + } 72 + }; 73 + load(); 74 + }, []); 75 + 76 + const call = async (path: string, body: any) => { 77 + setLoading(true); 78 + setError(null); 79 + setOutput(null); 80 + try { 81 + const res = await fetch(path, { 82 + method: "POST", 83 + headers: { "Content-Type": "application/json" }, 84 + body: JSON.stringify(body), 85 + }); 86 + 87 + const contentType = res.headers.get("content-type") || ""; 88 + const payload = contentType.includes("application/json") 89 + ? await res.json() 90 + : await res.text().catch(() => ""); 91 + 92 + if (!res.ok) { 93 + if (typeof payload === "string") { 94 + throw new Error(payload); 95 + } 96 + 97 + // Prefer the nested upstream error if present. 98 + const upstreamMessage = 99 + payload?.payload?.message || 100 + payload?.payload?.error || 101 + payload?.message; 102 + 103 + const details = { 104 + route: path, 105 + httpStatus: res.status, 106 + upstream: payload?.payload, 107 + message: upstreamMessage || "Request failed", 108 + }; 109 + 110 + throw new Error(JSON.stringify(details, null, 2)); 111 + } 112 + 113 + return payload; 114 + } finally { 115 + setLoading(false); 116 + } 117 + }; 118 + 119 + const createInvite = async () => { 120 + const payload = await call("/api/pds/atproto/invite", { useCount: 1 }); 121 + const code = payload?.code || payload?.inviteCode || ""; 122 + setInviteCode(code); 123 + setOutput(payload); 124 + }; 125 + 126 + const createAccount = async () => { 127 + const payload = await call("/api/pds/atproto/create-account", { 128 + email, 129 + handle, 130 + password: newPassword, 131 + inviteCode, 132 + }); 133 + setOutput(payload); 134 + setSessionIdentifier(handle); 135 + setSessionPassword(newPassword); 136 + }; 137 + 138 + const createSession = async () => { 139 + const payload = await call("/api/pds/atproto/create-session", { 140 + identifier: sessionIdentifier || handle, 141 + password: sessionPassword || newPassword, 142 + }); 143 + setOutput(payload); 144 + }; 145 + 146 + return ( 147 + <section className="space-y-3 rounded-md border border-white/10 bg-white/5 p-4 text-white backdrop-blur-xl"> 148 + <Heading 149 + as="h2" 150 + className="text-sm font-semibold uppercase tracking-wide text-white/80" 151 + > 152 + AT Protocol (test) 153 + </Heading> 154 + 155 + {pdsHost ? ( 156 + <Paragraph className="text-sm text-white/70"> 157 + PDS endpoint:{" "} 158 + <span className="font-mono text-white">{pdsHost}</span> 159 + </Paragraph> 160 + ) : ( 161 + <Paragraph className="text-sm text-white/70">Loading PDS endpoint…</Paragraph> 162 + )} 163 + 164 + {pdsStateNum !== null && !isPdsReady && ( 165 + <Paragraph className="text-sm text-amber-100/90"> 166 + PDS not ready yet (state={pdsStateNum}). Waiting for provisioning to 167 + finish. 168 + </Paragraph> 169 + )} 170 + 171 + <div className="space-y-2 text-sm"> 172 + <div className="flex flex-wrap gap-2"> 173 + <Button 174 + onClick={createInvite} 175 + disabled={loading || !pdsBareHost || !isPdsReady} 176 + className="rounded-full" 177 + > 178 + {loading ? "Working..." : "Create invite"} 179 + </Button> 180 + </div> 181 + 182 + {inviteCode && ( 183 + <div className="space-y-1"> 184 + <Paragraph className="text-xs font-medium text-white/60"> 185 + Invite code 186 + </Paragraph> 187 + <Paragraph className="font-mono text-white break-all"> 188 + {inviteCode} 189 + </Paragraph> 190 + </div> 191 + )} 192 + </div> 193 + 194 + <div className="grid gap-3 md:grid-cols-2"> 195 + <label className="space-y-1"> 196 + <Paragraph className="text-xs font-medium text-white/60"> 197 + Email (optional) 198 + </Paragraph> 199 + <input 200 + value={email} 201 + onChange={(e) => setEmail(e.target.value)} 202 + className="w-full rounded-md border border-white/20 bg-transparent px-3 py-2 text-sm text-white placeholder:text-white/50" 203 + placeholder="leave blank to reuse your own email" 204 + /> 205 + </label> 206 + 207 + <label className="space-y-1"> 208 + <Paragraph className="text-xs font-medium text-white/60">Handle</Paragraph> 209 + <input 210 + value={handle} 211 + onChange={(e) => setHandle(e.target.value)} 212 + className="w-full rounded-md border border-white/20 bg-transparent px-3 py-2 text-sm text-white placeholder:text-white/50" 213 + placeholder={`user1.${pdsBareHost || "eny.k8s.frx.pub"}`} 214 + /> 215 + </label> 216 + 217 + <label className="space-y-1 md:col-span-2"> 218 + <Paragraph className="text-xs font-medium text-white/60"> 219 + Password 220 + </Paragraph> 221 + <input 222 + type="password" 223 + value={newPassword} 224 + onChange={(e) => setNewPassword(e.target.value)} 225 + className="w-full rounded-md border border-white/20 bg-transparent px-3 py-2 text-sm text-white placeholder:text-white/50" 226 + placeholder="new account password" 227 + /> 228 + </label> 229 + </div> 230 + 231 + <div className="flex flex-wrap gap-2"> 232 + <Button 233 + onClick={createAccount} 234 + disabled={createAccountDisabled} 235 + className={ 236 + createAccountDisabled 237 + ? "rounded-full bg-emerald-400/10 border border-emerald-200/10 opacity-60 cursor-not-allowed" 238 + : "rounded-full bg-emerald-400/20 hover:bg-emerald-400/35 border border-emerald-200/25" 239 + } 240 + > 241 + Create user 242 + </Button> 243 + <Button 244 + onClick={createSession} 245 + disabled={createSessionDisabled} 246 + className={ 247 + createSessionDisabled 248 + ? "rounded-full bg-sky-400/10 border border-sky-200/10 opacity-60 cursor-not-allowed" 249 + : "rounded-full bg-sky-400/20 hover:bg-sky-400/35 border border-sky-200/25" 250 + } 251 + > 252 + Login (create session) 253 + </Button> 254 + </div> 255 + 256 + {error && ( 257 + <Paragraph className="text-sm text-rose-100 bg-rose-950/40 rounded p-3"> 258 + {error} 259 + </Paragraph> 260 + )} 261 + 262 + {output && ( 263 + <div className="space-y-2"> 264 + <Paragraph className="text-xs font-medium text-white/60">Response</Paragraph> 265 + <pre className="max-h-64 overflow-auto rounded bg-neutral-900/90 p-3 text-xs text-neutral-100"> 266 + {output?.emailUsed && ( 267 + <Paragraph className="mb-2 text-xs text-white/70"> 268 + Email used:{" "} 269 + <span className="font-mono">{output.emailUsed}</span> 270 + </Paragraph> 271 + )} 272 + {output?.accessJwt 273 + ? JSON.stringify( 274 + { 275 + ...output, 276 + accessJwt: redactJwt(output.accessJwt), 277 + refreshJwt: redactJwt(output.refreshJwt), 278 + }, 279 + null, 280 + 2, 281 + ) 282 + : JSON.stringify(output, null, 2)} 283 + </pre> 284 + </div> 285 + )} 286 + </section> 287 + ); 288 + } 289 +
+33
app/dashboard/collapsible-section.tsx
··· 1 + "use client"; 2 + 3 + import { cn } from "@/actions/lib/utils"; 4 + import { ChevronDownIcon } from "lucide-react"; 5 + 6 + interface CollapsibleSectionProps { 7 + title: string; 8 + children: React.ReactNode; 9 + defaultOpen?: boolean; 10 + className?: string; 11 + } 12 + 13 + export function CollapsibleSection({ 14 + title, 15 + children, 16 + defaultOpen = false, 17 + className, 18 + }: CollapsibleSectionProps) { 19 + return ( 20 + <details 21 + open={defaultOpen} 22 + className={cn("group rounded-md border border-white/10 bg-white/5 backdrop-blur-xl", className)} 23 + > 24 + <summary className="flex cursor-pointer select-none list-none items-center justify-between px-4 py-3 text-sm font-semibold uppercase tracking-wide text-white/80 hover:text-white transition-colors"> 25 + {title} 26 + <ChevronDownIcon className="size-4 transition-transform group-open:rotate-180" /> 27 + </summary> 28 + <div className="border-t border-white/10 px-4 py-4"> 29 + {children} 30 + </div> 31 + </details> 32 + ); 33 + }
+278
app/dashboard/dashboard-client.tsx
··· 1 + "use client"; 2 + 3 + import { useEffect, useMemo, useRef, useState } from "react"; 4 + import { 5 + createSubscriptionCheckout, 6 + cancelSubscription, 7 + resumeSubscription, 8 + createBillingPortalSession, 9 + } from "@/actions/subscription"; 10 + import { Heading } from "@/components/heading"; 11 + import { Paragraph } from "@/components/paragraph"; 12 + import { Button } from "@/actions/components/ui/button"; 13 + 14 + interface DashboardClientProps { 15 + subscribed: boolean; 16 + subscription: any; 17 + priceId: string; 18 + autoCheckoutFromPlan?: boolean; 19 + pdsPlan?: string; 20 + pdsUsername?: string; 21 + pdsHostname?: string; 22 + pdsDisksizeGb?: string; 23 + } 24 + 25 + export default function DashboardClient({ 26 + subscribed, 27 + subscription, 28 + priceId, 29 + autoCheckoutFromPlan, 30 + pdsPlan, 31 + pdsUsername, 32 + pdsHostname, 33 + pdsDisksizeGb, 34 + }: DashboardClientProps) { 35 + const [loading, setLoading] = useState(false); 36 + const [actionLoading, setActionLoading] = useState<string | null>(null); 37 + const hasAutoStartedCheckout = useRef(false); 38 + 39 + const planBasedDisksize = useMemo(() => { 40 + if (pdsDisksizeGb && Number(pdsDisksizeGb) > 0) { 41 + return Number(pdsDisksizeGb); 42 + } 43 + 44 + const p = (pdsPlan || "").toLowerCase(); 45 + if (p === "community" || p === "growth") return 50; 46 + if (p === "business" || p === "pro") return 200; 47 + return 10; 48 + }, [pdsDisksizeGb, pdsPlan]); 49 + 50 + const selectedUsername = pdsUsername || undefined; 51 + const selectedHostname = pdsHostname || undefined; 52 + 53 + const handleSubscribe = async () => { 54 + if (!priceId) { 55 + alert( 56 + "Stripe price ID not configured. Set NEXT_PUBLIC_STRIPE_PRICE_PERSONAL_ID (and COMMUNITY/BUSINESS) or NEXT_PUBLIC_STRIPE_PRICE_ID as fallback.", 57 + ); 58 + return; 59 + } 60 + 61 + setLoading(true); 62 + try { 63 + const { url } = await createSubscriptionCheckout(priceId, { 64 + username: selectedUsername, 65 + hostname: selectedHostname, 66 + disksizeGb: planBasedDisksize, 67 + }); 68 + if (url) { 69 + window.location.href = url; 70 + } 71 + } catch (error) { 72 + console.error("Error creating checkout:", error); 73 + alert("Failed to create checkout session. Please try again."); 74 + } finally { 75 + setLoading(false); 76 + } 77 + }; 78 + 79 + useEffect(() => { 80 + if ( 81 + autoCheckoutFromPlan && 82 + !subscribed && 83 + !loading && 84 + !hasAutoStartedCheckout.current 85 + ) { 86 + hasAutoStartedCheckout.current = true; 87 + void handleSubscribe(); 88 + } 89 + }, [autoCheckoutFromPlan, subscribed, loading]); 90 + 91 + const hasSubscription = !!subscription; 92 + const isCanceled = 93 + subscription?.status === "canceled" || subscription?.status === "past_due"; 94 + 95 + if (!hasSubscription) { 96 + return ( 97 + <div className="space-y-3 text-white"> 98 + <Heading as="h2" className="text-base font-semibold"> 99 + Subscribe to Access 100 + </Heading> 101 + <Paragraph className="text-sm text-white/80"> 102 + You need an active subscription to access the server features. 103 + </Paragraph> 104 + {(pdsPlan || selectedHostname || selectedUsername) && ( 105 + <Paragraph className="text-xs text-white/70"> 106 + Selected plan settings: plan={pdsPlan || "personal"}, disksize= 107 + {planBasedDisksize}GiB 108 + {selectedHostname ? `, hostname=${selectedHostname}` : ""} 109 + {selectedUsername ? `, username=${selectedUsername}` : ""} 110 + </Paragraph> 111 + )} 112 + <Button 113 + onClick={handleSubscribe} 114 + disabled={loading} 115 + className="mt-1 rounded-full bg-white px-4 text-xs font-medium uppercase tracking-wide text-neutral-950 hover:bg-primary/80" 116 + > 117 + {loading ? "Loading..." : "Subscribe Now"} 118 + </Button> 119 + </div> 120 + ); 121 + } 122 + 123 + if (isCanceled) { 124 + return ( 125 + <div className="space-y-3 text-white"> 126 + <Heading as="h2" className="text-base font-semibold text-rose-300"> 127 + Subscription Canceled 128 + </Heading> 129 + <Paragraph className="text-sm text-white/80"> 130 + Your subscription has been canceled. Subscribe again to regain access. 131 + </Paragraph> 132 + <Button 133 + onClick={handleSubscribe} 134 + disabled={loading} 135 + className="mt-1 rounded-full bg-white px-4 text-xs font-medium uppercase tracking-wide text-neutral-950 hover:bg-primary/80" 136 + > 137 + {loading ? "Loading..." : "Subscribe Again"} 138 + </Button> 139 + </div> 140 + ); 141 + } 142 + 143 + const handleCancel = async () => { 144 + if ( 145 + !confirm( 146 + "Are you sure you want to cancel your subscription? You'll have access until the end of your billing period.", 147 + ) 148 + ) { 149 + return; 150 + } 151 + 152 + setActionLoading("cancel"); 153 + try { 154 + const result = await cancelSubscription(); 155 + if (result.success) { 156 + alert( 157 + "Subscription canceled. You'll have access until the end of your billing period.", 158 + ); 159 + window.location.reload(); 160 + } else { 161 + alert(`Error: ${result.error}`); 162 + } 163 + } catch (error) { 164 + console.error("Error canceling subscription:", error); 165 + alert("Failed to cancel subscription. Please try again."); 166 + } finally { 167 + setActionLoading(null); 168 + } 169 + }; 170 + 171 + const handleResume = async () => { 172 + setActionLoading("resume"); 173 + try { 174 + const result = await resumeSubscription(); 175 + if (result.success) { 176 + alert("Subscription resumed successfully!"); 177 + window.location.reload(); 178 + } else { 179 + alert(`Error: ${result.error}`); 180 + } 181 + } catch (error) { 182 + console.error("Error resuming subscription:", error); 183 + alert("Failed to resume subscription. Please try again."); 184 + } finally { 185 + setActionLoading(null); 186 + } 187 + }; 188 + 189 + const handleManageBilling = async () => { 190 + setActionLoading("billing"); 191 + try { 192 + const result = await createBillingPortalSession(); 193 + if (result.success && result.url) { 194 + window.location.href = result.url; 195 + } else { 196 + alert(`Error: ${result.error || "Failed to open billing portal"}`); 197 + setActionLoading(null); 198 + } 199 + } catch (error) { 200 + console.error("Error opening billing portal:", error); 201 + alert("Failed to open billing portal. Please try again."); 202 + setActionLoading(null); 203 + } 204 + }; 205 + 206 + const isCanceling = subscription?.cancel_at_period_end === true; 207 + 208 + return ( 209 + <div className="space-y-4 text-white"> 210 + <Heading 211 + as="h2" 212 + className={`text-base font-semibold ${ 213 + isCanceling ? "text-amber-300" : "text-emerald-300" 214 + }`} 215 + > 216 + {isCanceling ? "Cancellation scheduled" : "Active Subscription"} 217 + </Heading> 218 + {subscription && ( 219 + <div className="space-y-1 text-sm text-white/80"> 220 + <Paragraph> 221 + <span className="font-semibold text-white">Status:</span>{" "} 222 + {subscription.status} 223 + </Paragraph> 224 + {subscription.current_period_end && ( 225 + <Paragraph> 226 + <span className="font-semibold text-white"> 227 + {isCanceling ? "Access until:" : "Renews:"} 228 + </span>{" "} 229 + {new Date(subscription.current_period_end).toLocaleDateString()} 230 + </Paragraph> 231 + )} 232 + {isCanceling && ( 233 + <Paragraph> 234 + Your subscription will cancel at the end of the billing period. 235 + </Paragraph> 236 + )} 237 + </div> 238 + )} 239 + 240 + <div className="space-y-3 pt-2"> 241 + <div className="flex flex-wrap gap-2"> 242 + <Button 243 + onClick={handleManageBilling} 244 + disabled={actionLoading !== null} 245 + className="rounded-full bg-white px-4 text-xs font-medium uppercase tracking-wide text-neutral-950 hover:bg-primary/80" 246 + > 247 + {actionLoading === "billing" 248 + ? "Loading..." 249 + : "Manage Payment Method"} 250 + </Button> 251 + 252 + {isCanceling ? ( 253 + <Button 254 + onClick={handleResume} 255 + disabled={actionLoading !== null} 256 + className="rounded-full border border-white/60 bg-transparent px-4 text-xs font-medium uppercase tracking-wide text-white hover:bg-white/10" 257 + > 258 + {actionLoading === "resume" 259 + ? "Loading..." 260 + : "Resume Subscription"} 261 + </Button> 262 + ) : ( 263 + <Button 264 + onClick={handleCancel} 265 + disabled={actionLoading !== null} 266 + className="rounded-full border border-white/40 bg-transparent px-4 text-xs font-medium uppercase tracking-wide text-white hover:bg-white/10" 267 + > 268 + {actionLoading === "cancel" 269 + ? "Loading..." 270 + : "Cancel Subscription"} 271 + </Button> 272 + )} 273 + </div> 274 + </div> 275 + 276 + </div> 277 + ); 278 + }
+123
app/dashboard/page.tsx
··· 1 + import { redirect } from "next/navigation"; 2 + import { createClient } from "@/lib/supabase/server"; 3 + import { getSubscriptionStatus } from "@/actions/subscription"; 4 + import { 5 + Card, 6 + CardContent, 7 + CardHeader, 8 + } from "@/actions/components/ui/card"; 9 + import { ButtonLink } from "@/components/button-link"; 10 + import { Heading } from "@/components/heading"; 11 + import { Paragraph } from "@/components/paragraph"; 12 + import DashboardClient from "./dashboard-client"; 13 + import { ServiceDetailsClient } from "./service-details-client"; 14 + import { AtprotoTestClient } from "./atproto-test-client"; 15 + import { CollapsibleSection } from "./collapsible-section"; 16 + import { prelaunch } from "@/lib/prelaunch"; 17 + import { getPriceIdForPlan } from "@/lib/stripe-plans"; 18 + 19 + type DashboardPageProps = { 20 + searchParams?: Promise<{ 21 + auto_checkout?: string; 22 + pds_plan?: string; 23 + pds_username?: string; 24 + pds_hostname?: string; 25 + pds_disksize_gb?: string; 26 + }>; 27 + }; 28 + 29 + export default async function DashboardPage({ searchParams }: DashboardPageProps) { 30 + const params = await searchParams; 31 + const supabase = await createClient(); 32 + const { 33 + data: { user }, 34 + } = await supabase.auth.getUser(); 35 + 36 + if (!user) { 37 + redirect("/login"); 38 + } 39 + 40 + const { subscribed, subscription } = await getSubscriptionStatus(); 41 + 42 + if (prelaunch && !subscribed) { 43 + redirect("/welcome"); 44 + } 45 + 46 + const pdsStatus = subscribed ? "active" : "provisioning"; 47 + const pdsHostname = 48 + user.email?.split("@")[0]?.toLowerCase().replace(/[^a-z0-9-]/g, "-") + 49 + ".eny.space" || "pending.eny.space"; 50 + const pdsDashboardUrl = `https://${pdsHostname}`; 51 + 52 + return ( 53 + <main className="mx-auto flex w-full max-w-7xl flex-col gap-4 px-4 py-6 sm:px-6"> 54 + {/* Overview — always visible */} 55 + <Card> 56 + <CardHeader> 57 + <Heading as="h1" className="text-xl font-semibold text-white"> 58 + My PDS 59 + </Heading> 60 + <Paragraph className="text-sm text-white/80"> 61 + Authenticated as {user.email}. 62 + </Paragraph> 63 + </CardHeader> 64 + <CardContent className="space-y-4"> 65 + <div className="grid gap-4 md:grid-cols-2 text-white"> 66 + <div className="space-y-1"> 67 + <Paragraph className="text-sm font-medium text-white/60">Status</Paragraph> 68 + <Paragraph className="text-base font-semibold capitalize">{pdsStatus}</Paragraph> 69 + </div> 70 + <div className="space-y-1"> 71 + <Paragraph className="text-sm font-medium text-white/60">Hostname</Paragraph> 72 + <a 73 + href={pdsDashboardUrl} 74 + target="_blank" 75 + rel="noreferrer" 76 + className="text-base font-semibold text-primary underline underline-offset-2" 77 + > 78 + {pdsHostname} 79 + </a> 80 + </div> 81 + </div> 82 + <div className="flex flex-wrap gap-3 pt-1"> 83 + <ButtonLink 84 + href={pdsDashboardUrl} 85 + className="border border-white/80 bg-transparent uppercase tracking-wide text-white hover:bg-white/10 hover:border-white focus-visible:ring-white/50" 86 + > 87 + Open dashboard 88 + </ButtonLink> 89 + </div> 90 + </CardContent> 91 + </Card> 92 + 93 + {/* Usage & Stats */} 94 + <CollapsibleSection title="Usage & Stats"> 95 + <ServiceDetailsClient mode="stats" /> 96 + </CollapsibleSection> 97 + 98 + {/* Service Details */} 99 + <CollapsibleSection title="Service Details"> 100 + <ServiceDetailsClient mode="details" /> 101 + </CollapsibleSection> 102 + 103 + {/* AT Protocol */} 104 + <CollapsibleSection title="AT Protocol"> 105 + <AtprotoTestClient /> 106 + </CollapsibleSection> 107 + 108 + {/* Billing & Subscription */} 109 + <CollapsibleSection title="Billing & Subscription" defaultOpen> 110 + <DashboardClient 111 + subscribed={subscribed} 112 + subscription={subscription} 113 + priceId={getPriceIdForPlan(params?.pds_plan)} 114 + autoCheckoutFromPlan={params?.auto_checkout === "1"} 115 + pdsPlan={params?.pds_plan} 116 + pdsUsername={params?.pds_username} 117 + pdsHostname={params?.pds_hostname} 118 + pdsDisksizeGb={params?.pds_disksize_gb} 119 + /> 120 + </CollapsibleSection> 121 + </main> 122 + ); 123 + }
+491
app/dashboard/service-details-client.tsx
··· 1 + "use client"; 2 + 3 + import { useEffect, useState } from "react"; 4 + import { Heading } from "@/components/heading"; 5 + import { Paragraph } from "@/components/paragraph"; 6 + 7 + type ServiceStats = { 8 + cpuUsagePercent?: number; 9 + ramUsagePercent?: number; 10 + storageUsedBytes?: number; 11 + storageAllocatedBytes?: number; 12 + storageObjectsCount?: number; 13 + storageUsedDailyLast30d?: Array<{ date: string; usedBytes: number }>; 14 + bandwidthUsedBytesThisMonth?: number; 15 + bandwidthLimitBytesPerMonth?: number; 16 + requestsLast24h?: number; 17 + requestsPerHourLast24h?: Array<{ hour: string; count: number }>; 18 + activeUsers?: number; 19 + uniqueUsersLast30d?: number; 20 + userSlotsUsed?: number; 21 + userSlotsTotal?: number; 22 + uptimeSeconds?: number; 23 + lastBackupAt?: string; 24 + failedRequestsLast24h?: number; 25 + successfulRequestsLast24h?: number; 26 + }; 27 + 28 + type ServiceConfig = { 29 + hostname: string; 30 + adminPassword?: string; 31 + emailSmtpUrl?: string; 32 + pdsEmailFromAddress?: string; 33 + dataStorage?: { 34 + size?: string; 35 + }; 36 + }; 37 + 38 + type ServiceResponse = { 39 + id?: number | string; 40 + name: string; 41 + service: string; 42 + namespace: string; 43 + state?: number | string; 44 + kubeconfig_id: number | string; 45 + encrypted_config: ServiceConfig; 46 + install_cmd: string; 47 + created_at?: string; 48 + updated_at?: string; 49 + stats?: ServiceStats; 50 + }; 51 + 52 + function formatBytes(bytes?: number) { 53 + if (bytes === undefined || bytes === null || Number.isNaN(bytes)) return "—"; 54 + const units = ["B", "KiB", "MiB", "GiB", "TiB"]; 55 + let v = bytes; 56 + let i = 0; 57 + while (v >= 1024 && i < units.length - 1) { 58 + v /= 1024; 59 + i += 1; 60 + } 61 + return `${v.toFixed(v >= 10 || i === 0 ? 0 : 1)} ${units[i]}`; 62 + } 63 + 64 + function clampPct(n: number) { 65 + return Math.max(0, Math.min(100, n)); 66 + } 67 + 68 + export function ServiceDetailsClient({ 69 + mode = "all", 70 + }: { 71 + mode?: "all" | "stats" | "details"; 72 + }) { 73 + const [service, setService] = useState<ServiceResponse | null>(null); 74 + const [loading, setLoading] = useState(true); 75 + const [error, setError] = useState<string | null>(null); 76 + 77 + useEffect(() => { 78 + const fetchService = async () => { 79 + try { 80 + const res = await fetch("/api/pds/service", { 81 + method: "GET", 82 + }); 83 + 84 + if (!res.ok) { 85 + throw new Error(`Request failed with status ${res.status}`); 86 + } 87 + 88 + const data = (await res.json()) as ServiceResponse; 89 + setService(data); 90 + } catch (err) { 91 + console.error("Failed to load service details", err); 92 + setError( 93 + err instanceof Error ? err.message : "Unknown error fetching service", 94 + ); 95 + } finally { 96 + setLoading(false); 97 + } 98 + }; 99 + 100 + fetchService(); 101 + }, []); 102 + 103 + if (loading) { 104 + return ( 105 + <div className="mt-4 rounded-md border border-white/10 bg-white/5 p-4 text-white/80 text-sm"> 106 + Loading service details… 107 + </div> 108 + ); 109 + } 110 + 111 + if (error) { 112 + return ( 113 + <div className="mt-4 rounded-md border border-rose-500/50 bg-rose-950/40 p-4 text-sm text-rose-100"> 114 + Failed to load service details: {error} 115 + </div> 116 + ); 117 + } 118 + 119 + if (!service) { 120 + return null; 121 + } 122 + 123 + const cfg = service.encrypted_config || {}; 124 + const stats = service.stats; 125 + const maskedAdminPassword = 126 + cfg.adminPassword && cfg.adminPassword.length > 0 ? "••••••••" : undefined; 127 + 128 + const storagePct = 129 + stats?.storageUsedBytes !== undefined && 130 + stats?.storageAllocatedBytes !== undefined && 131 + stats.storageAllocatedBytes > 0 132 + ? clampPct((stats.storageUsedBytes / stats.storageAllocatedBytes) * 100) 133 + : undefined; 134 + 135 + const bandwidthPct = 136 + stats?.bandwidthUsedBytesThisMonth !== undefined && 137 + stats?.bandwidthLimitBytesPerMonth !== undefined && 138 + stats.bandwidthLimitBytesPerMonth > 0 139 + ? clampPct( 140 + (stats.bandwidthUsedBytesThisMonth / 141 + stats.bandwidthLimitBytesPerMonth) * 142 + 100, 143 + ) 144 + : undefined; 145 + 146 + const errorRatePct = 147 + stats?.failedRequestsLast24h !== undefined && 148 + stats?.successfulRequestsLast24h !== undefined 149 + ? clampPct( 150 + (stats.failedRequestsLast24h / 151 + Math.max( 152 + 1, 153 + stats.failedRequestsLast24h + stats.successfulRequestsLast24h, 154 + )) * 155 + 100, 156 + ) 157 + : undefined; 158 + 159 + const showDetails = mode === "all" || mode === "details"; 160 + const showStats = mode === "all" || mode === "stats"; 161 + 162 + return ( 163 + <section 164 + className={ 165 + mode === "stats" 166 + ? "space-y-3 text-white" 167 + : "mt-6 space-y-3 rounded-md border border-white/10 bg-white/5 p-4 text-white backdrop-blur-xl" 168 + } 169 + > 170 + {showDetails && ( 171 + <> 172 + <Heading 173 + as="h2" 174 + className="text-sm font-semibold uppercase tracking-wide text-white/80" 175 + > 176 + Service Details 177 + </Heading> 178 + <div className="grid gap-3 md:grid-cols-2 text-sm text-white/80"> 179 + {service.id !== undefined && ( 180 + <div className="space-y-1"> 181 + <Paragraph className="text-xs font-medium text-white/60"> 182 + ID 183 + </Paragraph> 184 + <Paragraph className="text-sm font-mono text-white"> 185 + {String(service.id)} 186 + </Paragraph> 187 + </div> 188 + )} 189 + <div className="space-y-1"> 190 + <Paragraph className="text-xs font-medium text-white/60"> 191 + Name 192 + </Paragraph> 193 + <Paragraph className="text-sm font-semibold text-white"> 194 + {service.name} 195 + </Paragraph> 196 + </div> 197 + <div className="space-y-1"> 198 + <Paragraph className="text-xs font-medium text-white/60"> 199 + Service Type 200 + </Paragraph> 201 + <Paragraph className="text-sm font-semibold text-white"> 202 + {service.service} 203 + </Paragraph> 204 + </div> 205 + <div className="space-y-1"> 206 + <Paragraph className="text-xs font-medium text-white/60"> 207 + Namespace 208 + </Paragraph> 209 + <Paragraph className="text-sm font-mono text-white"> 210 + {service.namespace} 211 + </Paragraph> 212 + </div> 213 + {service.state !== undefined && ( 214 + <div className="space-y-1"> 215 + <Paragraph className="text-xs font-medium text-white/60"> 216 + State 217 + </Paragraph> 218 + <Paragraph className="text-sm font-mono text-white"> 219 + {String(service.state)} 220 + </Paragraph> 221 + </div> 222 + )} 223 + {service.kubeconfig_id !== undefined && ( 224 + <div className="space-y-1"> 225 + <Paragraph className="text-xs font-medium text-white/60"> 226 + Kubeconfig ID 227 + </Paragraph> 228 + <Paragraph className="text-sm font-mono text-white"> 229 + {String(service.kubeconfig_id)} 230 + </Paragraph> 231 + </div> 232 + )} 233 + <div className="space-y-1"> 234 + <Paragraph className="text-xs font-medium text-white/60"> 235 + Hostname 236 + </Paragraph> 237 + <Paragraph className="text-sm font-semibold text-white"> 238 + {cfg.hostname} 239 + </Paragraph> 240 + </div> 241 + {maskedAdminPassword && ( 242 + <div className="space-y-1"> 243 + <Paragraph className="text-xs font-medium text-white/60"> 244 + Admin Password 245 + </Paragraph> 246 + <Paragraph className="text-sm font-mono text-white"> 247 + {maskedAdminPassword} 248 + </Paragraph> 249 + </div> 250 + )} 251 + {cfg.pdsEmailFromAddress && ( 252 + <div className="space-y-1"> 253 + <Paragraph className="text-xs font-medium text-white/60"> 254 + PDS Email From 255 + </Paragraph> 256 + <Paragraph className="text-sm font-mono text-white"> 257 + {cfg.pdsEmailFromAddress} 258 + </Paragraph> 259 + </div> 260 + )} 261 + {cfg.emailSmtpUrl && ( 262 + <div className="space-y-1 md:col-span-2"> 263 + <Paragraph className="text-xs font-medium text-white/60"> 264 + SMTP URL 265 + </Paragraph> 266 + <Paragraph className="text-sm font-mono text-white break-all"> 267 + {cfg.emailSmtpUrl} 268 + </Paragraph> 269 + </div> 270 + )} 271 + {cfg.dataStorage?.size && ( 272 + <div className="space-y-1"> 273 + <Paragraph className="text-xs font-medium text-white/60"> 274 + Data Storage 275 + </Paragraph> 276 + <Paragraph className="text-sm font-semibold text-white"> 277 + {cfg.dataStorage.size} 278 + </Paragraph> 279 + </div> 280 + )} 281 + {(service.created_at || service.updated_at) && ( 282 + <div className="space-y-1 md:col-span-2"> 283 + <Paragraph className="text-xs font-medium text-white/60"> 284 + Timestamps 285 + </Paragraph> 286 + <Paragraph className="text-sm font-mono text-white/90"> 287 + {service.created_at && ( 288 + <span className="mr-4"> 289 + created_at: {service.created_at} 290 + </span> 291 + )} 292 + {service.updated_at && ( 293 + <span>updated_at: {service.updated_at}</span> 294 + )} 295 + </Paragraph> 296 + </div> 297 + )} 298 + </div> 299 + </> 300 + )} 301 + 302 + {showStats && stats && ( 303 + <div className="mt-4 space-y-3"> 304 + {mode !== "stats" && ( 305 + <Paragraph className="text-xs font-medium text-white/60"> 306 + Usage stats 307 + </Paragraph> 308 + )} 309 + 310 + <div className="grid gap-3 md:grid-cols-3 text-sm text-white/80"> 311 + <div className="rounded border border-white/10 bg-white/5 p-3"> 312 + <Paragraph className="text-xs font-medium text-white/60"> 313 + CPU usage 314 + </Paragraph> 315 + <Paragraph className="text-sm font-semibold text-white"> 316 + {stats.cpuUsagePercent !== undefined 317 + ? `${clampPct(stats.cpuUsagePercent).toFixed(0)}%` 318 + : "—"} 319 + </Paragraph> 320 + {stats.cpuUsagePercent !== undefined && ( 321 + <div className="mt-2 h-2 w-full rounded bg-white/10"> 322 + <div 323 + className="h-2 rounded bg-fuchsia-400/80" 324 + style={{ width: `${clampPct(stats.cpuUsagePercent)}%` }} 325 + /> 326 + </div> 327 + )} 328 + </div> 329 + 330 + <div className="rounded border border-white/10 bg-white/5 p-3"> 331 + <Paragraph className="text-xs font-medium text-white/60"> 332 + RAM usage 333 + </Paragraph> 334 + <Paragraph className="text-sm font-semibold text-white"> 335 + {stats.ramUsagePercent !== undefined 336 + ? `${clampPct(stats.ramUsagePercent).toFixed(0)}%` 337 + : "—"} 338 + </Paragraph> 339 + {stats.ramUsagePercent !== undefined && ( 340 + <div className="mt-2 h-2 w-full rounded bg-white/10"> 341 + <div 342 + className="h-2 rounded bg-amber-300/80" 343 + style={{ width: `${clampPct(stats.ramUsagePercent)}%` }} 344 + /> 345 + </div> 346 + )} 347 + {stats.userSlotsUsed !== undefined && 348 + stats.userSlotsTotal !== undefined && ( 349 + <Paragraph className="mt-2 text-xs text-white/70"> 350 + Users: {stats.userSlotsUsed}/{stats.userSlotsTotal} 351 + </Paragraph> 352 + )} 353 + </div> 354 + 355 + <div className="rounded border border-white/10 bg-white/5 p-3"> 356 + <Paragraph className="text-xs font-medium text-white/60"> 357 + Storage 358 + </Paragraph> 359 + <Paragraph className="text-sm font-semibold text-white"> 360 + {formatBytes(stats.storageUsedBytes)} /{" "} 361 + {formatBytes(stats.storageAllocatedBytes)} 362 + </Paragraph> 363 + {storagePct !== undefined && ( 364 + <div className="mt-2 h-2 w-full rounded bg-white/10"> 365 + <div 366 + className="h-2 rounded bg-emerald-400/80" 367 + style={{ width: `${storagePct}%` }} 368 + /> 369 + </div> 370 + )} 371 + {stats.storageObjectsCount !== undefined && ( 372 + <Paragraph className="mt-2 text-xs text-white/70"> 373 + Objects: {stats.storageObjectsCount.toLocaleString()} 374 + </Paragraph> 375 + )} 376 + </div> 377 + 378 + <div className="rounded border border-white/10 bg-white/5 p-3"> 379 + <Paragraph className="text-xs font-medium text-white/60"> 380 + Bandwidth (month) 381 + </Paragraph> 382 + <Paragraph className="text-sm font-semibold text-white"> 383 + {formatBytes(stats.bandwidthUsedBytesThisMonth)} /{" "} 384 + {formatBytes(stats.bandwidthLimitBytesPerMonth)} 385 + </Paragraph> 386 + {bandwidthPct !== undefined && ( 387 + <div className="mt-2 h-2 w-full rounded bg-white/10"> 388 + <div 389 + className="h-2 rounded bg-sky-400/80" 390 + style={{ width: `${bandwidthPct}%` }} 391 + /> 392 + </div> 393 + )} 394 + {stats.requestsLast24h !== undefined && ( 395 + <Paragraph className="mt-2 text-xs text-white/70"> 396 + Requests (24h): {stats.requestsLast24h.toLocaleString()} 397 + </Paragraph> 398 + )} 399 + </div> 400 + 401 + <div className="rounded border border-white/10 bg-white/5 p-3"> 402 + <Paragraph className="text-xs font-medium text-white/60"> 403 + Health (24h) 404 + </Paragraph> 405 + <Paragraph className="text-sm font-semibold text-white"> 406 + Error rate:{" "} 407 + {errorRatePct !== undefined 408 + ? `${errorRatePct.toFixed(2)}%` 409 + : "—"} 410 + </Paragraph> 411 + {stats.lastBackupAt && ( 412 + <Paragraph className="mt-2 text-xs text-white/70"> 413 + Last backup: {new Date(stats.lastBackupAt).toLocaleString()} 414 + </Paragraph> 415 + )} 416 + {stats.uptimeSeconds !== undefined && ( 417 + <Paragraph className="mt-1 text-xs text-white/70"> 418 + Uptime: {(stats.uptimeSeconds / 3600).toFixed(1)}h 419 + </Paragraph> 420 + )} 421 + </div> 422 + </div> 423 + 424 + {Array.isArray(stats.requestsPerHourLast24h) && 425 + stats.requestsPerHourLast24h.length > 0 && ( 426 + <div className="rounded border border-white/10 bg-white/5 p-3"> 427 + <Paragraph className="text-xs font-medium text-white/60"> 428 + Requests per hour (last 24h) 429 + </Paragraph> 430 + <div className="mt-3 flex h-16 items-end gap-1"> 431 + {(() => { 432 + const max = Math.max( 433 + ...stats.requestsPerHourLast24h!.map((p) => p.count), 434 + ); 435 + return stats.requestsPerHourLast24h!.map((p, idx) => ( 436 + <div 437 + key={`${p.hour}-${idx}`} 438 + className="w-full rounded-sm bg-white/10" 439 + title={`${new Date(p.hour).toLocaleString()}: ${p.count.toLocaleString()}`} 440 + style={{ 441 + height: `${clampPct((p.count / Math.max(1, max)) * 100)}%`, 442 + backgroundColor: "rgba(56, 189, 248, 0.6)", 443 + }} 444 + /> 445 + )); 446 + })()} 447 + </div> 448 + </div> 449 + )} 450 + 451 + {Array.isArray(stats.storageUsedDailyLast30d) && 452 + stats.storageUsedDailyLast30d.length > 0 && ( 453 + <div className="rounded border border-white/10 bg-white/5 p-3"> 454 + <Paragraph className="text-xs font-medium text-white/60"> 455 + Storage used (last 30d) 456 + </Paragraph> 457 + <div className="mt-3 flex h-16 items-end gap-1"> 458 + {(() => { 459 + const max = Math.max( 460 + ...stats.storageUsedDailyLast30d!.map((p) => p.usedBytes), 461 + ); 462 + return stats.storageUsedDailyLast30d!.map((p, idx) => ( 463 + <div 464 + key={`${p.date}-${idx}`} 465 + className="w-full rounded-sm bg-emerald-400/50" 466 + title={`${p.date}: ${formatBytes(p.usedBytes)}`} 467 + style={{ 468 + height: `${clampPct((p.usedBytes / Math.max(1, max)) * 100)}%`, 469 + }} 470 + /> 471 + )); 472 + })()} 473 + </div> 474 + </div> 475 + )} 476 + </div> 477 + )} 478 + 479 + {showDetails && service.install_cmd && ( 480 + <div className="mt-3 space-y-1"> 481 + <Paragraph className="text-xs font-medium text-white/60"> 482 + Install command 483 + </Paragraph> 484 + <pre className="max-h-64 overflow-auto rounded bg-neutral-900/90 p-3 text-xs text-neutral-100"> 485 + {service.install_cmd} 486 + </pre> 487 + </div> 488 + )} 489 + </section> 490 + ); 491 + }
+108 -404
app/globals.css
··· 1 1 @import "tailwindcss"; 2 2 @import "tw-animate-css"; 3 + @import "shadcn/tailwind.css"; 3 4 4 5 @custom-variant dark (&:is(.dark *)); 5 6 6 - /* Variables */ 7 7 :root { 8 - --body-color: #050505; 9 - --body-text-color: #f5f5f5; 10 - --checkout-color: #8f6ed5; 11 - --elements-color: #7c7cff; 12 - --h1-color: #f9fafb; 13 - --h2-color: #e5e7eb; 14 - --h3-color: #9ca3af; 8 + --background: oklch(1 0 0); /* pure white */ 9 + --foreground: oklch(0.145 0 0); /* very dark neutral (near black) */ 10 + --card: oklch(1 0 0); /* pure white */ 11 + --card-foreground: oklch(0.145 0 0); /* very dark neutral */ 12 + --popover: oklch(1 0 0); /* pure white */ 13 + --popover-foreground: oklch(0.145 0 0); /* very dark neutral */ 14 + /* Softer, lighter lilac primary for light mode */ 15 + --primary: oklch(0.88 0.16 325); /* light lilac / fuchsia */ 16 + --primary-foreground: oklch(0.22 0.05 325); /* deep plum text on lilac */ 17 + --secondary: oklch(0.967 0.001 286.375); /* very light cool gray with violet tint */ 18 + --secondary-foreground: oklch(0.21 0.006 285.885); /* deep cool gray text */ 19 + --muted: oklch(0.97 0 0); /* very light neutral gray */ 20 + --muted-foreground: oklch(0.556 0 0); /* medium neutral gray text */ 21 + --accent: oklch(0.97 0 0); /* very light neutral gray (accent bg) */ 22 + --accent-foreground: oklch(0.205 0 0); /* dark neutral text on accent */ 23 + --destructive: oklch(0.58 0.22 27); /* vivid warm red/orange */ 24 + --border: oklch(0.922 0 0); /* light neutral gray border */ 25 + --input: oklch(0.922 0 0); /* light neutral gray input */ 26 + --ring: oklch(0.708 0 0); /* medium neutral gray focus ring */ 27 + --chart-1: oklch(0.9 0.16 325); /* very light lilac */ 28 + --chart-2: oklch(0.86 0.18 325); /* light lilac */ 29 + --chart-3: oklch(0.82 0.19 325); /* mid lilac */ 30 + --chart-4: oklch(0.78 0.19 325); /* deeper lilac */ 31 + --chart-5: oklch(0.72 0.18 325); /* deepest lilac */ 15 32 --radius: 0.625rem; 16 - --container-width-max: 1280px; 17 - --page-width-max: 600px; 18 - --transition-duration: 2s; 19 - --background: oklch(1 0 0); 20 - --foreground: oklch(0.141 0.005 285.823); 21 - --card: oklch(1 0 0); 22 - --card-foreground: oklch(0.141 0.005 285.823); 23 - --popover: oklch(1 0 0); 24 - --popover-foreground: oklch(0.141 0.005 285.823); 25 - --primary: oklch(0.21 0.006 285.885); 26 - --primary-foreground: oklch(0.985 0 0); 27 - --secondary: oklch(0.967 0.001 286.375); 28 - --secondary-foreground: oklch(0.21 0.006 285.885); 29 - --muted: oklch(0.967 0.001 286.375); 30 - --muted-foreground: oklch(0.552 0.016 285.938); 31 - --accent: oklch(0.967 0.001 286.375); 32 - --accent-foreground: oklch(0.21 0.006 285.885); 33 - --destructive: oklch(0.577 0.245 27.325); 34 - --border: oklch(0.92 0.004 286.32); 35 - --input: oklch(0.92 0.004 286.32); 36 - --ring: oklch(0.705 0.015 286.067); 37 - --chart-1: oklch(0.646 0.222 41.116); 38 - --chart-2: oklch(0.6 0.118 184.704); 39 - --chart-3: oklch(0.398 0.07 227.392); 40 - --chart-4: oklch(0.828 0.189 84.429); 41 - --chart-5: oklch(0.769 0.188 70.08); 42 - --sidebar: oklch(0.985 0 0); 43 - --sidebar-foreground: oklch(0.141 0.005 285.823); 44 - --sidebar-primary: oklch(0.21 0.006 285.885); 45 - --sidebar-primary-foreground: oklch(0.985 0 0); 46 - --sidebar-accent: oklch(0.967 0.001 286.375); 47 - --sidebar-accent-foreground: oklch(0.21 0.006 285.885); 48 - --sidebar-border: oklch(0.92 0.004 286.32); 49 - --sidebar-ring: oklch(0.705 0.015 286.067); 50 - } 51 - 52 - body { 53 - margin: 0; 54 - padding: 0; 55 - background: var(--body-color); 56 - color: var(--body-text-color); 57 - overflow-y: scroll; 58 - } 59 - 60 - * { 61 - box-sizing: border-box; 62 - -webkit-tap-highlight-color: rgba(255, 255, 255, 0); 63 - } 64 - 65 - #__next { 66 - display: flex; 67 - justify-content: center; 68 - } 69 - 70 - .container { 71 - max-width: var(--container-width-max); 72 - padding: 45px 25px; 73 - display: flex; 74 - flex-direction: row; 75 - } 76 - 77 - .page-container { 78 - padding-bottom: 60px; 79 - max-width: var(--page-width-max); 80 - } 81 - 82 - h1 { 83 - font-weight: 600; 84 - color: var(--h1-color); 85 - margin: 6px 0 12px; 86 - font-size: 27px; 87 - line-height: 32px; 88 - } 89 - 90 - h1 span.light { 91 - color: var(--h3-color); 92 - } 93 - 94 - h2 { 95 - color: var(--h2-color); 96 - margin: 8px 0; 97 - } 98 - 99 - h3 { 100 - font-size: 17px; 101 - color: var(--h3-color); 102 - margin: 8px 0; 103 - } 104 - 105 - a { 106 - color: #ffffff; 107 - text-decoration: none; 108 - } 109 - 110 - header { 111 - position: relative; 112 - flex: 0 0 250px; 113 - padding-right: 48px; 114 - } 115 - 116 - .header-content { 117 - position: sticky; 118 - top: 45px; 119 - } 120 - 121 - .logo img { 122 - height: 20px; 123 - margin-bottom: 52px; 124 - } 125 - 126 - ul, 127 - li { 128 - list-style: none; 129 - padding: 0; 130 - margin: 0; 131 - } 132 - 133 - .card-list { 134 - display: flex; 135 - flex-wrap: wrap; 136 - align-content: flex-start; 137 - padding-top: 64px; 138 - } 139 - 140 - .card { 141 - display: block; 142 - border-radius: 10px; 143 - position: relative; 144 - padding: 12px; 145 - height: 320px; 146 - flex: 0 0 33%; 147 - min-width: 304px; 148 - width: 33%; 149 - margin: 0 20px 20px 0; 150 - text-decoration: none; 151 - box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6), 152 - 0 0 0 1px rgba(255, 255, 255, 0.08); 153 - background: #0b0b0f; 154 - } 155 - .card h2 { 156 - color: #fff; 157 - } 158 - .card h2.bottom { 159 - position: absolute; 160 - bottom: 10px; 161 - } 162 - 163 - .card img { 164 - width: 80%; 165 - position: absolute; 166 - top: 50%; 167 - left: 50%; 168 - transform: translate(-50%, -50%); 169 - } 170 - 171 - .error-message { 172 - color: #ef2961; 173 - } 174 - 175 - .FormRow, 176 - fieldset, 177 - input[type="number"], 178 - input[type="text"] { 179 - border-radius: var(--radius); 180 - padding: 5px 12px; 181 - width: 100%; 182 - background: #111827; 183 - color: var(--body-text-color); 184 - appearance: none; 185 - font-size: 16px; 186 - margin-top: 10px; 187 - } 188 - 189 - input[type="range"] { 190 - margin: 5px 0; 191 - width: 100%; 192 - } 193 - 194 - button { 195 - border-radius: var(--radius); 196 - color: white; 197 - font-size: larger; 198 - border: 0; 199 - padding: 12px 16px; 200 - margin-top: 10px; 201 - font-weight: 600; 202 - cursor: pointer; 203 - transition: all 0.2s ease; 204 - display: block; 205 - width: 100%; 206 - } 207 - button:disabled { 208 - opacity: 0.5; 209 - cursor: not-allowed; 210 - } 211 - 212 - .elements-style { 213 - color: var(--elements-color); 214 - border: 1px solid var(--elements-color); 215 - } 216 - .elements-style-background { 217 - background: var(--elements-color); 218 - transition: box-shadow var(--transition-duration); 219 - } 220 - .card.elements-style-background:hover { 221 - box-shadow: 20px 20px 60px #464e9c, -20px -20px 60px #8896ff; 222 - } 223 - .checkout-style { 224 - color: var(--checkout-color); 225 - border: 1px solid var(--checkout-color); 226 - } 227 - .checkout-style-background { 228 - background: #000000; 229 - color: #ffffff; 230 - border: 1px solid #ffffff; 231 - transition: box-shadow var(--transition-duration), transform 0.15s ease; 232 - } 233 - .card.checkout-style-background:hover { 234 - box-shadow: 0 0 0 2px #ffffff; 235 - transform: translateY(-2px); 236 - } 237 - 238 - /* Test card number */ 239 - .test-card-notice { 240 - display: block; 241 - margin-block-start: 1em; 242 - margin-block-end: 1em; 243 - margin-inline-start: 0px; 244 - margin-inline-end: 0px; 245 - } 246 - .card-number { 247 - display: inline; 248 - white-space: nowrap; 249 - font-family: Menlo, Consolas, monospace; 250 - color: #3c4257; 251 - font-weight: 500; 252 - } 253 - .card-number span { 254 - display: inline-block; 255 - width: 4px; 256 - } 257 - 258 - /* Code block */ 259 - code, 260 - pre { 261 - font-family: "SF Mono", "IBM Plex Mono", "Menlo", monospace; 262 - font-size: 12px; 263 - background: rgba(255, 255, 255, 0.04); 264 - padding: 12px; 265 - border-radius: var(--radius); 266 - max-height: 500px; 267 - width: var(--page-width-max); 268 - overflow: auto; 269 - } 270 - 271 - .banner { 272 - max-width: 825px; 273 - margin: 0 auto; 274 - font-size: 14px; 275 - background: #111827; 276 - color: #e5e7eb; 277 - border-radius: 50px; 278 - box-shadow: 0 12px 30px rgba(0, 0, 0, 0.8), 279 - 0 0 0 1px rgba(255, 255, 255, 0.08); 280 - display: flex; 281 - align-items: center; 282 - box-sizing: border-box; 283 - padding: 15px; 284 - line-height: 1.15; 285 - position: fixed; 286 - bottom: 2vh; 287 - left: 0; 288 - right: 0; 289 - text-align: center; 290 - justify-content: center; 291 - } 292 - 293 - @media only screen and (max-width: 980px) { 294 - .container { 295 - flex-direction: column; 296 - } 297 - 298 - .header-content { 299 - max-width: 280px; 300 - position: relative; 301 - top: 0; 302 - } 303 - 304 - .card { 305 - margin: 0 20px 20px 0; 306 - box-shadow: none; 307 - } 308 - 309 - .card-list { 310 - padding-top: 0; 311 - } 312 - 313 - .banner { 314 - box-shadow: none; 315 - bottom: 0; 316 - } 33 + --sidebar: oklch(0.985 0 0); /* off-white sidebar */ 34 + --sidebar-foreground: oklch(0.145 0 0); /* very dark neutral text */ 35 + --sidebar-primary: oklch(0.82 0.19 325); /* saturated lilac sidebar accent */ 36 + --sidebar-primary-foreground: oklch(0.99 0.02 325); /* soft near-white on lilac */ 37 + --sidebar-accent: oklch(0.97 0 0); /* very light neutral accent */ 38 + --sidebar-accent-foreground: oklch(0.205 0 0); /* dark neutral on accent */ 39 + --sidebar-border: oklch(0.922 0 0); /* light gray sidebar border */ 40 + --sidebar-ring: oklch(0.708 0 0); /* medium gray sidebar ring */ 317 41 } 318 42 319 - @media only screen and (max-width: 600px) { 320 - .container { 321 - flex-direction: column; 322 - } 323 - 324 - .card { 325 - display: block; 326 - border-radius: 8px; 327 - flex: 1 0 100%; 328 - max-width: 100%; 329 - padding-left: 0; 330 - padding-right: 0; 331 - margin: 0 0 20px 0; 332 - box-shadow: none; 333 - } 334 - 335 - .card-list { 336 - padding-top: 0; 337 - } 338 - 339 - code, 340 - pre, 341 - h3 { 342 - display: none; 343 - } 344 - 345 - .banner { 346 - box-shadow: none; 347 - bottom: 0; 348 - } 43 + .dark { 44 + --background: oklch(0.145 0 0); /* almost-black charcoal */ 45 + --foreground: oklch(0.985 0 0); /* near-white text */ 46 + --card: oklch(0.205 0 0); /* very dark gray card */ 47 + --card-foreground: oklch(0.985 0 0); /* near-white card text */ 48 + --popover: oklch(0.205 0 0); /* very dark gray popover */ 49 + --popover-foreground: oklch(0.985 0 0); /* near-white popover text */ 50 + /* Slightly lighter lilac primary for dark mode */ 51 + --primary: oklch(0.82 0.17 325); /* bright lilac / fuchsia */ 52 + --primary-foreground: oklch(0.2 0.06 325); /* deep plum on lilac */ 53 + --secondary: oklch(0.274 0.006 286.033); /* deep cool gray with violet tint */ 54 + --secondary-foreground: oklch(0.985 0 0); /* near-white on secondary */ 55 + --muted: oklch(0.269 0 0); /* dark muted gray */ 56 + --muted-foreground: oklch(0.708 0 0); /* medium gray on muted */ 57 + --accent: oklch(0.371 0 0); /* medium-dark accent gray */ 58 + --accent-foreground: oklch(0.985 0 0); /* near-white on accent */ 59 + --destructive: oklch(0.704 0.191 22.216); /* bright warm red/orange */ 60 + --border: oklch(1 0 0 / 10%); /* subtle light border on dark */ 61 + --input: oklch(1 0 0 / 15%); /* subtle light input on dark */ 62 + --ring: oklch(0.556 0 0); /* medium gray ring on dark */ 63 + --chart-1: oklch(0.88 0.17 325); /* very light lilac on dark */ 64 + --chart-2: oklch(0.84 0.19 325); /* light lilac on dark */ 65 + --chart-3: oklch(0.8 0.2 325); /* mid lilac on dark */ 66 + --chart-4: oklch(0.75 0.2 325); /* deeper lilac on dark */ 67 + --chart-5: oklch(0.7 0.19 325); /* deepest lilac on dark */ 68 + --sidebar: oklch(0.205 0 0); /* very dark gray sidebar */ 69 + --sidebar-foreground: oklch(0.985 0 0); /* near-white sidebar text */ 70 + --sidebar-primary: oklch(0.8 0.2 325); /* saturated lilac sidebar accent */ 71 + --sidebar-primary-foreground: oklch(0.2 0.06 325); /* deep plum text on accent */ 72 + --sidebar-accent: oklch(0.269 0 0); /* dark accent gray */ 73 + --sidebar-accent-foreground: oklch(0.985 0 0); /* near-white on accent */ 74 + --sidebar-border: oklch(1 0 0 / 10%); /* subtle light sidebar border */ 75 + --sidebar-ring: oklch(0.556 0 0); /* medium gray sidebar ring */ 349 76 } 350 77 351 78 @theme inline { 79 + --font-heading: var(--font-heading); 80 + --color-sidebar-ring: var(--sidebar-ring); 81 + --color-sidebar-border: var(--sidebar-border); 82 + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); 83 + --color-sidebar-accent: var(--sidebar-accent); 84 + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); 85 + --color-sidebar-primary: var(--sidebar-primary); 86 + --color-sidebar-foreground: var(--sidebar-foreground); 87 + --color-sidebar: var(--sidebar); 88 + --color-chart-5: var(--chart-5); 89 + --color-chart-4: var(--chart-4); 90 + --color-chart-3: var(--chart-3); 91 + --color-chart-2: var(--chart-2); 92 + --color-chart-1: var(--chart-1); 93 + --color-ring: var(--ring); 94 + --color-input: var(--input); 95 + --color-border: var(--border); 96 + --color-destructive: var(--destructive); 97 + --color-accent-foreground: var(--accent-foreground); 98 + --color-accent: var(--accent); 99 + --color-muted-foreground: var(--muted-foreground); 100 + --color-muted: var(--muted); 101 + --color-secondary-foreground: var(--secondary-foreground); 102 + --color-secondary: var(--secondary); 103 + --color-primary-foreground: var(--primary-foreground); 104 + --color-primary: var(--primary); 105 + --color-popover-foreground: var(--popover-foreground); 106 + --color-popover: var(--popover); 107 + --color-card-foreground: var(--card-foreground); 108 + --color-card: var(--card); 109 + --color-foreground: var(--foreground); 110 + --color-background: var(--background); 352 111 --radius-sm: calc(var(--radius) - 4px); 353 112 --radius-md: calc(var(--radius) - 2px); 354 113 --radius-lg: var(--radius); ··· 356 115 --radius-2xl: calc(var(--radius) + 8px); 357 116 --radius-3xl: calc(var(--radius) + 12px); 358 117 --radius-4xl: calc(var(--radius) + 16px); 359 - --color-background: var(--background); 360 - --color-foreground: var(--foreground); 361 - --color-card: var(--card); 362 - --color-card-foreground: var(--card-foreground); 363 - --color-popover: var(--popover); 364 - --color-popover-foreground: var(--popover-foreground); 365 - --color-primary: var(--primary); 366 - --color-primary-foreground: var(--primary-foreground); 367 - --color-secondary: var(--secondary); 368 - --color-secondary-foreground: var(--secondary-foreground); 369 - --color-muted: var(--muted); 370 - --color-muted-foreground: var(--muted-foreground); 371 - --color-accent: var(--accent); 372 - --color-accent-foreground: var(--accent-foreground); 373 - --color-destructive: var(--destructive); 374 - --color-border: var(--border); 375 - --color-input: var(--input); 376 - --color-ring: var(--ring); 377 - --color-chart-1: var(--chart-1); 378 - --color-chart-2: var(--chart-2); 379 - --color-chart-3: var(--chart-3); 380 - --color-chart-4: var(--chart-4); 381 - --color-chart-5: var(--chart-5); 382 - --color-sidebar: var(--sidebar); 383 - --color-sidebar-foreground: var(--sidebar-foreground); 384 - --color-sidebar-primary: var(--sidebar-primary); 385 - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); 386 - --color-sidebar-accent: var(--sidebar-accent); 387 - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); 388 - --color-sidebar-border: var(--sidebar-border); 389 - --color-sidebar-ring: var(--sidebar-ring); 390 - } 118 + --animate-marquee: marquee 80s linear infinite; 391 119 392 - .dark { 393 - --background: oklch(0.141 0.005 285.823); 394 - --foreground: oklch(0.985 0 0); 395 - --card: oklch(0.21 0.006 285.885); 396 - --card-foreground: oklch(0.985 0 0); 397 - --popover: oklch(0.21 0.006 285.885); 398 - --popover-foreground: oklch(0.985 0 0); 399 - --primary: oklch(0.92 0.004 286.32); 400 - --primary-foreground: oklch(0.21 0.006 285.885); 401 - --secondary: oklch(0.274 0.006 286.033); 402 - --secondary-foreground: oklch(0.985 0 0); 403 - --muted: oklch(0.274 0.006 286.033); 404 - --muted-foreground: oklch(0.705 0.015 286.067); 405 - --accent: oklch(0.274 0.006 286.033); 406 - --accent-foreground: oklch(0.985 0 0); 407 - --destructive: oklch(0.704 0.191 22.216); 408 - --border: oklch(1 0 0 / 10%); 409 - --input: oklch(1 0 0 / 15%); 410 - --ring: oklch(0.552 0.016 285.938); 411 - --chart-1: oklch(0.488 0.243 264.376); 412 - --chart-2: oklch(0.696 0.17 162.48); 413 - --chart-3: oklch(0.769 0.188 70.08); 414 - --chart-4: oklch(0.627 0.265 303.9); 415 - --chart-5: oklch(0.645 0.246 16.439); 416 - --sidebar: oklch(0.21 0.006 285.885); 417 - --sidebar-foreground: oklch(0.985 0 0); 418 - --sidebar-primary: oklch(0.488 0.243 264.376); 419 - --sidebar-primary-foreground: oklch(0.985 0 0); 420 - --sidebar-accent: oklch(0.274 0.006 286.033); 421 - --sidebar-accent-foreground: oklch(0.985 0 0); 422 - --sidebar-border: oklch(1 0 0 / 10%); 423 - --sidebar-ring: oklch(0.552 0.016 285.938); 120 + @keyframes marquee { 121 + 0% { 122 + transform: translate3d(0, 0, 0); 123 + } 124 + 100% { 125 + transform: translate3d(-50%, 0, 0); 126 + } 127 + } 424 128 } 425 129 426 130 @layer base { ··· 428 132 @apply border-border outline-ring/50; 429 133 } 430 134 body { 431 - @apply bg-background text-foreground; 135 + @apply bg-transparent text-foreground; 432 136 } 433 137 }
+34 -14
app/layout.tsx
··· 1 1 import type { Metadata } from "next"; 2 2 import { SpeedInsights } from "@vercel/speed-insights/next"; 3 3 import { Analytics } from "@vercel/analytics/next"; 4 - import { Space_Grotesk } from "next/font/google"; 4 + import { createClient } from "@/lib/supabase/server"; 5 + import { SiteHeader } from "@/components/site-header"; 6 + import { Footer } from "@/components/footer"; 7 + import { SiteBackground } from "@/components/site-background"; 5 8 6 9 import "./globals.css"; 10 + import { Doto, Fira_Mono } from "next/font/google"; 7 11 8 - const fontSans = Space_Grotesk({ 12 + const firaMono = Fira_Mono({ 9 13 subsets: ["latin"], 10 - weight: ["400", "500", "600", "700"], 14 + weight: ["400", "500", "700"], 15 + variable: "--font-sans", 16 + }); 17 + 18 + const doto = Doto({ 19 + subsets: ["latin"], 20 + variable: "--font-heading", 11 21 }); 12 22 13 23 interface LayoutProps { ··· 19 29 default: "eny.space", 20 30 template: "%s | eny.space", 21 31 }, 32 + icons: { 33 + icon: [ 34 + { url: "/favicon.svg", type: "image/svg+xml" }, 35 + { url: "/favicon-96x96.png", sizes: "96x96", type: "image/png" }, 36 + { url: "/favicon.ico", sizes: "16x16 32x32 48x48", type: "image/x-icon" }, 37 + ], 38 + apple: [{ url: "/apple-touch-icon.png", sizes: "180x180", type: "image/png" }], 39 + shortcut: "/favicon.ico", 40 + }, 22 41 twitter: { 23 42 card: "summary_large_image", 24 43 description: "eny.space – your data, your space, use it enywhere.", 25 44 }, 26 45 }; 27 46 28 - export default function RootLayout({ children }: LayoutProps) { 47 + export default async function RootLayout({ children }: LayoutProps) { 48 + const supabase = await createClient(); 49 + const { 50 + data: { user }, 51 + } = await supabase.auth.getUser(); 52 + 29 53 return ( 30 - <html lang="en"> 31 - <body className={fontSans.className}> 32 - <div className="container"> 33 - <header> 34 - <div className="header-content"> 35 - <h1>eny.space</h1> 36 - </div> 37 - </header> 38 - {children} 39 - </div> 54 + <html lang="en" className={`${firaMono.variable} ${doto.variable}`}> 55 + <body className="min-h-screen flex flex-col"> 56 + <SiteBackground /> 57 + <SiteHeader user={user} /> 58 + <main className="flex-1">{children}</main> 59 + <Footer /> 40 60 <SpeedInsights /> 41 61 <Analytics /> 42 62 </body>
+94
app/login/page.tsx
··· 1 + import Link from "next/link"; 2 + import { signIn } from "@/actions/auth"; 3 + import { Button } from "@/actions/components/ui/button"; 4 + import { 5 + Card, 6 + CardContent, 7 + CardDescription, 8 + CardHeader, 9 + CardTitle, 10 + CardFooter, 11 + } from "@/actions/components/ui/card"; 12 + import { Input } from "@/actions/components/ui/input"; 13 + import { Label } from "@/actions/components/ui/label"; 14 + 15 + type LoginPageProps = { 16 + searchParams?: { 17 + auto_checkout?: string; 18 + pds_plan?: string; 19 + pds_username?: string; 20 + pds_hostname?: string; 21 + pds_disksize_gb?: string; 22 + }; 23 + }; 24 + 25 + export default function LoginPage({ searchParams }: LoginPageProps) { 26 + const nextParams = new URLSearchParams(); 27 + if (searchParams?.auto_checkout) { 28 + nextParams.set("auto_checkout", searchParams.auto_checkout); 29 + } 30 + if (searchParams?.pds_plan) { 31 + nextParams.set("pds_plan", searchParams.pds_plan); 32 + } 33 + if (searchParams?.pds_username) { 34 + nextParams.set("pds_username", searchParams.pds_username); 35 + } 36 + if (searchParams?.pds_hostname) { 37 + nextParams.set("pds_hostname", searchParams.pds_hostname); 38 + } 39 + if (searchParams?.pds_disksize_gb) { 40 + nextParams.set("pds_disksize_gb", searchParams.pds_disksize_gb); 41 + } 42 + 43 + const next = `/dashboard${nextParams.toString() ? `?${nextParams.toString()}` : ""}`; 44 + const signupHref = `/signup${nextParams.toString() ? `?${nextParams.toString()}` : ""}`; 45 + 46 + return ( 47 + <main className="flex min-h-[60vh] items-center justify-center px-4"> 48 + <Card className="w-full max-w-sm"> 49 + <CardHeader> 50 + <CardTitle>Login</CardTitle> 51 + <CardDescription> 52 + Sign in to access your eny.space dashboard. 53 + </CardDescription> 54 + </CardHeader> 55 + <CardContent> 56 + <form action={signIn} className="space-y-4"> 57 + <input type="hidden" name="next" value={next} /> 58 + <div className="space-y-2"> 59 + <Label htmlFor="email">Email</Label> 60 + <Input 61 + id="email" 62 + name="email" 63 + type="email" 64 + autoComplete="email" 65 + required 66 + /> 67 + </div> 68 + <div className="space-y-2"> 69 + <Label htmlFor="password">Password</Label> 70 + <Input 71 + id="password" 72 + name="password" 73 + type="password" 74 + autoComplete="current-password" 75 + required 76 + /> 77 + </div> 78 + <Button type="submit" className="w-full"> 79 + Login 80 + </Button> 81 + </form> 82 + </CardContent> 83 + <CardFooter className="flex justify-center text-sm text-muted-foreground"> 84 + <span> 85 + Don&apos;t have an account?{" "} 86 + <Link href={signupHref} className="underline underline-offset-4"> 87 + Sign up 88 + </Link> 89 + </span> 90 + </CardFooter> 91 + </Card> 92 + </main> 93 + ); 94 + }
+24
app/not-found.tsx
··· 1 + import { Heading } from "@/components/heading"; 2 + import { ButtonLink } from "@/components/button-link"; 3 + 4 + export default function NotFound() { 5 + return ( 6 + <div className="flex flex-col items-center justify-center gap-6 py-32 text-center"> 7 + <Heading className="text-5xl tracking-tight text-white sm:text-6xl md:text-7xl"> 8 + you've drifted past the heliopause. 9 + </Heading> 10 + <Heading as="h2" className="text-2xl text-white/50"> 11 + 404 12 + </Heading> 13 + <p className="text-muted-foreground max-w-sm"> 14 + you've gone too far into the unknown. this page doesn't exist. 15 + </p> 16 + <ButtonLink 17 + href="/" 18 + className="bg-primary text-primary-foreground hover:bg-primary/90" 19 + > 20 + Go home 21 + </ButtonLink> 22 + </div> 23 + ); 24 + }
+16 -66
app/page.tsx
··· 1 - import type { Metadata } from "next"; 1 + import { Hero } from "@/components/hero/hero"; 2 + import { LogoBar } from "@/components/logo-bar"; 3 + import { FeaturesSection } from "@/components/features"; 4 + import { PricingSection } from "@/components/pricing"; 5 + import { FAQSection } from "@/components/faq"; 6 + import { CTASection } from "@/components/cta"; 7 + import { PrelaunchSection } from "./components/prelaunch"; 2 8 3 - import Link from "next/link"; 4 - 5 - export const metadata: Metadata = { 6 - title: "eny.space – your data, your space, use it enywhere", 7 - }; 8 - 9 - export default function IndexPage(): JSX.Element { 9 + export default function Page() { 10 10 return ( 11 - <main className="page-container"> 12 - <h1>Your own custom PDS in seconds</h1> 13 - <h2>One-click ATProto hosting with eny.space</h2> 14 - <p> 15 - We&apos;re building a managed ATProto Personal Data Server (PDS) 16 - platform so you can focus on your product while we handle the 17 - infrastructure, scaling, and compliance. 18 - </p> 19 - 20 - <h3>What&apos;s coming soon</h3> 21 - <ul> 22 - <li>One-click provisioning of dedicated ATProto PDS instances</li> 23 - <li>Automatic backups and seamless upgrades</li> 24 - <li>Usage-based pricing with clear, predictable costs</li> 25 - </ul> 26 - 27 - <h3>Be the first to know</h3> 28 - <p> 29 - We&apos;re onboarding early adopters now. If you&apos;re building on 30 - ATProto and want reliable managed hosting, we&apos;d love to hear from 31 - you. 32 - </p> 33 - 34 - <div 35 - style={{ display: "flex", gap: 12, marginTop: 24, flexWrap: "wrap" }} 36 - > 37 - <Link 38 - href="mailto:hello@krekeny.com?subject=I%27d%20like%20early%20access%20to%20eny.space%20PDS" 39 - style={{ 40 - display: "inline-block", 41 - padding: "12px 24px", 42 - borderRadius: 6, 43 - backgroundColor: "#000000", 44 - color: "#ffffff", 45 - border: "1px solid #ffffff", 46 - textDecoration: "none", 47 - fontWeight: 600, 48 - }} 49 - > 50 - Request early access 51 - </Link> 52 - {/* <Link 53 - href="/checkout" 54 - style={{ 55 - display: "inline-block", 56 - padding: "12px 24px", 57 - borderRadius: 6, 58 - backgroundColor: "#ffffff", 59 - color: "#000000", 60 - border: "1px solid #ffffff", 61 - textDecoration: "none", 62 - fontWeight: 600, 63 - }} 64 - > 65 - Get yours 66 - </Link> */} 67 - </div> 68 - </main> 11 + <> 12 + <Hero /> 13 + <LogoBar /> 14 + <FeaturesSection /> 15 + <PrelaunchSection /> <PricingSection /> 16 + <FAQSection /> 17 + <CTASection /> 18 + </> 69 19 ); 70 20 }
+28
app/signup/page.tsx
··· 1 + import { SignUpForm } from "./signup-form"; 2 + 3 + type SignUpPageProps = { 4 + searchParams?: Promise<{ 5 + auto_checkout?: string; 6 + pds_plan?: string; 7 + pds_username?: string; 8 + pds_hostname?: string; 9 + pds_disksize_gb?: string; 10 + }>; 11 + }; 12 + 13 + export default async function SignUpPage({ searchParams }: SignUpPageProps) { 14 + const params = await searchParams; 15 + const nextParams = new URLSearchParams(); 16 + 17 + if (params?.auto_checkout) nextParams.set("auto_checkout", params.auto_checkout); 18 + if (params?.pds_plan) nextParams.set("pds_plan", params.pds_plan); 19 + if (params?.pds_username) nextParams.set("pds_username", params.pds_username); 20 + if (params?.pds_hostname) nextParams.set("pds_hostname", params.pds_hostname); 21 + if (params?.pds_disksize_gb) nextParams.set("pds_disksize_gb", params.pds_disksize_gb); 22 + 23 + const qs = nextParams.toString(); 24 + const next = `/dashboard${qs ? `?${qs}` : ""}`; 25 + const loginHref = `/login${qs ? `?${qs}` : ""}`; 26 + 27 + return <SignUpForm next={next} loginHref={loginHref} />; 28 + }
+113
app/signup/signup-form.tsx
··· 1 + "use client"; 2 + 3 + import { useState, useTransition } from "react"; 4 + import Link from "next/link"; 5 + import { signUp } from "@/actions/auth"; 6 + import { Button } from "@/actions/components/ui/button"; 7 + import { 8 + Card, 9 + CardContent, 10 + CardDescription, 11 + CardHeader, 12 + CardTitle, 13 + CardFooter, 14 + } from "@/actions/components/ui/card"; 15 + import { Input } from "@/actions/components/ui/input"; 16 + import { Label } from "@/actions/components/ui/label"; 17 + 18 + interface SignUpFormProps { 19 + next: string; 20 + loginHref: string; 21 + } 22 + 23 + export function SignUpForm({ next, loginHref }: SignUpFormProps) { 24 + const [state, setState] = useState<{ 25 + error?: string; 26 + success?: boolean; 27 + } | null>(null); 28 + const [isPending, startTransition] = useTransition(); 29 + 30 + function handleSubmit(e: React.FormEvent<HTMLFormElement>) { 31 + e.preventDefault(); 32 + const formData = new FormData(e.currentTarget); 33 + startTransition(async () => { 34 + try { 35 + const result = await signUp(null, formData); 36 + setState(result); 37 + } catch { 38 + setState({ error: "An unexpected error occurred. Please try again." }); 39 + } 40 + }); 41 + } 42 + 43 + if (state?.success) { 44 + return ( 45 + <main className="flex min-h-[60vh] items-center justify-center px-4"> 46 + <Card className="w-full max-w-sm text-center"> 47 + <CardHeader> 48 + <CardTitle>Check your email</CardTitle> 49 + <CardDescription> 50 + We sent you a confirmation link. Click it to activate your account 51 + and you&apos;ll be taken to your dashboard. 52 + </CardDescription> 53 + </CardHeader> 54 + </Card> 55 + </main> 56 + ); 57 + } 58 + 59 + return ( 60 + <main className="flex min-h-[60vh] items-center justify-center px-4"> 61 + <Card className="w-full max-w-sm"> 62 + <CardHeader> 63 + <CardTitle>Create account</CardTitle> 64 + <CardDescription> 65 + Get started with eny.space in a few seconds. 66 + </CardDescription> 67 + </CardHeader> 68 + <CardContent> 69 + <form onSubmit={handleSubmit} className="space-y-4"> 70 + <input type="hidden" name="next" value={next} /> 71 + {state?.error && ( 72 + <p className="rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive"> 73 + {state.error} 74 + </p> 75 + )} 76 + <div className="space-y-2"> 77 + <Label htmlFor="email">Email</Label> 78 + <Input 79 + id="email" 80 + name="email" 81 + type="email" 82 + autoComplete="email" 83 + required 84 + /> 85 + </div> 86 + <div className="space-y-2"> 87 + <Label htmlFor="password">Password</Label> 88 + <Input 89 + id="password" 90 + name="password" 91 + type="password" 92 + minLength={6} 93 + autoComplete="new-password" 94 + required 95 + /> 96 + </div> 97 + <Button type="submit" className="w-full" disabled={isPending}> 98 + {isPending ? "Creating account…" : "Sign Up"} 99 + </Button> 100 + </form> 101 + </CardContent> 102 + <CardFooter className="flex justify-center text-sm text-muted-foreground"> 103 + <span> 104 + Already have an account?{" "} 105 + <Link href={loginHref} className="underline underline-offset-4"> 106 + Login 107 + </Link> 108 + </span> 109 + </CardFooter> 110 + </Card> 111 + </main> 112 + ); 113 + }
+102
app/welcome/page.tsx
··· 1 + import { redirect } from "next/navigation"; 2 + import { createClient } from "@/lib/supabase/server"; 3 + import { getSubscriptionStatus } from "@/actions/subscription"; 4 + import { prelaunch } from "@/lib/prelaunch"; 5 + import { 6 + Card, 7 + CardContent, 8 + CardDescription, 9 + CardHeader, 10 + CardTitle, 11 + } from "@/actions/components/ui/card"; 12 + import { ButtonLink } from "@/components/button-link"; 13 + import { Heading } from "@/components/heading"; 14 + import { Paragraph } from "@/components/paragraph"; 15 + import DashboardClient from "../dashboard/dashboard-client"; 16 + import { getPriceIdForPlan } from "@/lib/stripe-plans"; 17 + 18 + type WelcomePageProps = { 19 + searchParams?: { 20 + auto_checkout?: string; 21 + pds_plan?: string; 22 + pds_username?: string; 23 + pds_hostname?: string; 24 + pds_disksize_gb?: string; 25 + }; 26 + }; 27 + 28 + export default async function WelcomePage({ searchParams }: WelcomePageProps) { 29 + const supabase = await createClient(); 30 + const { 31 + data: { user }, 32 + } = await supabase.auth.getUser(); 33 + 34 + if (!user) { 35 + redirect("/login"); 36 + } 37 + 38 + const { subscribed, subscription } = await getSubscriptionStatus(); 39 + 40 + // If they already have access, skip the onboarding. 41 + if (subscribed) { 42 + redirect("/dashboard"); 43 + } 44 + 45 + return ( 46 + <main className="flex min-h-[60vh] items-center justify-center px-4 py-8"> 47 + <Card className="w-full max-w-2xl bg-white/5"> 48 + <CardHeader> 49 + <CardTitle>Welcome</CardTitle> 50 + <CardDescription> 51 + {prelaunch 52 + ? "Thanks for registering. We'll notify you when we're live." 53 + : "Almost there — pick a plan to activate your access."} 54 + </CardDescription> 55 + </CardHeader> 56 + 57 + <CardContent className="space-y-6"> 58 + {prelaunch ? ( 59 + <div className="space-y-3 text-white"> 60 + <Heading as="h2" className="text-base font-semibold text-white"> 61 + You're on the launch list 62 + </Heading> 63 + <Paragraph className="text-sm text-white/80"> 64 + We don't offer PDS hosting yet. Once we launch and start 65 + offering packages, we'll email you and unlock your dashboard. 66 + </Paragraph> 67 + <Paragraph className="text-xs text-white/60"> 68 + Registered as:{" "} 69 + <span className="font-mono text-white">{user.email}</span> 70 + </Paragraph> 71 + <div className="flex flex-wrap gap-3 pt-2"> 72 + <ButtonLink 73 + href="/" 74 + className="border border-white/80 bg-transparent uppercase tracking-wide text-white hover:bg-white/10 hover:border-white focus-visible:ring-white/50" 75 + > 76 + Back to home 77 + </ButtonLink> 78 + </div> 79 + </div> 80 + ) : ( 81 + <div className="space-y-4 text-white"> 82 + <Heading as="h2" className="text-base font-semibold"> 83 + Subscribe to Access 84 + </Heading> 85 + <DashboardClient 86 + subscribed={subscribed} 87 + subscription={subscription} 88 + priceId={getPriceIdForPlan(searchParams?.pds_plan)} 89 + autoCheckoutFromPlan={searchParams?.auto_checkout === "1"} 90 + pdsPlan={searchParams?.pds_plan} 91 + pdsUsername={searchParams?.pds_username} 92 + pdsHostname={searchParams?.pds_hostname} 93 + pdsDisksizeGb={searchParams?.pds_disksize_gb} 94 + /> 95 + </div> 96 + )} 97 + </CardContent> 98 + </Card> 99 + </main> 100 + ); 101 + } 102 +
+5 -2
components.json
··· 1 1 { 2 2 "$schema": "https://ui.shadcn.com/schema.json", 3 - "style": "new-york", 3 + "style": "radix-nova", 4 4 "rsc": true, 5 5 "tsx": true, 6 6 "tailwind": { 7 7 "config": "", 8 8 "css": "app/globals.css", 9 - "baseColor": "zinc", 9 + "baseColor": "neutral", 10 10 "cssVariables": true, 11 11 "prefix": "" 12 12 }, 13 13 "iconLibrary": "lucide", 14 + "rtl": false, 14 15 "aliases": { 15 16 "components": "@/actions/components", 16 17 "utils": "@/actions/lib/utils", ··· 18 19 "lib": "@/actions/lib", 19 20 "hooks": "@/actions/hooks" 20 21 }, 22 + "menuColor": "default", 23 + "menuAccent": "subtle", 21 24 "registries": {} 22 25 }
-6
config/index.ts
··· 1 - export const CURRENCY = "eur"; 2 - // Set your amount limits: Use float for decimal currencies and 3 - // Integer for zero-decimal currencies: https://stripe.com/docs/currencies#zero-decimal. 4 - export const MIN_AMOUNT = 10.0; 5 - export const MAX_AMOUNT = 100.0; 6 - export const AMOUNT_STEP = 1.0;
+9
lib/prelaunch.ts
··· 1 + /** 2 + * Feature flag for “prelaunch” mode. 3 + * 4 + * Set `NEXT_PUBLIC_PRELAUNCH=true` to enable prelaunch gating that hides 5 + * elements meant to ship only after launch. 6 + */ 7 + export const prelaunch = 8 + process.env.NEXT_PUBLIC_PRELAUNCH?.toLowerCase() === "true"; 9 +
+84
lib/stripe-plans.ts
··· 1 + import { stripe } from "@/lib/stripe"; 2 + 3 + /** Matches Stripe product names: Personal, Community, Business */ 4 + export const PLAN_KEYS = ["personal", "community", "business"] as const; 5 + export type PlanKey = (typeof PLAN_KEYS)[number]; 6 + 7 + /** Old query-param keys → current plan keys (backwards compatibility). */ 8 + const LEGACY_PLAN_KEYS: Record<string, PlanKey> = { 9 + starter: "personal", 10 + growth: "community", 11 + pro: "business", 12 + }; 13 + 14 + function getDefaultFallbackPriceId(): string | null { 15 + const fallback = process.env.NEXT_PUBLIC_STRIPE_PRICE_ID; 16 + return fallback && fallback.trim().length ? fallback : null; 17 + } 18 + 19 + function getEnvPriceId(planKey: PlanKey): string | null { 20 + const fallback = getDefaultFallbackPriceId(); 21 + 22 + const map: Record<PlanKey, string | undefined> = { 23 + personal: process.env.NEXT_PUBLIC_STRIPE_PRICE_PERSONAL_ID, 24 + community: process.env.NEXT_PUBLIC_STRIPE_PRICE_COMMUNITY_ID, 25 + business: process.env.NEXT_PUBLIC_STRIPE_PRICE_BUSINESS_ID, 26 + }; 27 + 28 + return (map[planKey] && map[planKey]!.trim().length ? map[planKey]! : fallback) ?? null; 29 + } 30 + 31 + function normalizePlanKey(planKey: string | undefined | null): PlanKey { 32 + const raw = (planKey || "personal").toLowerCase(); 33 + const fromLegacy = LEGACY_PLAN_KEYS[raw]; 34 + const candidate = fromLegacy ?? raw; 35 + return (PLAN_KEYS as readonly string[]).includes(candidate) 36 + ? (candidate as PlanKey) 37 + : "personal"; 38 + } 39 + 40 + export function getPriceIdForPlan(planKey: string | undefined | null): string { 41 + const key = normalizePlanKey(planKey); 42 + return getEnvPriceId(key) || ""; 43 + } 44 + 45 + type StripePriceAmount = { 46 + priceId: string; 47 + unitAmount: number | null; 48 + currency: string | null; 49 + }; 50 + 51 + async function retrievePriceById(priceId: string): Promise<StripePriceAmount> { 52 + const price = await stripe.prices.retrieve(priceId); 53 + return { 54 + priceId, 55 + unitAmount: price.unit_amount ?? null, 56 + currency: price.currency ?? null, 57 + }; 58 + } 59 + 60 + /** 61 + * Fetch amounts for each plan from Stripe (using Price IDs from env). 62 + * 63 + * Note: this is server-side only; it never exposes Stripe secrets to the client. 64 + */ 65 + export async function getStripePlanAmounts(): Promise< 66 + Record<PlanKey, StripePriceAmount> 67 + > { 68 + const results = {} as Record<PlanKey, StripePriceAmount>; 69 + 70 + await Promise.all( 71 + PLAN_KEYS.map(async (planKey) => { 72 + const priceId = getEnvPriceId(planKey); 73 + 74 + if (!priceId) { 75 + results[planKey] = { priceId: "", unitAmount: null, currency: null }; 76 + return; 77 + } 78 + 79 + results[planKey] = await retrievePriceById(priceId); 80 + }), 81 + ); 82 + 83 + return results; 84 + }
+21
lib/supabase/admin.ts
··· 1 + import { createClient } from "@supabase/supabase-js"; 2 + 3 + // Admin client for server-side operations that bypass RLS 4 + // Use this ONLY in server-side code that needs to bypass RLS (like webhooks) 5 + export function createAdminClient() { 6 + const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL; 7 + const supabaseServiceKey = process.env.SUPABASE_SERVICE_ROLE_KEY; 8 + 9 + if (!supabaseUrl || !supabaseServiceKey) { 10 + throw new Error( 11 + "Missing Supabase admin credentials. Please set NEXT_PUBLIC_SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY in your environment variables." 12 + ); 13 + } 14 + 15 + return createClient(supabaseUrl, supabaseServiceKey, { 16 + auth: { 17 + autoRefreshToken: false, 18 + persistSession: false, 19 + }, 20 + }); 21 + }
+8
lib/supabase/client.ts
··· 1 + import { createBrowserClient } from "@supabase/ssr"; 2 + 3 + export function createClient() { 4 + return createBrowserClient( 5 + process.env.NEXT_PUBLIC_SUPABASE_URL!, 6 + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! 7 + ); 8 + }
+29
lib/supabase/middleware.ts
··· 1 + import { createServerClient } from "@supabase/ssr"; 2 + import { type NextRequest, NextResponse } from "next/server"; 3 + 4 + export function createMiddlewareClient(request: NextRequest) { 5 + let response = NextResponse.next({ request }); 6 + 7 + const supabase = createServerClient( 8 + process.env.NEXT_PUBLIC_SUPABASE_URL!, 9 + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, 10 + { 11 + cookies: { 12 + getAll() { 13 + return request.cookies.getAll(); 14 + }, 15 + setAll(cookiesToSet) { 16 + cookiesToSet.forEach(({ name, value }) => 17 + request.cookies.set(name, value) 18 + ); 19 + response = NextResponse.next({ request }); 20 + cookiesToSet.forEach(({ name, value, options }) => 21 + response.cookies.set(name, value, options) 22 + ); 23 + }, 24 + }, 25 + } 26 + ); 27 + 28 + return { supabase, response }; 29 + }
+29
lib/supabase/server.ts
··· 1 + import { createServerClient } from "@supabase/ssr"; 2 + import { cookies } from "next/headers"; 3 + 4 + export async function createClient() { 5 + const cookieStore = await cookies(); 6 + 7 + return createServerClient( 8 + process.env.NEXT_PUBLIC_SUPABASE_URL!, 9 + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, 10 + { 11 + cookies: { 12 + getAll() { 13 + return cookieStore.getAll(); 14 + }, 15 + setAll(cookiesToSet) { 16 + try { 17 + cookiesToSet.forEach(({ name, value, options }) => 18 + cookieStore.set(name, value, options) 19 + ); 20 + } catch { 21 + // The `setAll` method was called from a Server Component. 22 + // This can be ignored if you have middleware refreshing 23 + // user sessions. 24 + } 25 + }, 26 + }, 27 + } 28 + ); 29 + }
+22
middleware.ts
··· 1 + import { type NextRequest, NextResponse } from "next/server"; 2 + import { createMiddlewareClient } from "@/lib/supabase/middleware"; 3 + 4 + const AUTH_ROUTES = ["/login", "/signup"]; 5 + 6 + export async function middleware(request: NextRequest) { 7 + const { supabase, response } = createMiddlewareClient(request); 8 + 9 + const { 10 + data: { user }, 11 + } = await supabase.auth.getUser(); 12 + 13 + if (user && AUTH_ROUTES.includes(request.nextUrl.pathname)) { 14 + return NextResponse.redirect(new URL("/dashboard", request.url)); 15 + } 16 + 17 + return response; 18 + } 19 + 20 + export const config = { 21 + matcher: ["/login", "/signup"], 22 + };
+5686 -370
package-lock.json
··· 5 5 "packages": { 6 6 "": { 7 7 "dependencies": { 8 + "@base-ui/react": "^1.2.0", 8 9 "@radix-ui/react-slot": "^1.2.4", 9 - "@stripe/react-stripe-js": "2.4.0", 10 - "@stripe/stripe-js": "2.2.2", 10 + "@supabase/ssr": "^0.8.0", 11 + "@supabase/supabase-js": "^2.90.1", 11 12 "@tailwindcss/postcss": "^4.1.18", 12 13 "@vercel/analytics": "^1.6.1", 13 14 "@vercel/speed-insights": "^1.3.1", 14 15 "class-variance-authority": "^0.7.1", 15 16 "clsx": "^2.1.1", 17 + "framer-motion": "^12.35.2", 16 18 "lucide-react": "^0.562.0", 17 19 "next": "latest", 18 20 "postcss": "^8.5.6", 21 + "radix-ui": "^1.4.3", 19 22 "react": "18.2.0", 20 23 "react-dom": "18.2.0", 21 24 "server-only": "0.0.1", 25 + "shadcn": "^3.8.5", 22 26 "stripe": "14.8.0", 23 - "tailwind-merge": "^3.4.0", 27 + "tailwind-merge": "^3.5.0", 24 28 "tailwindcss": "^4.1.18" 25 29 }, 26 30 "devDependencies": { 27 31 "@types/node": "20.4.6", 28 32 "@types/react": "18.2.8", 33 + "@types/react-dom": "^18.2.8", 29 34 "tw-animate-css": "^1.4.0", 30 35 "typescript": "5.1.6" 31 36 } ··· 34 39 "version": "5.2.0", 35 40 "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", 36 41 "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", 37 - "license": "MIT", 42 + "engines": { 43 + "node": ">=10" 44 + }, 45 + "funding": { 46 + "url": "https://github.com/sponsors/sindresorhus" 47 + } 48 + }, 49 + "node_modules/@antfu/ni": { 50 + "version": "25.0.0", 51 + "resolved": "https://registry.npmjs.org/@antfu/ni/-/ni-25.0.0.tgz", 52 + "integrity": "sha512-9q/yCljni37pkMr4sPrI3G4jqdIk074+iukc5aFJl7kmDCCsiJrbZ6zKxnES1Gwg+i9RcDZwvktl23puGslmvA==", 53 + "dependencies": { 54 + "ansis": "^4.0.0", 55 + "fzf": "^0.5.2", 56 + "package-manager-detector": "^1.3.0", 57 + "tinyexec": "^1.0.1" 58 + }, 59 + "bin": { 60 + "na": "bin/na.mjs", 61 + "nci": "bin/nci.mjs", 62 + "ni": "bin/ni.mjs", 63 + "nlx": "bin/nlx.mjs", 64 + "nr": "bin/nr.mjs", 65 + "nun": "bin/nun.mjs", 66 + "nup": "bin/nup.mjs" 67 + } 68 + }, 69 + "node_modules/@babel/code-frame": { 70 + "version": "7.29.0", 71 + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", 72 + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", 73 + "dependencies": { 74 + "@babel/helper-validator-identifier": "^7.28.5", 75 + "js-tokens": "^4.0.0", 76 + "picocolors": "^1.1.1" 77 + }, 78 + "engines": { 79 + "node": ">=6.9.0" 80 + } 81 + }, 82 + "node_modules/@babel/compat-data": { 83 + "version": "7.29.0", 84 + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", 85 + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", 86 + "engines": { 87 + "node": ">=6.9.0" 88 + } 89 + }, 90 + "node_modules/@babel/core": { 91 + "version": "7.29.0", 92 + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", 93 + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", 94 + "dependencies": { 95 + "@babel/code-frame": "^7.29.0", 96 + "@babel/generator": "^7.29.0", 97 + "@babel/helper-compilation-targets": "^7.28.6", 98 + "@babel/helper-module-transforms": "^7.28.6", 99 + "@babel/helpers": "^7.28.6", 100 + "@babel/parser": "^7.29.0", 101 + "@babel/template": "^7.28.6", 102 + "@babel/traverse": "^7.29.0", 103 + "@babel/types": "^7.29.0", 104 + "@jridgewell/remapping": "^2.3.5", 105 + "convert-source-map": "^2.0.0", 106 + "debug": "^4.1.0", 107 + "gensync": "^1.0.0-beta.2", 108 + "json5": "^2.2.3", 109 + "semver": "^6.3.1" 110 + }, 111 + "engines": { 112 + "node": ">=6.9.0" 113 + }, 114 + "funding": { 115 + "type": "opencollective", 116 + "url": "https://opencollective.com/babel" 117 + } 118 + }, 119 + "node_modules/@babel/generator": { 120 + "version": "7.29.1", 121 + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", 122 + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", 123 + "dependencies": { 124 + "@babel/parser": "^7.29.0", 125 + "@babel/types": "^7.29.0", 126 + "@jridgewell/gen-mapping": "^0.3.12", 127 + "@jridgewell/trace-mapping": "^0.3.28", 128 + "jsesc": "^3.0.2" 129 + }, 130 + "engines": { 131 + "node": ">=6.9.0" 132 + } 133 + }, 134 + "node_modules/@babel/helper-annotate-as-pure": { 135 + "version": "7.27.3", 136 + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", 137 + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", 138 + "dependencies": { 139 + "@babel/types": "^7.27.3" 140 + }, 141 + "engines": { 142 + "node": ">=6.9.0" 143 + } 144 + }, 145 + "node_modules/@babel/helper-compilation-targets": { 146 + "version": "7.28.6", 147 + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", 148 + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", 149 + "dependencies": { 150 + "@babel/compat-data": "^7.28.6", 151 + "@babel/helper-validator-option": "^7.27.1", 152 + "browserslist": "^4.24.0", 153 + "lru-cache": "^5.1.1", 154 + "semver": "^6.3.1" 155 + }, 156 + "engines": { 157 + "node": ">=6.9.0" 158 + } 159 + }, 160 + "node_modules/@babel/helper-create-class-features-plugin": { 161 + "version": "7.28.6", 162 + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", 163 + "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", 164 + "dependencies": { 165 + "@babel/helper-annotate-as-pure": "^7.27.3", 166 + "@babel/helper-member-expression-to-functions": "^7.28.5", 167 + "@babel/helper-optimise-call-expression": "^7.27.1", 168 + "@babel/helper-replace-supers": "^7.28.6", 169 + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", 170 + "@babel/traverse": "^7.28.6", 171 + "semver": "^6.3.1" 172 + }, 173 + "engines": { 174 + "node": ">=6.9.0" 175 + }, 176 + "peerDependencies": { 177 + "@babel/core": "^7.0.0" 178 + } 179 + }, 180 + "node_modules/@babel/helper-globals": { 181 + "version": "7.28.0", 182 + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", 183 + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", 184 + "engines": { 185 + "node": ">=6.9.0" 186 + } 187 + }, 188 + "node_modules/@babel/helper-member-expression-to-functions": { 189 + "version": "7.28.5", 190 + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", 191 + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", 192 + "dependencies": { 193 + "@babel/traverse": "^7.28.5", 194 + "@babel/types": "^7.28.5" 195 + }, 196 + "engines": { 197 + "node": ">=6.9.0" 198 + } 199 + }, 200 + "node_modules/@babel/helper-module-imports": { 201 + "version": "7.28.6", 202 + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", 203 + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", 204 + "dependencies": { 205 + "@babel/traverse": "^7.28.6", 206 + "@babel/types": "^7.28.6" 207 + }, 208 + "engines": { 209 + "node": ">=6.9.0" 210 + } 211 + }, 212 + "node_modules/@babel/helper-module-transforms": { 213 + "version": "7.28.6", 214 + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", 215 + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", 216 + "dependencies": { 217 + "@babel/helper-module-imports": "^7.28.6", 218 + "@babel/helper-validator-identifier": "^7.28.5", 219 + "@babel/traverse": "^7.28.6" 220 + }, 221 + "engines": { 222 + "node": ">=6.9.0" 223 + }, 224 + "peerDependencies": { 225 + "@babel/core": "^7.0.0" 226 + } 227 + }, 228 + "node_modules/@babel/helper-optimise-call-expression": { 229 + "version": "7.27.1", 230 + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", 231 + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", 232 + "dependencies": { 233 + "@babel/types": "^7.27.1" 234 + }, 235 + "engines": { 236 + "node": ">=6.9.0" 237 + } 238 + }, 239 + "node_modules/@babel/helper-plugin-utils": { 240 + "version": "7.28.6", 241 + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", 242 + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", 243 + "engines": { 244 + "node": ">=6.9.0" 245 + } 246 + }, 247 + "node_modules/@babel/helper-replace-supers": { 248 + "version": "7.28.6", 249 + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", 250 + "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", 251 + "dependencies": { 252 + "@babel/helper-member-expression-to-functions": "^7.28.5", 253 + "@babel/helper-optimise-call-expression": "^7.27.1", 254 + "@babel/traverse": "^7.28.6" 255 + }, 256 + "engines": { 257 + "node": ">=6.9.0" 258 + }, 259 + "peerDependencies": { 260 + "@babel/core": "^7.0.0" 261 + } 262 + }, 263 + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { 264 + "version": "7.27.1", 265 + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", 266 + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", 267 + "dependencies": { 268 + "@babel/traverse": "^7.27.1", 269 + "@babel/types": "^7.27.1" 270 + }, 271 + "engines": { 272 + "node": ">=6.9.0" 273 + } 274 + }, 275 + "node_modules/@babel/helper-string-parser": { 276 + "version": "7.27.1", 277 + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", 278 + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", 279 + "engines": { 280 + "node": ">=6.9.0" 281 + } 282 + }, 283 + "node_modules/@babel/helper-validator-identifier": { 284 + "version": "7.28.5", 285 + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", 286 + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", 287 + "engines": { 288 + "node": ">=6.9.0" 289 + } 290 + }, 291 + "node_modules/@babel/helper-validator-option": { 292 + "version": "7.27.1", 293 + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", 294 + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", 295 + "engines": { 296 + "node": ">=6.9.0" 297 + } 298 + }, 299 + "node_modules/@babel/helpers": { 300 + "version": "7.28.6", 301 + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", 302 + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", 303 + "dependencies": { 304 + "@babel/template": "^7.28.6", 305 + "@babel/types": "^7.28.6" 306 + }, 307 + "engines": { 308 + "node": ">=6.9.0" 309 + } 310 + }, 311 + "node_modules/@babel/parser": { 312 + "version": "7.29.0", 313 + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", 314 + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", 315 + "dependencies": { 316 + "@babel/types": "^7.29.0" 317 + }, 318 + "bin": { 319 + "parser": "bin/babel-parser.js" 320 + }, 321 + "engines": { 322 + "node": ">=6.0.0" 323 + } 324 + }, 325 + "node_modules/@babel/plugin-syntax-jsx": { 326 + "version": "7.28.6", 327 + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", 328 + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", 329 + "dependencies": { 330 + "@babel/helper-plugin-utils": "^7.28.6" 331 + }, 332 + "engines": { 333 + "node": ">=6.9.0" 334 + }, 335 + "peerDependencies": { 336 + "@babel/core": "^7.0.0-0" 337 + } 338 + }, 339 + "node_modules/@babel/plugin-syntax-typescript": { 340 + "version": "7.28.6", 341 + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", 342 + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", 343 + "dependencies": { 344 + "@babel/helper-plugin-utils": "^7.28.6" 345 + }, 346 + "engines": { 347 + "node": ">=6.9.0" 348 + }, 349 + "peerDependencies": { 350 + "@babel/core": "^7.0.0-0" 351 + } 352 + }, 353 + "node_modules/@babel/plugin-transform-modules-commonjs": { 354 + "version": "7.28.6", 355 + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", 356 + "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", 357 + "dependencies": { 358 + "@babel/helper-module-transforms": "^7.28.6", 359 + "@babel/helper-plugin-utils": "^7.28.6" 360 + }, 361 + "engines": { 362 + "node": ">=6.9.0" 363 + }, 364 + "peerDependencies": { 365 + "@babel/core": "^7.0.0-0" 366 + } 367 + }, 368 + "node_modules/@babel/plugin-transform-typescript": { 369 + "version": "7.28.6", 370 + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.6.tgz", 371 + "integrity": "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==", 372 + "dependencies": { 373 + "@babel/helper-annotate-as-pure": "^7.27.3", 374 + "@babel/helper-create-class-features-plugin": "^7.28.6", 375 + "@babel/helper-plugin-utils": "^7.28.6", 376 + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", 377 + "@babel/plugin-syntax-typescript": "^7.28.6" 378 + }, 379 + "engines": { 380 + "node": ">=6.9.0" 381 + }, 382 + "peerDependencies": { 383 + "@babel/core": "^7.0.0-0" 384 + } 385 + }, 386 + "node_modules/@babel/preset-typescript": { 387 + "version": "7.28.5", 388 + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz", 389 + "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==", 390 + "dependencies": { 391 + "@babel/helper-plugin-utils": "^7.27.1", 392 + "@babel/helper-validator-option": "^7.27.1", 393 + "@babel/plugin-syntax-jsx": "^7.27.1", 394 + "@babel/plugin-transform-modules-commonjs": "^7.27.1", 395 + "@babel/plugin-transform-typescript": "^7.28.5" 396 + }, 397 + "engines": { 398 + "node": ">=6.9.0" 399 + }, 400 + "peerDependencies": { 401 + "@babel/core": "^7.0.0-0" 402 + } 403 + }, 404 + "node_modules/@babel/runtime": { 405 + "version": "7.28.6", 406 + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", 407 + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", 408 + "engines": { 409 + "node": ">=6.9.0" 410 + } 411 + }, 412 + "node_modules/@babel/template": { 413 + "version": "7.28.6", 414 + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", 415 + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", 416 + "dependencies": { 417 + "@babel/code-frame": "^7.28.6", 418 + "@babel/parser": "^7.28.6", 419 + "@babel/types": "^7.28.6" 420 + }, 421 + "engines": { 422 + "node": ">=6.9.0" 423 + } 424 + }, 425 + "node_modules/@babel/traverse": { 426 + "version": "7.29.0", 427 + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", 428 + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", 429 + "dependencies": { 430 + "@babel/code-frame": "^7.29.0", 431 + "@babel/generator": "^7.29.0", 432 + "@babel/helper-globals": "^7.28.0", 433 + "@babel/parser": "^7.29.0", 434 + "@babel/template": "^7.28.6", 435 + "@babel/types": "^7.29.0", 436 + "debug": "^4.3.1" 437 + }, 438 + "engines": { 439 + "node": ">=6.9.0" 440 + } 441 + }, 442 + "node_modules/@babel/types": { 443 + "version": "7.29.0", 444 + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", 445 + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", 446 + "dependencies": { 447 + "@babel/helper-string-parser": "^7.27.1", 448 + "@babel/helper-validator-identifier": "^7.28.5" 449 + }, 450 + "engines": { 451 + "node": ">=6.9.0" 452 + } 453 + }, 454 + "node_modules/@base-ui/react": { 455 + "version": "1.2.0", 456 + "resolved": "https://registry.npmjs.org/@base-ui/react/-/react-1.2.0.tgz", 457 + "integrity": "sha512-O6aEQHcm+QyGTFY28xuwRD3SEJGZOBDpyjN2WvpfWYFVhg+3zfXPysAILqtM0C1kWC82MccOE/v1j+GHXE4qIw==", 458 + "dependencies": { 459 + "@babel/runtime": "^7.28.6", 460 + "@base-ui/utils": "0.2.5", 461 + "@floating-ui/react-dom": "^2.1.6", 462 + "@floating-ui/utils": "^0.2.10", 463 + "tabbable": "^6.4.0", 464 + "use-sync-external-store": "^1.6.0" 465 + }, 466 + "engines": { 467 + "node": ">=14.0.0" 468 + }, 469 + "funding": { 470 + "type": "opencollective", 471 + "url": "https://opencollective.com/mui-org" 472 + }, 473 + "peerDependencies": { 474 + "@types/react": "^17 || ^18 || ^19", 475 + "react": "^17 || ^18 || ^19", 476 + "react-dom": "^17 || ^18 || ^19" 477 + }, 478 + "peerDependenciesMeta": { 479 + "@types/react": { 480 + "optional": true 481 + } 482 + } 483 + }, 484 + "node_modules/@base-ui/utils": { 485 + "version": "0.2.5", 486 + "resolved": "https://registry.npmjs.org/@base-ui/utils/-/utils-0.2.5.tgz", 487 + "integrity": "sha512-oYC7w0gp76RI5MxprlGLV0wze0SErZaRl3AAkeP3OnNB/UBMb6RqNf6ZSIlxOc9Qp68Ab3C2VOcJQyRs7Xc7Vw==", 488 + "dependencies": { 489 + "@babel/runtime": "^7.28.6", 490 + "@floating-ui/utils": "^0.2.10", 491 + "reselect": "^5.1.1", 492 + "use-sync-external-store": "^1.6.0" 493 + }, 494 + "peerDependencies": { 495 + "@types/react": "^17 || ^18 || ^19", 496 + "react": "^17 || ^18 || ^19", 497 + "react-dom": "^17 || ^18 || ^19" 498 + }, 499 + "peerDependenciesMeta": { 500 + "@types/react": { 501 + "optional": true 502 + } 503 + } 504 + }, 505 + "node_modules/@dotenvx/dotenvx": { 506 + "version": "1.54.1", 507 + "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.54.1.tgz", 508 + "integrity": "sha512-41gU3q7v05GM92QPuPUf4CmUw+mmF8p4wLUh6MCRlxpCkJ9ByLcY9jUf6MwrMNmiKyG/rIckNxj9SCfmNCmCqw==", 509 + "dependencies": { 510 + "commander": "^11.1.0", 511 + "dotenv": "^17.2.1", 512 + "eciesjs": "^0.4.10", 513 + "execa": "^5.1.1", 514 + "fdir": "^6.2.0", 515 + "ignore": "^5.3.0", 516 + "object-treeify": "1.1.33", 517 + "picomatch": "^4.0.2", 518 + "which": "^4.0.0" 519 + }, 520 + "bin": { 521 + "dotenvx": "src/cli/dotenvx.js" 522 + }, 523 + "funding": { 524 + "url": "https://dotenvx.com" 525 + } 526 + }, 527 + "node_modules/@dotenvx/dotenvx/node_modules/commander": { 528 + "version": "11.1.0", 529 + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", 530 + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", 531 + "engines": { 532 + "node": ">=16" 533 + } 534 + }, 535 + "node_modules/@dotenvx/dotenvx/node_modules/execa": { 536 + "version": "5.1.1", 537 + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", 538 + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", 539 + "dependencies": { 540 + "cross-spawn": "^7.0.3", 541 + "get-stream": "^6.0.0", 542 + "human-signals": "^2.1.0", 543 + "is-stream": "^2.0.0", 544 + "merge-stream": "^2.0.0", 545 + "npm-run-path": "^4.0.1", 546 + "onetime": "^5.1.2", 547 + "signal-exit": "^3.0.3", 548 + "strip-final-newline": "^2.0.0" 549 + }, 550 + "engines": { 551 + "node": ">=10" 552 + }, 553 + "funding": { 554 + "url": "https://github.com/sindresorhus/execa?sponsor=1" 555 + } 556 + }, 557 + "node_modules/@dotenvx/dotenvx/node_modules/get-stream": { 558 + "version": "6.0.1", 559 + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", 560 + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", 38 561 "engines": { 39 562 "node": ">=10" 40 563 }, ··· 42 565 "url": "https://github.com/sponsors/sindresorhus" 43 566 } 44 567 }, 568 + "node_modules/@dotenvx/dotenvx/node_modules/human-signals": { 569 + "version": "2.1.0", 570 + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", 571 + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", 572 + "engines": { 573 + "node": ">=10.17.0" 574 + } 575 + }, 576 + "node_modules/@dotenvx/dotenvx/node_modules/is-stream": { 577 + "version": "2.0.1", 578 + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", 579 + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", 580 + "engines": { 581 + "node": ">=8" 582 + }, 583 + "funding": { 584 + "url": "https://github.com/sponsors/sindresorhus" 585 + } 586 + }, 587 + "node_modules/@dotenvx/dotenvx/node_modules/npm-run-path": { 588 + "version": "4.0.1", 589 + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", 590 + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", 591 + "dependencies": { 592 + "path-key": "^3.0.0" 593 + }, 594 + "engines": { 595 + "node": ">=8" 596 + } 597 + }, 598 + "node_modules/@dotenvx/dotenvx/node_modules/onetime": { 599 + "version": "5.1.2", 600 + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", 601 + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", 602 + "dependencies": { 603 + "mimic-fn": "^2.1.0" 604 + }, 605 + "engines": { 606 + "node": ">=6" 607 + }, 608 + "funding": { 609 + "url": "https://github.com/sponsors/sindresorhus" 610 + } 611 + }, 612 + "node_modules/@dotenvx/dotenvx/node_modules/signal-exit": { 613 + "version": "3.0.7", 614 + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 615 + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" 616 + }, 617 + "node_modules/@dotenvx/dotenvx/node_modules/strip-final-newline": { 618 + "version": "2.0.0", 619 + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", 620 + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", 621 + "engines": { 622 + "node": ">=6" 623 + } 624 + }, 625 + "node_modules/@ecies/ciphers": { 626 + "version": "0.2.5", 627 + "resolved": "https://registry.npmjs.org/@ecies/ciphers/-/ciphers-0.2.5.tgz", 628 + "integrity": "sha512-GalEZH4JgOMHYYcYmVqnFirFsjZHeoGMDt9IxEnM9F7GRUUyUksJ7Ou53L83WHJq3RWKD3AcBpo0iQh0oMpf8A==", 629 + "engines": { 630 + "bun": ">=1", 631 + "deno": ">=2", 632 + "node": ">=16" 633 + }, 634 + "peerDependencies": { 635 + "@noble/ciphers": "^1.0.0" 636 + } 637 + }, 45 638 "node_modules/@emnapi/runtime": { 46 - "version": "1.7.1", 47 - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", 48 - "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", 49 - "license": "MIT", 639 + "version": "1.8.1", 640 + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", 641 + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", 50 642 "optional": true, 51 643 "dependencies": { 52 644 "tslib": "^2.4.0" 53 645 } 54 646 }, 647 + "node_modules/@floating-ui/core": { 648 + "version": "1.7.5", 649 + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", 650 + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", 651 + "dependencies": { 652 + "@floating-ui/utils": "^0.2.11" 653 + } 654 + }, 655 + "node_modules/@floating-ui/dom": { 656 + "version": "1.7.6", 657 + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", 658 + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", 659 + "dependencies": { 660 + "@floating-ui/core": "^1.7.5", 661 + "@floating-ui/utils": "^0.2.11" 662 + } 663 + }, 664 + "node_modules/@floating-ui/react-dom": { 665 + "version": "2.1.8", 666 + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz", 667 + "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==", 668 + "dependencies": { 669 + "@floating-ui/dom": "^1.7.6" 670 + }, 671 + "peerDependencies": { 672 + "react": ">=16.8.0", 673 + "react-dom": ">=16.8.0" 674 + } 675 + }, 676 + "node_modules/@floating-ui/utils": { 677 + "version": "0.2.11", 678 + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", 679 + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==" 680 + }, 681 + "node_modules/@hono/node-server": { 682 + "version": "1.19.11", 683 + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.11.tgz", 684 + "integrity": "sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g==", 685 + "engines": { 686 + "node": ">=18.14.1" 687 + }, 688 + "peerDependencies": { 689 + "hono": "^4" 690 + } 691 + }, 55 692 "node_modules/@img/colour": { 56 - "version": "1.0.0", 57 - "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", 58 - "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", 59 - "license": "MIT", 693 + "version": "1.1.0", 694 + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", 695 + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", 60 696 "optional": true, 61 697 "engines": { 62 698 "node": ">=18" ··· 69 705 "cpu": [ 70 706 "arm64" 71 707 ], 72 - "license": "Apache-2.0", 73 708 "optional": true, 74 709 "os": [ 75 710 "darwin" ··· 91 726 "cpu": [ 92 727 "x64" 93 728 ], 94 - "license": "Apache-2.0", 95 729 "optional": true, 96 730 "os": [ 97 731 "darwin" ··· 113 747 "cpu": [ 114 748 "arm64" 115 749 ], 116 - "license": "LGPL-3.0-or-later", 117 750 "optional": true, 118 751 "os": [ 119 752 "darwin" ··· 129 762 "cpu": [ 130 763 "x64" 131 764 ], 132 - "license": "LGPL-3.0-or-later", 133 765 "optional": true, 134 766 "os": [ 135 767 "darwin" ··· 145 777 "cpu": [ 146 778 "arm" 147 779 ], 148 - "license": "LGPL-3.0-or-later", 149 780 "optional": true, 150 781 "os": [ 151 782 "linux" ··· 161 792 "cpu": [ 162 793 "arm64" 163 794 ], 164 - "license": "LGPL-3.0-or-later", 165 795 "optional": true, 166 796 "os": [ 167 797 "linux" ··· 177 807 "cpu": [ 178 808 "ppc64" 179 809 ], 180 - "license": "LGPL-3.0-or-later", 181 810 "optional": true, 182 811 "os": [ 183 812 "linux" ··· 193 822 "cpu": [ 194 823 "riscv64" 195 824 ], 196 - "license": "LGPL-3.0-or-later", 197 825 "optional": true, 198 826 "os": [ 199 827 "linux" ··· 209 837 "cpu": [ 210 838 "s390x" 211 839 ], 212 - "license": "LGPL-3.0-or-later", 213 840 "optional": true, 214 841 "os": [ 215 842 "linux" ··· 225 852 "cpu": [ 226 853 "x64" 227 854 ], 228 - "license": "LGPL-3.0-or-later", 229 855 "optional": true, 230 856 "os": [ 231 857 "linux" ··· 241 867 "cpu": [ 242 868 "arm64" 243 869 ], 244 - "license": "LGPL-3.0-or-later", 245 870 "optional": true, 246 871 "os": [ 247 872 "linux" ··· 257 882 "cpu": [ 258 883 "x64" 259 884 ], 260 - "license": "LGPL-3.0-or-later", 261 885 "optional": true, 262 886 "os": [ 263 887 "linux" ··· 273 897 "cpu": [ 274 898 "arm" 275 899 ], 276 - "license": "Apache-2.0", 277 900 "optional": true, 278 901 "os": [ 279 902 "linux" ··· 295 918 "cpu": [ 296 919 "arm64" 297 920 ], 298 - "license": "Apache-2.0", 299 921 "optional": true, 300 922 "os": [ 301 923 "linux" ··· 317 939 "cpu": [ 318 940 "ppc64" 319 941 ], 320 - "license": "Apache-2.0", 321 942 "optional": true, 322 943 "os": [ 323 944 "linux" ··· 339 960 "cpu": [ 340 961 "riscv64" 341 962 ], 342 - "license": "Apache-2.0", 343 963 "optional": true, 344 964 "os": [ 345 965 "linux" ··· 361 981 "cpu": [ 362 982 "s390x" 363 983 ], 364 - "license": "Apache-2.0", 365 984 "optional": true, 366 985 "os": [ 367 986 "linux" ··· 383 1002 "cpu": [ 384 1003 "x64" 385 1004 ], 386 - "license": "Apache-2.0", 387 1005 "optional": true, 388 1006 "os": [ 389 1007 "linux" ··· 405 1023 "cpu": [ 406 1024 "arm64" 407 1025 ], 408 - "license": "Apache-2.0", 409 1026 "optional": true, 410 1027 "os": [ 411 1028 "linux" ··· 427 1044 "cpu": [ 428 1045 "x64" 429 1046 ], 430 - "license": "Apache-2.0", 431 1047 "optional": true, 432 1048 "os": [ 433 1049 "linux" ··· 449 1065 "cpu": [ 450 1066 "wasm32" 451 1067 ], 452 - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", 453 1068 "optional": true, 454 1069 "dependencies": { 455 1070 "@emnapi/runtime": "^1.7.0" ··· 468 1083 "cpu": [ 469 1084 "arm64" 470 1085 ], 471 - "license": "Apache-2.0 AND LGPL-3.0-or-later", 472 1086 "optional": true, 473 1087 "os": [ 474 1088 "win32" ··· 487 1101 "cpu": [ 488 1102 "ia32" 489 1103 ], 490 - "license": "Apache-2.0 AND LGPL-3.0-or-later", 491 1104 "optional": true, 492 1105 "os": [ 493 1106 "win32" ··· 506 1119 "cpu": [ 507 1120 "x64" 508 1121 ], 509 - "license": "Apache-2.0 AND LGPL-3.0-or-later", 510 1122 "optional": true, 511 1123 "os": [ 512 1124 "win32" ··· 518 1130 "url": "https://opencollective.com/libvips" 519 1131 } 520 1132 }, 1133 + "node_modules/@inquirer/ansi": { 1134 + "version": "1.0.2", 1135 + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", 1136 + "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", 1137 + "engines": { 1138 + "node": ">=18" 1139 + } 1140 + }, 1141 + "node_modules/@inquirer/confirm": { 1142 + "version": "5.1.21", 1143 + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", 1144 + "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", 1145 + "dependencies": { 1146 + "@inquirer/core": "^10.3.2", 1147 + "@inquirer/type": "^3.0.10" 1148 + }, 1149 + "engines": { 1150 + "node": ">=18" 1151 + }, 1152 + "peerDependencies": { 1153 + "@types/node": ">=18" 1154 + }, 1155 + "peerDependenciesMeta": { 1156 + "@types/node": { 1157 + "optional": true 1158 + } 1159 + } 1160 + }, 1161 + "node_modules/@inquirer/core": { 1162 + "version": "10.3.2", 1163 + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", 1164 + "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", 1165 + "dependencies": { 1166 + "@inquirer/ansi": "^1.0.2", 1167 + "@inquirer/figures": "^1.0.15", 1168 + "@inquirer/type": "^3.0.10", 1169 + "cli-width": "^4.1.0", 1170 + "mute-stream": "^2.0.0", 1171 + "signal-exit": "^4.1.0", 1172 + "wrap-ansi": "^6.2.0", 1173 + "yoctocolors-cjs": "^2.1.3" 1174 + }, 1175 + "engines": { 1176 + "node": ">=18" 1177 + }, 1178 + "peerDependencies": { 1179 + "@types/node": ">=18" 1180 + }, 1181 + "peerDependenciesMeta": { 1182 + "@types/node": { 1183 + "optional": true 1184 + } 1185 + } 1186 + }, 1187 + "node_modules/@inquirer/figures": { 1188 + "version": "1.0.15", 1189 + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", 1190 + "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", 1191 + "engines": { 1192 + "node": ">=18" 1193 + } 1194 + }, 1195 + "node_modules/@inquirer/type": { 1196 + "version": "3.0.10", 1197 + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", 1198 + "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", 1199 + "engines": { 1200 + "node": ">=18" 1201 + }, 1202 + "peerDependencies": { 1203 + "@types/node": ">=18" 1204 + }, 1205 + "peerDependenciesMeta": { 1206 + "@types/node": { 1207 + "optional": true 1208 + } 1209 + } 1210 + }, 521 1211 "node_modules/@jridgewell/gen-mapping": { 522 1212 "version": "0.3.13", 523 1213 "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", 524 1214 "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", 525 - "license": "MIT", 526 1215 "dependencies": { 527 1216 "@jridgewell/sourcemap-codec": "^1.5.0", 528 1217 "@jridgewell/trace-mapping": "^0.3.24" ··· 532 1221 "version": "2.3.5", 533 1222 "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", 534 1223 "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", 535 - "license": "MIT", 536 1224 "dependencies": { 537 1225 "@jridgewell/gen-mapping": "^0.3.5", 538 1226 "@jridgewell/trace-mapping": "^0.3.24" ··· 542 1230 "version": "3.1.2", 543 1231 "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 544 1232 "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 545 - "license": "MIT", 546 1233 "engines": { 547 1234 "node": ">=6.0.0" 548 1235 } ··· 550 1237 "node_modules/@jridgewell/sourcemap-codec": { 551 1238 "version": "1.5.5", 552 1239 "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", 553 - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", 554 - "license": "MIT" 1240 + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" 555 1241 }, 556 1242 "node_modules/@jridgewell/trace-mapping": { 557 1243 "version": "0.3.31", 558 1244 "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", 559 1245 "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", 560 - "license": "MIT", 561 1246 "dependencies": { 562 1247 "@jridgewell/resolve-uri": "^3.1.0", 563 1248 "@jridgewell/sourcemap-codec": "^1.4.14" 564 1249 } 565 1250 }, 1251 + "node_modules/@modelcontextprotocol/sdk": { 1252 + "version": "1.27.1", 1253 + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.27.1.tgz", 1254 + "integrity": "sha512-sr6GbP+4edBwFndLbM60gf07z0FQ79gaExpnsjMGePXqFcSSb7t6iscpjk9DhFhwd+mTEQrzNafGP8/iGGFYaA==", 1255 + "dependencies": { 1256 + "@hono/node-server": "^1.19.9", 1257 + "ajv": "^8.17.1", 1258 + "ajv-formats": "^3.0.1", 1259 + "content-type": "^1.0.5", 1260 + "cors": "^2.8.5", 1261 + "cross-spawn": "^7.0.5", 1262 + "eventsource": "^3.0.2", 1263 + "eventsource-parser": "^3.0.0", 1264 + "express": "^5.2.1", 1265 + "express-rate-limit": "^8.2.1", 1266 + "hono": "^4.11.4", 1267 + "jose": "^6.1.3", 1268 + "json-schema-typed": "^8.0.2", 1269 + "pkce-challenge": "^5.0.0", 1270 + "raw-body": "^3.0.0", 1271 + "zod": "^3.25 || ^4.0", 1272 + "zod-to-json-schema": "^3.25.1" 1273 + }, 1274 + "engines": { 1275 + "node": ">=18" 1276 + }, 1277 + "peerDependencies": { 1278 + "@cfworker/json-schema": "^4.1.1", 1279 + "zod": "^3.25 || ^4.0" 1280 + }, 1281 + "peerDependenciesMeta": { 1282 + "@cfworker/json-schema": { 1283 + "optional": true 1284 + }, 1285 + "zod": { 1286 + "optional": false 1287 + } 1288 + } 1289 + }, 1290 + "node_modules/@mswjs/interceptors": { 1291 + "version": "0.41.3", 1292 + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.41.3.tgz", 1293 + "integrity": "sha512-cXu86tF4VQVfwz8W1SPbhoRyHJkti6mjH/XJIxp40jhO4j2k1m4KYrEykxqWPkFF3vrK4rgQppBh//AwyGSXPA==", 1294 + "dependencies": { 1295 + "@open-draft/deferred-promise": "^2.2.0", 1296 + "@open-draft/logger": "^0.3.0", 1297 + "@open-draft/until": "^2.0.0", 1298 + "is-node-process": "^1.2.0", 1299 + "outvariant": "^1.4.3", 1300 + "strict-event-emitter": "^0.5.1" 1301 + }, 1302 + "engines": { 1303 + "node": ">=18" 1304 + } 1305 + }, 566 1306 "node_modules/@next/env": { 567 - "version": "16.0.10", 568 - "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.10.tgz", 569 - "integrity": "sha512-8tuaQkyDVgeONQ1MeT9Mkk8pQmZapMKFh5B+OrFUlG3rVmYTXcXlBetBgTurKXGaIZvkoqRT9JL5K3phXcgang==", 570 - "license": "MIT" 1307 + "version": "16.1.6", 1308 + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.1.6.tgz", 1309 + "integrity": "sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==" 571 1310 }, 572 1311 "node_modules/@next/swc-darwin-arm64": { 573 - "version": "16.0.10", 574 - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.10.tgz", 575 - "integrity": "sha512-4XgdKtdVsaflErz+B5XeG0T5PeXKDdruDf3CRpnhN+8UebNa5N2H58+3GDgpn/9GBurrQ1uWW768FfscwYkJRg==", 1312 + "version": "16.1.6", 1313 + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.1.6.tgz", 1314 + "integrity": "sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw==", 576 1315 "cpu": [ 577 1316 "arm64" 578 1317 ], 579 - "license": "MIT", 580 1318 "optional": true, 581 1319 "os": [ 582 1320 "darwin" ··· 586 1324 } 587 1325 }, 588 1326 "node_modules/@next/swc-darwin-x64": { 589 - "version": "16.0.10", 590 - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.10.tgz", 591 - "integrity": "sha512-spbEObMvRKkQ3CkYVOME+ocPDFo5UqHb8EMTS78/0mQ+O1nqE8toHJVioZo4TvebATxgA8XMTHHrScPrn68OGw==", 1327 + "version": "16.1.6", 1328 + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.1.6.tgz", 1329 + "integrity": "sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ==", 592 1330 "cpu": [ 593 1331 "x64" 594 1332 ], 595 - "license": "MIT", 596 1333 "optional": true, 597 1334 "os": [ 598 1335 "darwin" ··· 602 1339 } 603 1340 }, 604 1341 "node_modules/@next/swc-linux-arm64-gnu": { 605 - "version": "16.0.10", 606 - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.10.tgz", 607 - "integrity": "sha512-uQtWE3X0iGB8apTIskOMi2w/MKONrPOUCi5yLO+v3O8Mb5c7K4Q5KD1jvTpTF5gJKa3VH/ijKjKUq9O9UhwOYw==", 1342 + "version": "16.1.6", 1343 + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.1.6.tgz", 1344 + "integrity": "sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw==", 608 1345 "cpu": [ 609 1346 "arm64" 610 1347 ], 611 - "license": "MIT", 612 1348 "optional": true, 613 1349 "os": [ 614 1350 "linux" ··· 618 1354 } 619 1355 }, 620 1356 "node_modules/@next/swc-linux-arm64-musl": { 621 - "version": "16.0.10", 622 - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.10.tgz", 623 - "integrity": "sha512-llA+hiDTrYvyWI21Z0L1GiXwjQaanPVQQwru5peOgtooeJ8qx3tlqRV2P7uH2pKQaUfHxI/WVarvI5oYgGxaTw==", 1357 + "version": "16.1.6", 1358 + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.1.6.tgz", 1359 + "integrity": "sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==", 624 1360 "cpu": [ 625 1361 "arm64" 626 1362 ], 627 - "license": "MIT", 628 1363 "optional": true, 629 1364 "os": [ 630 1365 "linux" ··· 634 1369 } 635 1370 }, 636 1371 "node_modules/@next/swc-linux-x64-gnu": { 637 - "version": "16.0.10", 638 - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.10.tgz", 639 - "integrity": "sha512-AK2q5H0+a9nsXbeZ3FZdMtbtu9jxW4R/NgzZ6+lrTm3d6Zb7jYrWcgjcpM1k8uuqlSy4xIyPR2YiuUr+wXsavA==", 1372 + "version": "16.1.6", 1373 + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.1.6.tgz", 1374 + "integrity": "sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==", 640 1375 "cpu": [ 641 1376 "x64" 642 1377 ], 643 - "license": "MIT", 644 1378 "optional": true, 645 1379 "os": [ 646 1380 "linux" ··· 650 1384 } 651 1385 }, 652 1386 "node_modules/@next/swc-linux-x64-musl": { 653 - "version": "16.0.10", 654 - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.10.tgz", 655 - "integrity": "sha512-1TDG9PDKivNw5550S111gsO4RGennLVl9cipPhtkXIFVwo31YZ73nEbLjNC8qG3SgTz/QZyYyaFYMeY4BKZR/g==", 1387 + "version": "16.1.6", 1388 + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.1.6.tgz", 1389 + "integrity": "sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==", 656 1390 "cpu": [ 657 1391 "x64" 658 1392 ], 659 - "license": "MIT", 660 1393 "optional": true, 661 1394 "os": [ 662 1395 "linux" ··· 666 1399 } 667 1400 }, 668 1401 "node_modules/@next/swc-win32-arm64-msvc": { 669 - "version": "16.0.10", 670 - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.10.tgz", 671 - "integrity": "sha512-aEZIS4Hh32xdJQbHz121pyuVZniSNoqDVx1yIr2hy+ZwJGipeqnMZBJHyMxv2tiuAXGx6/xpTcQJ6btIiBjgmg==", 1402 + "version": "16.1.6", 1403 + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.1.6.tgz", 1404 + "integrity": "sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==", 672 1405 "cpu": [ 673 1406 "arm64" 674 1407 ], 675 - "license": "MIT", 676 1408 "optional": true, 677 1409 "os": [ 678 1410 "win32" ··· 682 1414 } 683 1415 }, 684 1416 "node_modules/@next/swc-win32-x64-msvc": { 685 - "version": "16.0.10", 686 - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.10.tgz", 687 - "integrity": "sha512-E+njfCoFLb01RAFEnGZn6ERoOqhK1Gl3Lfz1Kjnj0Ulfu7oJbuMyvBKNj/bw8XZnenHDASlygTjZICQW+rYW1Q==", 1417 + "version": "16.1.6", 1418 + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.1.6.tgz", 1419 + "integrity": "sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A==", 688 1420 "cpu": [ 689 1421 "x64" 690 1422 ], 691 - "license": "MIT", 692 1423 "optional": true, 693 1424 "os": [ 694 1425 "win32" ··· 697 1428 "node": ">= 10" 698 1429 } 699 1430 }, 1431 + "node_modules/@noble/ciphers": { 1432 + "version": "1.3.0", 1433 + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", 1434 + "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", 1435 + "engines": { 1436 + "node": "^14.21.3 || >=16" 1437 + }, 1438 + "funding": { 1439 + "url": "https://paulmillr.com/funding/" 1440 + } 1441 + }, 1442 + "node_modules/@noble/curves": { 1443 + "version": "1.9.7", 1444 + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", 1445 + "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", 1446 + "dependencies": { 1447 + "@noble/hashes": "1.8.0" 1448 + }, 1449 + "engines": { 1450 + "node": "^14.21.3 || >=16" 1451 + }, 1452 + "funding": { 1453 + "url": "https://paulmillr.com/funding/" 1454 + } 1455 + }, 1456 + "node_modules/@noble/hashes": { 1457 + "version": "1.8.0", 1458 + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", 1459 + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", 1460 + "engines": { 1461 + "node": "^14.21.3 || >=16" 1462 + }, 1463 + "funding": { 1464 + "url": "https://paulmillr.com/funding/" 1465 + } 1466 + }, 1467 + "node_modules/@nodelib/fs.scandir": { 1468 + "version": "2.1.5", 1469 + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 1470 + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 1471 + "dependencies": { 1472 + "@nodelib/fs.stat": "2.0.5", 1473 + "run-parallel": "^1.1.9" 1474 + }, 1475 + "engines": { 1476 + "node": ">= 8" 1477 + } 1478 + }, 1479 + "node_modules/@nodelib/fs.stat": { 1480 + "version": "2.0.5", 1481 + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 1482 + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 1483 + "engines": { 1484 + "node": ">= 8" 1485 + } 1486 + }, 1487 + "node_modules/@nodelib/fs.walk": { 1488 + "version": "1.2.8", 1489 + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 1490 + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 1491 + "dependencies": { 1492 + "@nodelib/fs.scandir": "2.1.5", 1493 + "fastq": "^1.6.0" 1494 + }, 1495 + "engines": { 1496 + "node": ">= 8" 1497 + } 1498 + }, 1499 + "node_modules/@open-draft/deferred-promise": { 1500 + "version": "2.2.0", 1501 + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", 1502 + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==" 1503 + }, 1504 + "node_modules/@open-draft/logger": { 1505 + "version": "0.3.0", 1506 + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", 1507 + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", 1508 + "dependencies": { 1509 + "is-node-process": "^1.2.0", 1510 + "outvariant": "^1.4.0" 1511 + } 1512 + }, 1513 + "node_modules/@open-draft/until": { 1514 + "version": "2.1.0", 1515 + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", 1516 + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==" 1517 + }, 1518 + "node_modules/@radix-ui/number": { 1519 + "version": "1.1.1", 1520 + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", 1521 + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==" 1522 + }, 1523 + "node_modules/@radix-ui/primitive": { 1524 + "version": "1.1.3", 1525 + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", 1526 + "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==" 1527 + }, 700 1528 "node_modules/@radix-ui/react-compose-refs": { 701 1529 "version": "1.1.2", 702 1530 "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", 703 1531 "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", 704 - "license": "MIT", 1532 + "peerDependencies": { 1533 + "@types/react": "*", 1534 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1535 + }, 1536 + "peerDependenciesMeta": { 1537 + "@types/react": { 1538 + "optional": true 1539 + } 1540 + } 1541 + }, 1542 + "node_modules/@radix-ui/react-context": { 1543 + "version": "1.1.2", 1544 + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", 1545 + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", 1546 + "peerDependencies": { 1547 + "@types/react": "*", 1548 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1549 + }, 1550 + "peerDependenciesMeta": { 1551 + "@types/react": { 1552 + "optional": true 1553 + } 1554 + } 1555 + }, 1556 + "node_modules/@radix-ui/react-direction": { 1557 + "version": "1.1.1", 1558 + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", 1559 + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", 1560 + "peerDependencies": { 1561 + "@types/react": "*", 1562 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1563 + }, 1564 + "peerDependenciesMeta": { 1565 + "@types/react": { 1566 + "optional": true 1567 + } 1568 + } 1569 + }, 1570 + "node_modules/@radix-ui/react-focus-guards": { 1571 + "version": "1.1.3", 1572 + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", 1573 + "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", 1574 + "peerDependencies": { 1575 + "@types/react": "*", 1576 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1577 + }, 1578 + "peerDependenciesMeta": { 1579 + "@types/react": { 1580 + "optional": true 1581 + } 1582 + } 1583 + }, 1584 + "node_modules/@radix-ui/react-id": { 1585 + "version": "1.1.1", 1586 + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", 1587 + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", 1588 + "dependencies": { 1589 + "@radix-ui/react-use-layout-effect": "1.1.1" 1590 + }, 705 1591 "peerDependencies": { 706 1592 "@types/react": "*", 707 1593 "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" ··· 716 1602 "version": "1.2.4", 717 1603 "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", 718 1604 "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", 719 - "license": "MIT", 720 1605 "dependencies": { 721 1606 "@radix-ui/react-compose-refs": "1.1.2" 722 1607 }, ··· 730 1615 } 731 1616 } 732 1617 }, 733 - "node_modules/@stripe/react-stripe-js": { 734 - "version": "2.4.0", 735 - "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-2.4.0.tgz", 736 - "integrity": "sha512-1jVQEL3OuhuzNlf4OdfqovHt+MkWh8Uh8xpLxx/xUFUDdF+7/kDOrGKy+xJO3WLCfZUL7NAy+/ypwXbbYZi0tg==", 737 - "license": "MIT", 1618 + "node_modules/@radix-ui/react-use-callback-ref": { 1619 + "version": "1.1.1", 1620 + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", 1621 + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", 1622 + "peerDependencies": { 1623 + "@types/react": "*", 1624 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1625 + }, 1626 + "peerDependenciesMeta": { 1627 + "@types/react": { 1628 + "optional": true 1629 + } 1630 + } 1631 + }, 1632 + "node_modules/@radix-ui/react-use-controllable-state": { 1633 + "version": "1.2.2", 1634 + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", 1635 + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", 1636 + "dependencies": { 1637 + "@radix-ui/react-use-effect-event": "0.0.2", 1638 + "@radix-ui/react-use-layout-effect": "1.1.1" 1639 + }, 1640 + "peerDependencies": { 1641 + "@types/react": "*", 1642 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1643 + }, 1644 + "peerDependenciesMeta": { 1645 + "@types/react": { 1646 + "optional": true 1647 + } 1648 + } 1649 + }, 1650 + "node_modules/@radix-ui/react-use-effect-event": { 1651 + "version": "0.0.2", 1652 + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", 1653 + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", 1654 + "dependencies": { 1655 + "@radix-ui/react-use-layout-effect": "1.1.1" 1656 + }, 1657 + "peerDependencies": { 1658 + "@types/react": "*", 1659 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1660 + }, 1661 + "peerDependenciesMeta": { 1662 + "@types/react": { 1663 + "optional": true 1664 + } 1665 + } 1666 + }, 1667 + "node_modules/@radix-ui/react-use-escape-keydown": { 1668 + "version": "1.1.1", 1669 + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", 1670 + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", 1671 + "dependencies": { 1672 + "@radix-ui/react-use-callback-ref": "1.1.1" 1673 + }, 1674 + "peerDependencies": { 1675 + "@types/react": "*", 1676 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1677 + }, 1678 + "peerDependenciesMeta": { 1679 + "@types/react": { 1680 + "optional": true 1681 + } 1682 + } 1683 + }, 1684 + "node_modules/@radix-ui/react-use-is-hydrated": { 1685 + "version": "0.1.0", 1686 + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz", 1687 + "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==", 1688 + "dependencies": { 1689 + "use-sync-external-store": "^1.5.0" 1690 + }, 1691 + "peerDependencies": { 1692 + "@types/react": "*", 1693 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1694 + }, 1695 + "peerDependenciesMeta": { 1696 + "@types/react": { 1697 + "optional": true 1698 + } 1699 + } 1700 + }, 1701 + "node_modules/@radix-ui/react-use-layout-effect": { 1702 + "version": "1.1.1", 1703 + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", 1704 + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", 1705 + "peerDependencies": { 1706 + "@types/react": "*", 1707 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1708 + }, 1709 + "peerDependenciesMeta": { 1710 + "@types/react": { 1711 + "optional": true 1712 + } 1713 + } 1714 + }, 1715 + "node_modules/@radix-ui/react-use-previous": { 1716 + "version": "1.1.1", 1717 + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", 1718 + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", 1719 + "peerDependencies": { 1720 + "@types/react": "*", 1721 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1722 + }, 1723 + "peerDependenciesMeta": { 1724 + "@types/react": { 1725 + "optional": true 1726 + } 1727 + } 1728 + }, 1729 + "node_modules/@radix-ui/react-use-rect": { 1730 + "version": "1.1.1", 1731 + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", 1732 + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", 1733 + "dependencies": { 1734 + "@radix-ui/rect": "1.1.1" 1735 + }, 1736 + "peerDependencies": { 1737 + "@types/react": "*", 1738 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1739 + }, 1740 + "peerDependenciesMeta": { 1741 + "@types/react": { 1742 + "optional": true 1743 + } 1744 + } 1745 + }, 1746 + "node_modules/@radix-ui/react-use-size": { 1747 + "version": "1.1.1", 1748 + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", 1749 + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", 1750 + "dependencies": { 1751 + "@radix-ui/react-use-layout-effect": "1.1.1" 1752 + }, 1753 + "peerDependencies": { 1754 + "@types/react": "*", 1755 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1756 + }, 1757 + "peerDependenciesMeta": { 1758 + "@types/react": { 1759 + "optional": true 1760 + } 1761 + } 1762 + }, 1763 + "node_modules/@radix-ui/rect": { 1764 + "version": "1.1.1", 1765 + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", 1766 + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==" 1767 + }, 1768 + "node_modules/@sec-ant/readable-stream": { 1769 + "version": "0.4.1", 1770 + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", 1771 + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==" 1772 + }, 1773 + "node_modules/@sindresorhus/merge-streams": { 1774 + "version": "4.0.0", 1775 + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", 1776 + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", 1777 + "engines": { 1778 + "node": ">=18" 1779 + }, 1780 + "funding": { 1781 + "url": "https://github.com/sponsors/sindresorhus" 1782 + } 1783 + }, 1784 + "node_modules/@supabase/auth-js": { 1785 + "version": "2.99.1", 1786 + "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.99.1.tgz", 1787 + "integrity": "sha512-x7lKKTvKjABJt/FYcRSPiTT01Xhm2FF8RhfL8+RHMkmlwmRQ88/lREupIHKwFPW0W6pTCJqkZb7Yhpw/EZ+fNw==", 1788 + "dependencies": { 1789 + "tslib": "2.8.1" 1790 + }, 1791 + "engines": { 1792 + "node": ">=20.0.0" 1793 + } 1794 + }, 1795 + "node_modules/@supabase/functions-js": { 1796 + "version": "2.99.1", 1797 + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.99.1.tgz", 1798 + "integrity": "sha512-WQE62W5geYImCO4jzFxCk/avnK7JmOdtqu2eiPz3zOaNiIJajNRSAwMMDgEGd2EMs+sUVYj1LfBjfmW3EzHgIA==", 1799 + "dependencies": { 1800 + "tslib": "2.8.1" 1801 + }, 1802 + "engines": { 1803 + "node": ">=20.0.0" 1804 + } 1805 + }, 1806 + "node_modules/@supabase/postgrest-js": { 1807 + "version": "2.99.1", 1808 + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.99.1.tgz", 1809 + "integrity": "sha512-gtw2ibJrADvfqrpUWXGNlrYUvxttF4WVWfPpTFKOb2IRj7B6YRWMDgcrYqIuD4ZEabK4m6YKQCCGy6clgf1lPA==", 1810 + "dependencies": { 1811 + "tslib": "2.8.1" 1812 + }, 1813 + "engines": { 1814 + "node": ">=20.0.0" 1815 + } 1816 + }, 1817 + "node_modules/@supabase/realtime-js": { 1818 + "version": "2.99.1", 1819 + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.99.1.tgz", 1820 + "integrity": "sha512-9EDdy/5wOseGFqxW88ShV9JMRhm7f+9JGY5x+LqT8c7R0X1CTLwg5qie8FiBWcXTZ+68yYxVWunI+7W4FhkWOg==", 1821 + "dependencies": { 1822 + "@types/phoenix": "^1.6.6", 1823 + "@types/ws": "^8.18.1", 1824 + "tslib": "2.8.1", 1825 + "ws": "^8.18.2" 1826 + }, 1827 + "engines": { 1828 + "node": ">=20.0.0" 1829 + } 1830 + }, 1831 + "node_modules/@supabase/ssr": { 1832 + "version": "0.8.0", 1833 + "resolved": "https://registry.npmjs.org/@supabase/ssr/-/ssr-0.8.0.tgz", 1834 + "integrity": "sha512-/PKk8kNFSs8QvvJ2vOww1mF5/c5W8y42duYtXvkOSe+yZKRgTTZywYG2l41pjhNomqESZCpZtXuWmYjFRMV+dw==", 738 1835 "dependencies": { 739 - "prop-types": "^15.7.2" 1836 + "cookie": "^1.0.2" 740 1837 }, 741 1838 "peerDependencies": { 742 - "@stripe/stripe-js": "^1.44.1 || ^2.0.0", 743 - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", 744 - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" 1839 + "@supabase/supabase-js": "^2.76.1" 745 1840 } 746 1841 }, 747 - "node_modules/@stripe/stripe-js": { 748 - "version": "2.2.2", 749 - "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-2.2.2.tgz", 750 - "integrity": "sha512-LvFZRZEBoMe6vXC6RoOAIbXWo/0JDdndq43ekL9M6affcM7PtF5KALmwt91BazW7q49sbSl0l7TunWhhSwEW4w==", 751 - "license": "MIT" 1842 + "node_modules/@supabase/storage-js": { 1843 + "version": "2.99.1", 1844 + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.99.1.tgz", 1845 + "integrity": "sha512-mf7zPfqofI62SOoyQJeNUVxe72E4rQsbWim6lTDPeLu3lHija/cP5utlQADGrjeTgOUN6znx/rWn7SjrETP1dw==", 1846 + "dependencies": { 1847 + "iceberg-js": "^0.8.1", 1848 + "tslib": "2.8.1" 1849 + }, 1850 + "engines": { 1851 + "node": ">=20.0.0" 1852 + } 1853 + }, 1854 + "node_modules/@supabase/supabase-js": { 1855 + "version": "2.99.1", 1856 + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.99.1.tgz", 1857 + "integrity": "sha512-5MRoYD9ffXq8F6a036dm65YoSHisC3by/d22mauKE99Vrwf792KxYIIr/iqCX7E4hkuugbPZ5EGYHTB7MKy6Vg==", 1858 + "dependencies": { 1859 + "@supabase/auth-js": "2.99.1", 1860 + "@supabase/functions-js": "2.99.1", 1861 + "@supabase/postgrest-js": "2.99.1", 1862 + "@supabase/realtime-js": "2.99.1", 1863 + "@supabase/storage-js": "2.99.1" 1864 + }, 1865 + "engines": { 1866 + "node": ">=20.0.0" 1867 + } 752 1868 }, 753 1869 "node_modules/@swc/helpers": { 754 1870 "version": "0.5.15", 755 1871 "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", 756 1872 "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", 757 - "license": "Apache-2.0", 758 1873 "dependencies": { 759 1874 "tslib": "^2.8.0" 760 1875 } 761 1876 }, 762 1877 "node_modules/@tailwindcss/node": { 763 - "version": "4.1.18", 764 - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz", 765 - "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==", 766 - "license": "MIT", 1878 + "version": "4.2.1", 1879 + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.1.tgz", 1880 + "integrity": "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==", 767 1881 "dependencies": { 768 - "@jridgewell/remapping": "^2.3.4", 769 - "enhanced-resolve": "^5.18.3", 1882 + "@jridgewell/remapping": "^2.3.5", 1883 + "enhanced-resolve": "^5.19.0", 770 1884 "jiti": "^2.6.1", 771 - "lightningcss": "1.30.2", 1885 + "lightningcss": "1.31.1", 772 1886 "magic-string": "^0.30.21", 773 1887 "source-map-js": "^1.2.1", 774 - "tailwindcss": "4.1.18" 1888 + "tailwindcss": "4.2.1" 775 1889 } 776 1890 }, 777 1891 "node_modules/@tailwindcss/oxide": { 778 - "version": "4.1.18", 779 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz", 780 - "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==", 781 - "license": "MIT", 1892 + "version": "4.2.1", 1893 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.1.tgz", 1894 + "integrity": "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==", 782 1895 "engines": { 783 - "node": ">= 10" 1896 + "node": ">= 20" 784 1897 }, 785 1898 "optionalDependencies": { 786 - "@tailwindcss/oxide-android-arm64": "4.1.18", 787 - "@tailwindcss/oxide-darwin-arm64": "4.1.18", 788 - "@tailwindcss/oxide-darwin-x64": "4.1.18", 789 - "@tailwindcss/oxide-freebsd-x64": "4.1.18", 790 - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", 791 - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", 792 - "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", 793 - "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", 794 - "@tailwindcss/oxide-linux-x64-musl": "4.1.18", 795 - "@tailwindcss/oxide-wasm32-wasi": "4.1.18", 796 - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", 797 - "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" 1899 + "@tailwindcss/oxide-android-arm64": "4.2.1", 1900 + "@tailwindcss/oxide-darwin-arm64": "4.2.1", 1901 + "@tailwindcss/oxide-darwin-x64": "4.2.1", 1902 + "@tailwindcss/oxide-freebsd-x64": "4.2.1", 1903 + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", 1904 + "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", 1905 + "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", 1906 + "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", 1907 + "@tailwindcss/oxide-linux-x64-musl": "4.2.1", 1908 + "@tailwindcss/oxide-wasm32-wasi": "4.2.1", 1909 + "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", 1910 + "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" 798 1911 } 799 1912 }, 800 1913 "node_modules/@tailwindcss/oxide-android-arm64": { 801 - "version": "4.1.18", 802 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz", 803 - "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==", 1914 + "version": "4.2.1", 1915 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz", 1916 + "integrity": "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==", 804 1917 "cpu": [ 805 1918 "arm64" 806 1919 ], 807 - "license": "MIT", 808 1920 "optional": true, 809 1921 "os": [ 810 1922 "android" 811 1923 ], 812 1924 "engines": { 813 - "node": ">= 10" 1925 + "node": ">= 20" 814 1926 } 815 1927 }, 816 1928 "node_modules/@tailwindcss/oxide-darwin-arm64": { 817 - "version": "4.1.18", 818 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz", 819 - "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==", 1929 + "version": "4.2.1", 1930 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz", 1931 + "integrity": "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==", 820 1932 "cpu": [ 821 1933 "arm64" 822 1934 ], 823 - "license": "MIT", 824 1935 "optional": true, 825 1936 "os": [ 826 1937 "darwin" 827 1938 ], 828 1939 "engines": { 829 - "node": ">= 10" 1940 + "node": ">= 20" 830 1941 } 831 1942 }, 832 1943 "node_modules/@tailwindcss/oxide-darwin-x64": { 833 - "version": "4.1.18", 834 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz", 835 - "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==", 1944 + "version": "4.2.1", 1945 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz", 1946 + "integrity": "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==", 836 1947 "cpu": [ 837 1948 "x64" 838 1949 ], 839 - "license": "MIT", 840 1950 "optional": true, 841 1951 "os": [ 842 1952 "darwin" 843 1953 ], 844 1954 "engines": { 845 - "node": ">= 10" 1955 + "node": ">= 20" 846 1956 } 847 1957 }, 848 1958 "node_modules/@tailwindcss/oxide-freebsd-x64": { 849 - "version": "4.1.18", 850 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz", 851 - "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==", 1959 + "version": "4.2.1", 1960 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz", 1961 + "integrity": "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==", 852 1962 "cpu": [ 853 1963 "x64" 854 1964 ], 855 - "license": "MIT", 856 1965 "optional": true, 857 1966 "os": [ 858 1967 "freebsd" 859 1968 ], 860 1969 "engines": { 861 - "node": ">= 10" 1970 + "node": ">= 20" 862 1971 } 863 1972 }, 864 1973 "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { 865 - "version": "4.1.18", 866 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz", 867 - "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==", 1974 + "version": "4.2.1", 1975 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz", 1976 + "integrity": "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==", 868 1977 "cpu": [ 869 1978 "arm" 870 1979 ], 871 - "license": "MIT", 872 1980 "optional": true, 873 1981 "os": [ 874 1982 "linux" 875 1983 ], 876 1984 "engines": { 877 - "node": ">= 10" 1985 + "node": ">= 20" 878 1986 } 879 1987 }, 880 1988 "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { 881 - "version": "4.1.18", 882 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz", 883 - "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==", 1989 + "version": "4.2.1", 1990 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz", 1991 + "integrity": "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==", 884 1992 "cpu": [ 885 1993 "arm64" 886 1994 ], 887 - "license": "MIT", 888 1995 "optional": true, 889 1996 "os": [ 890 1997 "linux" 891 1998 ], 892 1999 "engines": { 893 - "node": ">= 10" 2000 + "node": ">= 20" 894 2001 } 895 2002 }, 896 2003 "node_modules/@tailwindcss/oxide-linux-arm64-musl": { 897 - "version": "4.1.18", 898 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz", 899 - "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==", 2004 + "version": "4.2.1", 2005 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz", 2006 + "integrity": "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==", 900 2007 "cpu": [ 901 2008 "arm64" 902 2009 ], 903 - "license": "MIT", 904 2010 "optional": true, 905 2011 "os": [ 906 2012 "linux" 907 2013 ], 908 2014 "engines": { 909 - "node": ">= 10" 2015 + "node": ">= 20" 910 2016 } 911 2017 }, 912 2018 "node_modules/@tailwindcss/oxide-linux-x64-gnu": { 913 - "version": "4.1.18", 914 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz", 915 - "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==", 2019 + "version": "4.2.1", 2020 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz", 2021 + "integrity": "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==", 916 2022 "cpu": [ 917 2023 "x64" 918 2024 ], 919 - "license": "MIT", 920 2025 "optional": true, 921 2026 "os": [ 922 2027 "linux" 923 2028 ], 924 2029 "engines": { 925 - "node": ">= 10" 2030 + "node": ">= 20" 926 2031 } 927 2032 }, 928 2033 "node_modules/@tailwindcss/oxide-linux-x64-musl": { 929 - "version": "4.1.18", 930 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz", 931 - "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==", 2034 + "version": "4.2.1", 2035 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz", 2036 + "integrity": "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==", 932 2037 "cpu": [ 933 2038 "x64" 934 2039 ], 935 - "license": "MIT", 936 2040 "optional": true, 937 2041 "os": [ 938 2042 "linux" 939 2043 ], 940 2044 "engines": { 941 - "node": ">= 10" 2045 + "node": ">= 20" 942 2046 } 943 2047 }, 944 2048 "node_modules/@tailwindcss/oxide-wasm32-wasi": { 945 - "version": "4.1.18", 946 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz", 947 - "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==", 2049 + "version": "4.2.1", 2050 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz", 2051 + "integrity": "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==", 948 2052 "bundleDependencies": [ 949 2053 "@napi-rs/wasm-runtime", 950 2054 "@emnapi/core", ··· 956 2060 "cpu": [ 957 2061 "wasm32" 958 2062 ], 959 - "license": "MIT", 960 2063 "optional": true, 961 2064 "dependencies": { 962 - "@emnapi/core": "^1.7.1", 963 - "@emnapi/runtime": "^1.7.1", 2065 + "@emnapi/core": "^1.8.1", 2066 + "@emnapi/runtime": "^1.8.1", 964 2067 "@emnapi/wasi-threads": "^1.1.0", 965 - "@napi-rs/wasm-runtime": "^1.1.0", 2068 + "@napi-rs/wasm-runtime": "^1.1.1", 966 2069 "@tybys/wasm-util": "^0.10.1", 967 - "tslib": "^2.4.0" 2070 + "tslib": "^2.8.1" 968 2071 }, 969 2072 "engines": { 970 2073 "node": ">=14.0.0" 971 2074 } 972 2075 }, 973 2076 "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { 974 - "version": "4.1.18", 975 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz", 976 - "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==", 2077 + "version": "4.2.1", 2078 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz", 2079 + "integrity": "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==", 977 2080 "cpu": [ 978 2081 "arm64" 979 2082 ], 980 - "license": "MIT", 981 2083 "optional": true, 982 2084 "os": [ 983 2085 "win32" 984 2086 ], 985 2087 "engines": { 986 - "node": ">= 10" 2088 + "node": ">= 20" 987 2089 } 988 2090 }, 989 2091 "node_modules/@tailwindcss/oxide-win32-x64-msvc": { 990 - "version": "4.1.18", 991 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz", 992 - "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==", 2092 + "version": "4.2.1", 2093 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz", 2094 + "integrity": "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==", 993 2095 "cpu": [ 994 2096 "x64" 995 2097 ], 996 - "license": "MIT", 997 2098 "optional": true, 998 2099 "os": [ 999 2100 "win32" 1000 2101 ], 1001 2102 "engines": { 1002 - "node": ">= 10" 2103 + "node": ">= 20" 1003 2104 } 1004 2105 }, 1005 2106 "node_modules/@tailwindcss/postcss": { 1006 - "version": "4.1.18", 1007 - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.18.tgz", 1008 - "integrity": "sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==", 1009 - "license": "MIT", 2107 + "version": "4.2.1", 2108 + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.2.1.tgz", 2109 + "integrity": "sha512-OEwGIBnXnj7zJeonOh6ZG9woofIjGrd2BORfvE5p9USYKDCZoQmfqLcfNiRWoJlRWLdNPn2IgVZuWAOM4iTYMw==", 1010 2110 "dependencies": { 1011 2111 "@alloc/quick-lru": "^5.2.0", 1012 - "@tailwindcss/node": "4.1.18", 1013 - "@tailwindcss/oxide": "4.1.18", 1014 - "postcss": "^8.4.41", 1015 - "tailwindcss": "4.1.18" 2112 + "@tailwindcss/node": "4.2.1", 2113 + "@tailwindcss/oxide": "4.2.1", 2114 + "postcss": "^8.5.6", 2115 + "tailwindcss": "4.2.1" 2116 + } 2117 + }, 2118 + "node_modules/@ts-morph/common": { 2119 + "version": "0.27.0", 2120 + "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.27.0.tgz", 2121 + "integrity": "sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ==", 2122 + "dependencies": { 2123 + "fast-glob": "^3.3.3", 2124 + "minimatch": "^10.0.1", 2125 + "path-browserify": "^1.0.1" 1016 2126 } 1017 2127 }, 1018 2128 "node_modules/@types/node": { 1019 2129 "version": "20.4.6", 1020 2130 "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.6.tgz", 1021 - "integrity": "sha512-q0RkvNgMweWWIvSMDiXhflGUKMdIxBo2M2tYM/0kEGDueQByFzK4KZAgu5YHGFNxziTlppNpTIBcqHQAxlfHdA==", 1022 - "license": "MIT" 2131 + "integrity": "sha512-q0RkvNgMweWWIvSMDiXhflGUKMdIxBo2M2tYM/0kEGDueQByFzK4KZAgu5YHGFNxziTlppNpTIBcqHQAxlfHdA==" 2132 + }, 2133 + "node_modules/@types/phoenix": { 2134 + "version": "1.6.7", 2135 + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.7.tgz", 2136 + "integrity": "sha512-oN9ive//QSBkf19rfDv45M7eZPi0eEXylht2OLEXicu5b4KoQ1OzXIw+xDSGWxSxe1JmepRR/ZH283vsu518/Q==" 1023 2137 }, 1024 2138 "node_modules/@types/prop-types": { 1025 2139 "version": "15.7.15", 1026 2140 "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", 1027 2141 "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", 1028 - "devOptional": true, 1029 - "license": "MIT" 2142 + "devOptional": true 1030 2143 }, 1031 2144 "node_modules/@types/react": { 1032 2145 "version": "18.2.8", 1033 2146 "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.8.tgz", 1034 2147 "integrity": "sha512-lTyWUNrd8ntVkqycEEplasWy2OxNlShj3zqS0LuB1ENUGis5HodmhM7DtCoUGbxj3VW/WsGA0DUhpG6XrM7gPA==", 1035 2148 "devOptional": true, 1036 - "license": "MIT", 1037 2149 "dependencies": { 1038 2150 "@types/prop-types": "*", 1039 2151 "@types/scheduler": "*", 1040 2152 "csstype": "^3.0.2" 2153 + } 2154 + }, 2155 + "node_modules/@types/react-dom": { 2156 + "version": "18.2.8", 2157 + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.8.tgz", 2158 + "integrity": "sha512-bAIvO5lN/U8sPGvs1Xm61rlRHHaq5rp5N3kp9C+NJ/Q41P8iqjkXSu0+/qu8POsjH9pNWb0OYabFez7taP7omw==", 2159 + "devOptional": true, 2160 + "license": "MIT", 2161 + "dependencies": { 2162 + "@types/react": "*" 1041 2163 } 1042 2164 }, 1043 2165 "node_modules/@types/scheduler": { 1044 2166 "version": "0.26.0", 1045 2167 "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.26.0.tgz", 1046 2168 "integrity": "sha512-WFHp9YUJQ6CKshqoC37iOlHnQSmxNc795UhB26CyBBttrN9svdIrUjl/NjnNmfcwtncN0h/0PPAFWv9ovP8mLA==", 1047 - "devOptional": true, 1048 - "license": "MIT" 2169 + "devOptional": true 2170 + }, 2171 + "node_modules/@types/statuses": { 2172 + "version": "2.0.6", 2173 + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.6.tgz", 2174 + "integrity": "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==" 2175 + }, 2176 + "node_modules/@types/validate-npm-package-name": { 2177 + "version": "4.0.2", 2178 + "resolved": "https://registry.npmjs.org/@types/validate-npm-package-name/-/validate-npm-package-name-4.0.2.tgz", 2179 + "integrity": "sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw==" 2180 + }, 2181 + "node_modules/@types/ws": { 2182 + "version": "8.18.1", 2183 + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", 2184 + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", 2185 + "dependencies": { 2186 + "@types/node": "*" 2187 + } 1049 2188 }, 1050 2189 "node_modules/@vercel/analytics": { 1051 2190 "version": "1.6.1", 1052 2191 "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.6.1.tgz", 1053 2192 "integrity": "sha512-oH9He/bEM+6oKlv3chWuOOcp8Y6fo6/PSro8hEkgCW3pu9/OiCXiUpRUogDh3Fs3LH2sosDrx8CxeOLBEE+afg==", 1054 - "license": "MPL-2.0", 1055 2193 "peerDependencies": { 1056 2194 "@remix-run/react": "^2", 1057 2195 "@sveltejs/kit": "^1 || ^2", ··· 1089 2227 "version": "1.3.1", 1090 2228 "resolved": "https://registry.npmjs.org/@vercel/speed-insights/-/speed-insights-1.3.1.tgz", 1091 2229 "integrity": "sha512-PbEr7FrMkUrGYvlcLHGkXdCkxnylCWePx7lPxxq36DNdfo9mcUjLOmqOyPDHAOgnfqgGGdmE3XI9L/4+5fr+vQ==", 1092 - "license": "Apache-2.0", 1093 2230 "peerDependencies": { 1094 2231 "@sveltejs/kit": "^1 || ^2", 1095 2232 "next": ">= 13", ··· 1119 2256 } 1120 2257 } 1121 2258 }, 2259 + "node_modules/accepts": { 2260 + "version": "2.0.0", 2261 + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", 2262 + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", 2263 + "dependencies": { 2264 + "mime-types": "^3.0.0", 2265 + "negotiator": "^1.0.0" 2266 + }, 2267 + "engines": { 2268 + "node": ">= 0.6" 2269 + } 2270 + }, 2271 + "node_modules/agent-base": { 2272 + "version": "7.1.4", 2273 + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", 2274 + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", 2275 + "engines": { 2276 + "node": ">= 14" 2277 + } 2278 + }, 2279 + "node_modules/ajv": { 2280 + "version": "8.18.0", 2281 + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", 2282 + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", 2283 + "dependencies": { 2284 + "fast-deep-equal": "^3.1.3", 2285 + "fast-uri": "^3.0.1", 2286 + "json-schema-traverse": "^1.0.0", 2287 + "require-from-string": "^2.0.2" 2288 + }, 2289 + "funding": { 2290 + "type": "github", 2291 + "url": "https://github.com/sponsors/epoberezkin" 2292 + } 2293 + }, 2294 + "node_modules/ajv-formats": { 2295 + "version": "3.0.1", 2296 + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", 2297 + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", 2298 + "dependencies": { 2299 + "ajv": "^8.0.0" 2300 + }, 2301 + "peerDependencies": { 2302 + "ajv": "^8.0.0" 2303 + }, 2304 + "peerDependenciesMeta": { 2305 + "ajv": { 2306 + "optional": true 2307 + } 2308 + } 2309 + }, 2310 + "node_modules/ansi-regex": { 2311 + "version": "6.2.2", 2312 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", 2313 + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", 2314 + "engines": { 2315 + "node": ">=12" 2316 + }, 2317 + "funding": { 2318 + "url": "https://github.com/chalk/ansi-regex?sponsor=1" 2319 + } 2320 + }, 2321 + "node_modules/ansi-styles": { 2322 + "version": "4.3.0", 2323 + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 2324 + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 2325 + "dependencies": { 2326 + "color-convert": "^2.0.1" 2327 + }, 2328 + "engines": { 2329 + "node": ">=8" 2330 + }, 2331 + "funding": { 2332 + "url": "https://github.com/chalk/ansi-styles?sponsor=1" 2333 + } 2334 + }, 2335 + "node_modules/ansis": { 2336 + "version": "4.2.0", 2337 + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", 2338 + "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", 2339 + "engines": { 2340 + "node": ">=14" 2341 + } 2342 + }, 2343 + "node_modules/argparse": { 2344 + "version": "2.0.1", 2345 + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 2346 + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" 2347 + }, 2348 + "node_modules/aria-hidden": { 2349 + "version": "1.2.6", 2350 + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", 2351 + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", 2352 + "dependencies": { 2353 + "tslib": "^2.0.0" 2354 + }, 2355 + "engines": { 2356 + "node": ">=10" 2357 + } 2358 + }, 2359 + "node_modules/ast-types": { 2360 + "version": "0.16.1", 2361 + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", 2362 + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", 2363 + "dependencies": { 2364 + "tslib": "^2.0.1" 2365 + }, 2366 + "engines": { 2367 + "node": ">=4" 2368 + } 2369 + }, 2370 + "node_modules/balanced-match": { 2371 + "version": "4.0.4", 2372 + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", 2373 + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", 2374 + "engines": { 2375 + "node": "18 || 20 || >=22" 2376 + } 2377 + }, 2378 + "node_modules/baseline-browser-mapping": { 2379 + "version": "2.10.0", 2380 + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", 2381 + "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", 2382 + "bin": { 2383 + "baseline-browser-mapping": "dist/cli.cjs" 2384 + }, 2385 + "engines": { 2386 + "node": ">=6.0.0" 2387 + } 2388 + }, 2389 + "node_modules/body-parser": { 2390 + "version": "2.2.2", 2391 + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", 2392 + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", 2393 + "dependencies": { 2394 + "bytes": "^3.1.2", 2395 + "content-type": "^1.0.5", 2396 + "debug": "^4.4.3", 2397 + "http-errors": "^2.0.0", 2398 + "iconv-lite": "^0.7.0", 2399 + "on-finished": "^2.4.1", 2400 + "qs": "^6.14.1", 2401 + "raw-body": "^3.0.1", 2402 + "type-is": "^2.0.1" 2403 + }, 2404 + "engines": { 2405 + "node": ">=18" 2406 + }, 2407 + "funding": { 2408 + "type": "opencollective", 2409 + "url": "https://opencollective.com/express" 2410 + } 2411 + }, 2412 + "node_modules/brace-expansion": { 2413 + "version": "5.0.4", 2414 + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", 2415 + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", 2416 + "dependencies": { 2417 + "balanced-match": "^4.0.2" 2418 + }, 2419 + "engines": { 2420 + "node": "18 || 20 || >=22" 2421 + } 2422 + }, 2423 + "node_modules/braces": { 2424 + "version": "3.0.3", 2425 + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 2426 + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 2427 + "dependencies": { 2428 + "fill-range": "^7.1.1" 2429 + }, 2430 + "engines": { 2431 + "node": ">=8" 2432 + } 2433 + }, 2434 + "node_modules/browserslist": { 2435 + "version": "4.28.1", 2436 + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", 2437 + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", 2438 + "funding": [ 2439 + { 2440 + "type": "opencollective", 2441 + "url": "https://opencollective.com/browserslist" 2442 + }, 2443 + { 2444 + "type": "tidelift", 2445 + "url": "https://tidelift.com/funding/github/npm/browserslist" 2446 + }, 2447 + { 2448 + "type": "github", 2449 + "url": "https://github.com/sponsors/ai" 2450 + } 2451 + ], 2452 + "dependencies": { 2453 + "baseline-browser-mapping": "^2.9.0", 2454 + "caniuse-lite": "^1.0.30001759", 2455 + "electron-to-chromium": "^1.5.263", 2456 + "node-releases": "^2.0.27", 2457 + "update-browserslist-db": "^1.2.0" 2458 + }, 2459 + "bin": { 2460 + "browserslist": "cli.js" 2461 + }, 2462 + "engines": { 2463 + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" 2464 + } 2465 + }, 2466 + "node_modules/bundle-name": { 2467 + "version": "4.1.0", 2468 + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", 2469 + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", 2470 + "dependencies": { 2471 + "run-applescript": "^7.0.0" 2472 + }, 2473 + "engines": { 2474 + "node": ">=18" 2475 + }, 2476 + "funding": { 2477 + "url": "https://github.com/sponsors/sindresorhus" 2478 + } 2479 + }, 2480 + "node_modules/bytes": { 2481 + "version": "3.1.2", 2482 + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 2483 + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 2484 + "engines": { 2485 + "node": ">= 0.8" 2486 + } 2487 + }, 1122 2488 "node_modules/call-bind-apply-helpers": { 1123 2489 "version": "1.0.2", 1124 2490 "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", 1125 2491 "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", 1126 - "license": "MIT", 1127 2492 "dependencies": { 1128 2493 "es-errors": "^1.3.0", 1129 2494 "function-bind": "^1.1.2" ··· 1136 2501 "version": "1.0.4", 1137 2502 "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", 1138 2503 "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", 1139 - "license": "MIT", 1140 2504 "dependencies": { 1141 2505 "call-bind-apply-helpers": "^1.0.2", 1142 2506 "get-intrinsic": "^1.3.0" ··· 1146 2510 }, 1147 2511 "funding": { 1148 2512 "url": "https://github.com/sponsors/ljharb" 2513 + } 2514 + }, 2515 + "node_modules/callsites": { 2516 + "version": "3.1.0", 2517 + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 2518 + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 2519 + "engines": { 2520 + "node": ">=6" 1149 2521 } 1150 2522 }, 1151 2523 "node_modules/caniuse-lite": { 1152 - "version": "1.0.30001760", 1153 - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz", 1154 - "integrity": "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==", 2524 + "version": "1.0.30001777", 2525 + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001777.tgz", 2526 + "integrity": "sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ==", 1155 2527 "funding": [ 1156 2528 { 1157 2529 "type": "opencollective", ··· 1165 2537 "type": "github", 1166 2538 "url": "https://github.com/sponsors/ai" 1167 2539 } 1168 - ], 1169 - "license": "CC-BY-4.0" 2540 + ] 2541 + }, 2542 + "node_modules/chalk": { 2543 + "version": "5.6.2", 2544 + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", 2545 + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", 2546 + "engines": { 2547 + "node": "^12.17.0 || ^14.13 || >=16.0.0" 2548 + }, 2549 + "funding": { 2550 + "url": "https://github.com/chalk/chalk?sponsor=1" 2551 + } 1170 2552 }, 1171 2553 "node_modules/class-variance-authority": { 1172 2554 "version": "0.7.1", 1173 2555 "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", 1174 2556 "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", 1175 - "license": "Apache-2.0", 1176 2557 "dependencies": { 1177 2558 "clsx": "^2.1.1" 1178 2559 }, ··· 1180 2561 "url": "https://polar.sh/cva" 1181 2562 } 1182 2563 }, 2564 + "node_modules/cli-cursor": { 2565 + "version": "5.0.0", 2566 + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", 2567 + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", 2568 + "dependencies": { 2569 + "restore-cursor": "^5.0.0" 2570 + }, 2571 + "engines": { 2572 + "node": ">=18" 2573 + }, 2574 + "funding": { 2575 + "url": "https://github.com/sponsors/sindresorhus" 2576 + } 2577 + }, 2578 + "node_modules/cli-spinners": { 2579 + "version": "2.9.2", 2580 + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", 2581 + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", 2582 + "engines": { 2583 + "node": ">=6" 2584 + }, 2585 + "funding": { 2586 + "url": "https://github.com/sponsors/sindresorhus" 2587 + } 2588 + }, 2589 + "node_modules/cli-width": { 2590 + "version": "4.1.0", 2591 + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", 2592 + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", 2593 + "engines": { 2594 + "node": ">= 12" 2595 + } 2596 + }, 1183 2597 "node_modules/client-only": { 1184 2598 "version": "0.0.1", 1185 2599 "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", 1186 - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", 1187 - "license": "MIT" 2600 + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" 2601 + }, 2602 + "node_modules/cliui": { 2603 + "version": "8.0.1", 2604 + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", 2605 + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", 2606 + "dependencies": { 2607 + "string-width": "^4.2.0", 2608 + "strip-ansi": "^6.0.1", 2609 + "wrap-ansi": "^7.0.0" 2610 + }, 2611 + "engines": { 2612 + "node": ">=12" 2613 + } 2614 + }, 2615 + "node_modules/cliui/node_modules/ansi-regex": { 2616 + "version": "5.0.1", 2617 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 2618 + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 2619 + "engines": { 2620 + "node": ">=8" 2621 + } 2622 + }, 2623 + "node_modules/cliui/node_modules/emoji-regex": { 2624 + "version": "8.0.0", 2625 + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 2626 + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 2627 + }, 2628 + "node_modules/cliui/node_modules/string-width": { 2629 + "version": "4.2.3", 2630 + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 2631 + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 2632 + "dependencies": { 2633 + "emoji-regex": "^8.0.0", 2634 + "is-fullwidth-code-point": "^3.0.0", 2635 + "strip-ansi": "^6.0.1" 2636 + }, 2637 + "engines": { 2638 + "node": ">=8" 2639 + } 2640 + }, 2641 + "node_modules/cliui/node_modules/strip-ansi": { 2642 + "version": "6.0.1", 2643 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2644 + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2645 + "dependencies": { 2646 + "ansi-regex": "^5.0.1" 2647 + }, 2648 + "engines": { 2649 + "node": ">=8" 2650 + } 2651 + }, 2652 + "node_modules/cliui/node_modules/wrap-ansi": { 2653 + "version": "7.0.0", 2654 + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 2655 + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 2656 + "dependencies": { 2657 + "ansi-styles": "^4.0.0", 2658 + "string-width": "^4.1.0", 2659 + "strip-ansi": "^6.0.0" 2660 + }, 2661 + "engines": { 2662 + "node": ">=10" 2663 + }, 2664 + "funding": { 2665 + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 2666 + } 1188 2667 }, 1189 2668 "node_modules/clsx": { 1190 2669 "version": "2.1.1", 1191 2670 "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", 1192 2671 "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", 1193 - "license": "MIT", 1194 2672 "engines": { 1195 2673 "node": ">=6" 1196 2674 } 1197 2675 }, 2676 + "node_modules/code-block-writer": { 2677 + "version": "13.0.3", 2678 + "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz", 2679 + "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==" 2680 + }, 2681 + "node_modules/color-convert": { 2682 + "version": "2.0.1", 2683 + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 2684 + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 2685 + "dependencies": { 2686 + "color-name": "~1.1.4" 2687 + }, 2688 + "engines": { 2689 + "node": ">=7.0.0" 2690 + } 2691 + }, 2692 + "node_modules/color-name": { 2693 + "version": "1.1.4", 2694 + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 2695 + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 2696 + }, 2697 + "node_modules/commander": { 2698 + "version": "14.0.3", 2699 + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", 2700 + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", 2701 + "engines": { 2702 + "node": ">=20" 2703 + } 2704 + }, 2705 + "node_modules/content-disposition": { 2706 + "version": "1.0.1", 2707 + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", 2708 + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", 2709 + "engines": { 2710 + "node": ">=18" 2711 + }, 2712 + "funding": { 2713 + "type": "opencollective", 2714 + "url": "https://opencollective.com/express" 2715 + } 2716 + }, 2717 + "node_modules/content-type": { 2718 + "version": "1.0.5", 2719 + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 2720 + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 2721 + "engines": { 2722 + "node": ">= 0.6" 2723 + } 2724 + }, 2725 + "node_modules/convert-source-map": { 2726 + "version": "2.0.0", 2727 + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", 2728 + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" 2729 + }, 2730 + "node_modules/cookie": { 2731 + "version": "1.1.1", 2732 + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", 2733 + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", 2734 + "engines": { 2735 + "node": ">=18" 2736 + }, 2737 + "funding": { 2738 + "type": "opencollective", 2739 + "url": "https://opencollective.com/express" 2740 + } 2741 + }, 2742 + "node_modules/cookie-signature": { 2743 + "version": "1.2.2", 2744 + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", 2745 + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", 2746 + "engines": { 2747 + "node": ">=6.6.0" 2748 + } 2749 + }, 2750 + "node_modules/cors": { 2751 + "version": "2.8.6", 2752 + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", 2753 + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", 2754 + "dependencies": { 2755 + "object-assign": "^4", 2756 + "vary": "^1" 2757 + }, 2758 + "engines": { 2759 + "node": ">= 0.10" 2760 + }, 2761 + "funding": { 2762 + "type": "opencollective", 2763 + "url": "https://opencollective.com/express" 2764 + } 2765 + }, 2766 + "node_modules/cosmiconfig": { 2767 + "version": "9.0.1", 2768 + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.1.tgz", 2769 + "integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==", 2770 + "dependencies": { 2771 + "env-paths": "^2.2.1", 2772 + "import-fresh": "^3.3.0", 2773 + "js-yaml": "^4.1.0", 2774 + "parse-json": "^5.2.0" 2775 + }, 2776 + "engines": { 2777 + "node": ">=14" 2778 + }, 2779 + "funding": { 2780 + "url": "https://github.com/sponsors/d-fischer" 2781 + }, 2782 + "peerDependencies": { 2783 + "typescript": ">=4.9.5" 2784 + }, 2785 + "peerDependenciesMeta": { 2786 + "typescript": { 2787 + "optional": true 2788 + } 2789 + } 2790 + }, 2791 + "node_modules/cross-spawn": { 2792 + "version": "7.0.6", 2793 + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", 2794 + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", 2795 + "dependencies": { 2796 + "path-key": "^3.1.0", 2797 + "shebang-command": "^2.0.0", 2798 + "which": "^2.0.1" 2799 + }, 2800 + "engines": { 2801 + "node": ">= 8" 2802 + } 2803 + }, 2804 + "node_modules/cross-spawn/node_modules/isexe": { 2805 + "version": "2.0.0", 2806 + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 2807 + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" 2808 + }, 2809 + "node_modules/cross-spawn/node_modules/which": { 2810 + "version": "2.0.2", 2811 + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2812 + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2813 + "dependencies": { 2814 + "isexe": "^2.0.0" 2815 + }, 2816 + "bin": { 2817 + "node-which": "bin/node-which" 2818 + }, 2819 + "engines": { 2820 + "node": ">= 8" 2821 + } 2822 + }, 2823 + "node_modules/cssesc": { 2824 + "version": "3.0.0", 2825 + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", 2826 + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", 2827 + "bin": { 2828 + "cssesc": "bin/cssesc" 2829 + }, 2830 + "engines": { 2831 + "node": ">=4" 2832 + } 2833 + }, 1198 2834 "node_modules/csstype": { 1199 2835 "version": "3.2.3", 1200 2836 "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", 1201 2837 "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", 1202 - "devOptional": true, 1203 - "license": "MIT" 2838 + "devOptional": true 2839 + }, 2840 + "node_modules/data-uri-to-buffer": { 2841 + "version": "4.0.1", 2842 + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", 2843 + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", 2844 + "engines": { 2845 + "node": ">= 12" 2846 + } 2847 + }, 2848 + "node_modules/debug": { 2849 + "version": "4.4.3", 2850 + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", 2851 + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", 2852 + "dependencies": { 2853 + "ms": "^2.1.3" 2854 + }, 2855 + "engines": { 2856 + "node": ">=6.0" 2857 + }, 2858 + "peerDependenciesMeta": { 2859 + "supports-color": { 2860 + "optional": true 2861 + } 2862 + } 2863 + }, 2864 + "node_modules/dedent": { 2865 + "version": "1.7.2", 2866 + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", 2867 + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", 2868 + "peerDependencies": { 2869 + "babel-plugin-macros": "^3.1.0" 2870 + }, 2871 + "peerDependenciesMeta": { 2872 + "babel-plugin-macros": { 2873 + "optional": true 2874 + } 2875 + } 2876 + }, 2877 + "node_modules/deepmerge": { 2878 + "version": "4.3.1", 2879 + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", 2880 + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", 2881 + "engines": { 2882 + "node": ">=0.10.0" 2883 + } 2884 + }, 2885 + "node_modules/default-browser": { 2886 + "version": "5.5.0", 2887 + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", 2888 + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", 2889 + "dependencies": { 2890 + "bundle-name": "^4.1.0", 2891 + "default-browser-id": "^5.0.0" 2892 + }, 2893 + "engines": { 2894 + "node": ">=18" 2895 + }, 2896 + "funding": { 2897 + "url": "https://github.com/sponsors/sindresorhus" 2898 + } 2899 + }, 2900 + "node_modules/default-browser-id": { 2901 + "version": "5.0.1", 2902 + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", 2903 + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", 2904 + "engines": { 2905 + "node": ">=18" 2906 + }, 2907 + "funding": { 2908 + "url": "https://github.com/sponsors/sindresorhus" 2909 + } 2910 + }, 2911 + "node_modules/define-lazy-prop": { 2912 + "version": "3.0.0", 2913 + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", 2914 + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", 2915 + "engines": { 2916 + "node": ">=12" 2917 + }, 2918 + "funding": { 2919 + "url": "https://github.com/sponsors/sindresorhus" 2920 + } 2921 + }, 2922 + "node_modules/depd": { 2923 + "version": "2.0.0", 2924 + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 2925 + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 2926 + "engines": { 2927 + "node": ">= 0.8" 2928 + } 1204 2929 }, 1205 2930 "node_modules/detect-libc": { 1206 2931 "version": "2.1.2", 1207 2932 "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", 1208 2933 "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", 1209 - "license": "Apache-2.0", 1210 2934 "engines": { 1211 2935 "node": ">=8" 1212 2936 } 1213 2937 }, 2938 + "node_modules/detect-node-es": { 2939 + "version": "1.1.0", 2940 + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", 2941 + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" 2942 + }, 2943 + "node_modules/diff": { 2944 + "version": "8.0.3", 2945 + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz", 2946 + "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", 2947 + "engines": { 2948 + "node": ">=0.3.1" 2949 + } 2950 + }, 2951 + "node_modules/dotenv": { 2952 + "version": "17.3.1", 2953 + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz", 2954 + "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==", 2955 + "engines": { 2956 + "node": ">=12" 2957 + }, 2958 + "funding": { 2959 + "url": "https://dotenvx.com" 2960 + } 2961 + }, 1214 2962 "node_modules/dunder-proto": { 1215 2963 "version": "1.0.1", 1216 2964 "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 1217 2965 "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 1218 - "license": "MIT", 1219 2966 "dependencies": { 1220 2967 "call-bind-apply-helpers": "^1.0.1", 1221 2968 "es-errors": "^1.3.0", ··· 1225 2972 "node": ">= 0.4" 1226 2973 } 1227 2974 }, 2975 + "node_modules/eciesjs": { 2976 + "version": "0.4.18", 2977 + "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.18.tgz", 2978 + "integrity": "sha512-wG99Zcfcys9fZux7Cft8BAX/YrOJLJSZ3jyYPfhZHqN2E+Ffx+QXBDsv3gubEgPtV6dTzJMSQUwk1H98/t/0wQ==", 2979 + "dependencies": { 2980 + "@ecies/ciphers": "^0.2.5", 2981 + "@noble/ciphers": "^1.3.0", 2982 + "@noble/curves": "^1.9.7", 2983 + "@noble/hashes": "^1.8.0" 2984 + }, 2985 + "engines": { 2986 + "bun": ">=1", 2987 + "deno": ">=2", 2988 + "node": ">=16" 2989 + } 2990 + }, 2991 + "node_modules/ee-first": { 2992 + "version": "1.1.1", 2993 + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 2994 + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 2995 + }, 2996 + "node_modules/electron-to-chromium": { 2997 + "version": "1.5.307", 2998 + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz", 2999 + "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==" 3000 + }, 3001 + "node_modules/emoji-regex": { 3002 + "version": "10.6.0", 3003 + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", 3004 + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==" 3005 + }, 3006 + "node_modules/encodeurl": { 3007 + "version": "2.0.0", 3008 + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 3009 + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 3010 + "engines": { 3011 + "node": ">= 0.8" 3012 + } 3013 + }, 1228 3014 "node_modules/enhanced-resolve": { 1229 - "version": "5.18.4", 1230 - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", 1231 - "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", 1232 - "license": "MIT", 3015 + "version": "5.20.0", 3016 + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", 3017 + "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==", 1233 3018 "dependencies": { 1234 3019 "graceful-fs": "^4.2.4", 1235 - "tapable": "^2.2.0" 3020 + "tapable": "^2.3.0" 1236 3021 }, 1237 3022 "engines": { 1238 3023 "node": ">=10.13.0" 1239 3024 } 1240 3025 }, 3026 + "node_modules/env-paths": { 3027 + "version": "2.2.1", 3028 + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", 3029 + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", 3030 + "engines": { 3031 + "node": ">=6" 3032 + } 3033 + }, 3034 + "node_modules/error-ex": { 3035 + "version": "1.3.4", 3036 + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", 3037 + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", 3038 + "dependencies": { 3039 + "is-arrayish": "^0.2.1" 3040 + } 3041 + }, 1241 3042 "node_modules/es-define-property": { 1242 3043 "version": "1.0.1", 1243 3044 "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 1244 3045 "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 1245 - "license": "MIT", 1246 3046 "engines": { 1247 3047 "node": ">= 0.4" 1248 3048 } ··· 1251 3051 "version": "1.3.0", 1252 3052 "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 1253 3053 "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 1254 - "license": "MIT", 1255 3054 "engines": { 1256 3055 "node": ">= 0.4" 1257 3056 } ··· 1260 3059 "version": "1.1.1", 1261 3060 "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", 1262 3061 "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", 1263 - "license": "MIT", 1264 3062 "dependencies": { 1265 3063 "es-errors": "^1.3.0" 1266 3064 }, ··· 1268 3066 "node": ">= 0.4" 1269 3067 } 1270 3068 }, 3069 + "node_modules/escalade": { 3070 + "version": "3.2.0", 3071 + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", 3072 + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", 3073 + "engines": { 3074 + "node": ">=6" 3075 + } 3076 + }, 3077 + "node_modules/escape-html": { 3078 + "version": "1.0.3", 3079 + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 3080 + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 3081 + }, 3082 + "node_modules/esprima": { 3083 + "version": "4.0.1", 3084 + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 3085 + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 3086 + "bin": { 3087 + "esparse": "bin/esparse.js", 3088 + "esvalidate": "bin/esvalidate.js" 3089 + }, 3090 + "engines": { 3091 + "node": ">=4" 3092 + } 3093 + }, 3094 + "node_modules/etag": { 3095 + "version": "1.8.1", 3096 + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 3097 + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 3098 + "engines": { 3099 + "node": ">= 0.6" 3100 + } 3101 + }, 3102 + "node_modules/eventsource": { 3103 + "version": "3.0.7", 3104 + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", 3105 + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", 3106 + "dependencies": { 3107 + "eventsource-parser": "^3.0.1" 3108 + }, 3109 + "engines": { 3110 + "node": ">=18.0.0" 3111 + } 3112 + }, 3113 + "node_modules/eventsource-parser": { 3114 + "version": "3.0.6", 3115 + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", 3116 + "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", 3117 + "engines": { 3118 + "node": ">=18.0.0" 3119 + } 3120 + }, 3121 + "node_modules/execa": { 3122 + "version": "9.6.1", 3123 + "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", 3124 + "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==", 3125 + "dependencies": { 3126 + "@sindresorhus/merge-streams": "^4.0.0", 3127 + "cross-spawn": "^7.0.6", 3128 + "figures": "^6.1.0", 3129 + "get-stream": "^9.0.0", 3130 + "human-signals": "^8.0.1", 3131 + "is-plain-obj": "^4.1.0", 3132 + "is-stream": "^4.0.1", 3133 + "npm-run-path": "^6.0.0", 3134 + "pretty-ms": "^9.2.0", 3135 + "signal-exit": "^4.1.0", 3136 + "strip-final-newline": "^4.0.0", 3137 + "yoctocolors": "^2.1.1" 3138 + }, 3139 + "engines": { 3140 + "node": "^18.19.0 || >=20.5.0" 3141 + }, 3142 + "funding": { 3143 + "url": "https://github.com/sindresorhus/execa?sponsor=1" 3144 + } 3145 + }, 3146 + "node_modules/express": { 3147 + "version": "5.2.1", 3148 + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", 3149 + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", 3150 + "dependencies": { 3151 + "accepts": "^2.0.0", 3152 + "body-parser": "^2.2.1", 3153 + "content-disposition": "^1.0.0", 3154 + "content-type": "^1.0.5", 3155 + "cookie": "^0.7.1", 3156 + "cookie-signature": "^1.2.1", 3157 + "debug": "^4.4.0", 3158 + "depd": "^2.0.0", 3159 + "encodeurl": "^2.0.0", 3160 + "escape-html": "^1.0.3", 3161 + "etag": "^1.8.1", 3162 + "finalhandler": "^2.1.0", 3163 + "fresh": "^2.0.0", 3164 + "http-errors": "^2.0.0", 3165 + "merge-descriptors": "^2.0.0", 3166 + "mime-types": "^3.0.0", 3167 + "on-finished": "^2.4.1", 3168 + "once": "^1.4.0", 3169 + "parseurl": "^1.3.3", 3170 + "proxy-addr": "^2.0.7", 3171 + "qs": "^6.14.0", 3172 + "range-parser": "^1.2.1", 3173 + "router": "^2.2.0", 3174 + "send": "^1.1.0", 3175 + "serve-static": "^2.2.0", 3176 + "statuses": "^2.0.1", 3177 + "type-is": "^2.0.1", 3178 + "vary": "^1.1.2" 3179 + }, 3180 + "engines": { 3181 + "node": ">= 18" 3182 + }, 3183 + "funding": { 3184 + "type": "opencollective", 3185 + "url": "https://opencollective.com/express" 3186 + } 3187 + }, 3188 + "node_modules/express-rate-limit": { 3189 + "version": "8.3.1", 3190 + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.3.1.tgz", 3191 + "integrity": "sha512-D1dKN+cmyPWuvB+G2SREQDzPY1agpBIcTa9sJxOPMCNeH3gwzhqJRDWCXW3gg0y//+LQ/8j52JbMROWyrKdMdw==", 3192 + "dependencies": { 3193 + "ip-address": "10.1.0" 3194 + }, 3195 + "engines": { 3196 + "node": ">= 16" 3197 + }, 3198 + "funding": { 3199 + "url": "https://github.com/sponsors/express-rate-limit" 3200 + }, 3201 + "peerDependencies": { 3202 + "express": ">= 4.11" 3203 + } 3204 + }, 3205 + "node_modules/express/node_modules/cookie": { 3206 + "version": "0.7.2", 3207 + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", 3208 + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", 3209 + "engines": { 3210 + "node": ">= 0.6" 3211 + } 3212 + }, 3213 + "node_modules/fast-deep-equal": { 3214 + "version": "3.1.3", 3215 + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 3216 + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 3217 + }, 3218 + "node_modules/fast-glob": { 3219 + "version": "3.3.3", 3220 + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", 3221 + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", 3222 + "dependencies": { 3223 + "@nodelib/fs.stat": "^2.0.2", 3224 + "@nodelib/fs.walk": "^1.2.3", 3225 + "glob-parent": "^5.1.2", 3226 + "merge2": "^1.3.0", 3227 + "micromatch": "^4.0.8" 3228 + }, 3229 + "engines": { 3230 + "node": ">=8.6.0" 3231 + } 3232 + }, 3233 + "node_modules/fast-uri": { 3234 + "version": "3.1.0", 3235 + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", 3236 + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", 3237 + "funding": [ 3238 + { 3239 + "type": "github", 3240 + "url": "https://github.com/sponsors/fastify" 3241 + }, 3242 + { 3243 + "type": "opencollective", 3244 + "url": "https://opencollective.com/fastify" 3245 + } 3246 + ] 3247 + }, 3248 + "node_modules/fastq": { 3249 + "version": "1.20.1", 3250 + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", 3251 + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", 3252 + "dependencies": { 3253 + "reusify": "^1.0.4" 3254 + } 3255 + }, 3256 + "node_modules/fdir": { 3257 + "version": "6.5.0", 3258 + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", 3259 + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", 3260 + "engines": { 3261 + "node": ">=12.0.0" 3262 + }, 3263 + "peerDependencies": { 3264 + "picomatch": "^3 || ^4" 3265 + }, 3266 + "peerDependenciesMeta": { 3267 + "picomatch": { 3268 + "optional": true 3269 + } 3270 + } 3271 + }, 3272 + "node_modules/fetch-blob": { 3273 + "version": "3.2.0", 3274 + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", 3275 + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", 3276 + "funding": [ 3277 + { 3278 + "type": "github", 3279 + "url": "https://github.com/sponsors/jimmywarting" 3280 + }, 3281 + { 3282 + "type": "paypal", 3283 + "url": "https://paypal.me/jimmywarting" 3284 + } 3285 + ], 3286 + "dependencies": { 3287 + "node-domexception": "^1.0.0", 3288 + "web-streams-polyfill": "^3.0.3" 3289 + }, 3290 + "engines": { 3291 + "node": "^12.20 || >= 14.13" 3292 + } 3293 + }, 3294 + "node_modules/figures": { 3295 + "version": "6.1.0", 3296 + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", 3297 + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", 3298 + "dependencies": { 3299 + "is-unicode-supported": "^2.0.0" 3300 + }, 3301 + "engines": { 3302 + "node": ">=18" 3303 + }, 3304 + "funding": { 3305 + "url": "https://github.com/sponsors/sindresorhus" 3306 + } 3307 + }, 3308 + "node_modules/fill-range": { 3309 + "version": "7.1.1", 3310 + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 3311 + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 3312 + "dependencies": { 3313 + "to-regex-range": "^5.0.1" 3314 + }, 3315 + "engines": { 3316 + "node": ">=8" 3317 + } 3318 + }, 3319 + "node_modules/finalhandler": { 3320 + "version": "2.1.1", 3321 + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", 3322 + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", 3323 + "dependencies": { 3324 + "debug": "^4.4.0", 3325 + "encodeurl": "^2.0.0", 3326 + "escape-html": "^1.0.3", 3327 + "on-finished": "^2.4.1", 3328 + "parseurl": "^1.3.3", 3329 + "statuses": "^2.0.1" 3330 + }, 3331 + "engines": { 3332 + "node": ">= 18.0.0" 3333 + }, 3334 + "funding": { 3335 + "type": "opencollective", 3336 + "url": "https://opencollective.com/express" 3337 + } 3338 + }, 3339 + "node_modules/formdata-polyfill": { 3340 + "version": "4.0.10", 3341 + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", 3342 + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", 3343 + "dependencies": { 3344 + "fetch-blob": "^3.1.2" 3345 + }, 3346 + "engines": { 3347 + "node": ">=12.20.0" 3348 + } 3349 + }, 3350 + "node_modules/forwarded": { 3351 + "version": "0.2.0", 3352 + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 3353 + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 3354 + "engines": { 3355 + "node": ">= 0.6" 3356 + } 3357 + }, 3358 + "node_modules/framer-motion": { 3359 + "version": "12.35.2", 3360 + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.35.2.tgz", 3361 + "integrity": "sha512-dhfuEMaNo0hc+AEqyHiIfiJRNb9U9UQutE9FoKm5pjf7CMitp9xPEF1iWZihR1q86LBmo6EJ7S8cN8QXEy49AA==", 3362 + "dependencies": { 3363 + "motion-dom": "^12.35.2", 3364 + "motion-utils": "^12.29.2", 3365 + "tslib": "^2.4.0" 3366 + }, 3367 + "peerDependencies": { 3368 + "@emotion/is-prop-valid": "*", 3369 + "react": "^18.0.0 || ^19.0.0", 3370 + "react-dom": "^18.0.0 || ^19.0.0" 3371 + }, 3372 + "peerDependenciesMeta": { 3373 + "@emotion/is-prop-valid": { 3374 + "optional": true 3375 + }, 3376 + "react": { 3377 + "optional": true 3378 + }, 3379 + "react-dom": { 3380 + "optional": true 3381 + } 3382 + } 3383 + }, 3384 + "node_modules/fresh": { 3385 + "version": "2.0.0", 3386 + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", 3387 + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", 3388 + "engines": { 3389 + "node": ">= 0.8" 3390 + } 3391 + }, 3392 + "node_modules/fs-extra": { 3393 + "version": "11.3.4", 3394 + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", 3395 + "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", 3396 + "dependencies": { 3397 + "graceful-fs": "^4.2.0", 3398 + "jsonfile": "^6.0.1", 3399 + "universalify": "^2.0.0" 3400 + }, 3401 + "engines": { 3402 + "node": ">=14.14" 3403 + } 3404 + }, 1271 3405 "node_modules/function-bind": { 1272 3406 "version": "1.1.2", 1273 3407 "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 1274 3408 "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 1275 - "license": "MIT", 1276 3409 "funding": { 1277 3410 "url": "https://github.com/sponsors/ljharb" 1278 3411 } 1279 3412 }, 3413 + "node_modules/fuzzysort": { 3414 + "version": "3.1.0", 3415 + "resolved": "https://registry.npmjs.org/fuzzysort/-/fuzzysort-3.1.0.tgz", 3416 + "integrity": "sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ==" 3417 + }, 3418 + "node_modules/fzf": { 3419 + "version": "0.5.2", 3420 + "resolved": "https://registry.npmjs.org/fzf/-/fzf-0.5.2.tgz", 3421 + "integrity": "sha512-Tt4kuxLXFKHy8KT40zwsUPUkg1CrsgY25FxA2U/j/0WgEDCk3ddc/zLTCCcbSHX9FcKtLuVaDGtGE/STWC+j3Q==" 3422 + }, 3423 + "node_modules/gensync": { 3424 + "version": "1.0.0-beta.2", 3425 + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", 3426 + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", 3427 + "engines": { 3428 + "node": ">=6.9.0" 3429 + } 3430 + }, 3431 + "node_modules/get-caller-file": { 3432 + "version": "2.0.5", 3433 + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 3434 + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 3435 + "engines": { 3436 + "node": "6.* || 8.* || >= 10.*" 3437 + } 3438 + }, 3439 + "node_modules/get-east-asian-width": { 3440 + "version": "1.5.0", 3441 + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", 3442 + "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", 3443 + "engines": { 3444 + "node": ">=18" 3445 + }, 3446 + "funding": { 3447 + "url": "https://github.com/sponsors/sindresorhus" 3448 + } 3449 + }, 1280 3450 "node_modules/get-intrinsic": { 1281 3451 "version": "1.3.0", 1282 3452 "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", 1283 3453 "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", 1284 - "license": "MIT", 1285 3454 "dependencies": { 1286 3455 "call-bind-apply-helpers": "^1.0.2", 1287 3456 "es-define-property": "^1.0.1", ··· 1301 3470 "url": "https://github.com/sponsors/ljharb" 1302 3471 } 1303 3472 }, 3473 + "node_modules/get-nonce": { 3474 + "version": "1.0.1", 3475 + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", 3476 + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", 3477 + "engines": { 3478 + "node": ">=6" 3479 + } 3480 + }, 3481 + "node_modules/get-own-enumerable-keys": { 3482 + "version": "1.0.0", 3483 + "resolved": "https://registry.npmjs.org/get-own-enumerable-keys/-/get-own-enumerable-keys-1.0.0.tgz", 3484 + "integrity": "sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA==", 3485 + "engines": { 3486 + "node": ">=14.16" 3487 + }, 3488 + "funding": { 3489 + "url": "https://github.com/sponsors/sindresorhus" 3490 + } 3491 + }, 1304 3492 "node_modules/get-proto": { 1305 3493 "version": "1.0.1", 1306 3494 "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", 1307 3495 "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", 1308 - "license": "MIT", 1309 3496 "dependencies": { 1310 3497 "dunder-proto": "^1.0.1", 1311 3498 "es-object-atoms": "^1.0.0" ··· 1314 3501 "node": ">= 0.4" 1315 3502 } 1316 3503 }, 3504 + "node_modules/get-stream": { 3505 + "version": "9.0.1", 3506 + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", 3507 + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", 3508 + "dependencies": { 3509 + "@sec-ant/readable-stream": "^0.4.1", 3510 + "is-stream": "^4.0.1" 3511 + }, 3512 + "engines": { 3513 + "node": ">=18" 3514 + }, 3515 + "funding": { 3516 + "url": "https://github.com/sponsors/sindresorhus" 3517 + } 3518 + }, 3519 + "node_modules/glob-parent": { 3520 + "version": "5.1.2", 3521 + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 3522 + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 3523 + "dependencies": { 3524 + "is-glob": "^4.0.1" 3525 + }, 3526 + "engines": { 3527 + "node": ">= 6" 3528 + } 3529 + }, 1317 3530 "node_modules/gopd": { 1318 3531 "version": "1.2.0", 1319 3532 "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 1320 3533 "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 1321 - "license": "MIT", 1322 3534 "engines": { 1323 3535 "node": ">= 0.4" 1324 3536 }, ··· 1329 3541 "node_modules/graceful-fs": { 1330 3542 "version": "4.2.11", 1331 3543 "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 1332 - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", 1333 - "license": "ISC" 3544 + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" 3545 + }, 3546 + "node_modules/graphql": { 3547 + "version": "16.13.1", 3548 + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.13.1.tgz", 3549 + "integrity": "sha512-gGgrVCoDKlIZ8fIqXBBb0pPKqDgki0Z/FSKNiQzSGj2uEYHr1tq5wmBegGwJx6QB5S5cM0khSBpi/JFHMCvsmQ==", 3550 + "engines": { 3551 + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" 3552 + } 1334 3553 }, 1335 3554 "node_modules/has-symbols": { 1336 3555 "version": "1.1.0", 1337 3556 "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 1338 3557 "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 1339 - "license": "MIT", 1340 3558 "engines": { 1341 3559 "node": ">= 0.4" 1342 3560 }, ··· 1348 3566 "version": "2.0.2", 1349 3567 "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 1350 3568 "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 1351 - "license": "MIT", 1352 3569 "dependencies": { 1353 3570 "function-bind": "^1.1.2" 1354 3571 }, ··· 1356 3573 "node": ">= 0.4" 1357 3574 } 1358 3575 }, 3576 + "node_modules/headers-polyfill": { 3577 + "version": "4.0.3", 3578 + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", 3579 + "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==" 3580 + }, 3581 + "node_modules/hono": { 3582 + "version": "4.12.7", 3583 + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.7.tgz", 3584 + "integrity": "sha512-jq9l1DM0zVIvsm3lv9Nw9nlJnMNPOcAtsbsgiUhWcFzPE99Gvo6yRTlszSLLYacMeQ6quHD6hMfId8crVHvexw==", 3585 + "engines": { 3586 + "node": ">=16.9.0" 3587 + } 3588 + }, 3589 + "node_modules/http-errors": { 3590 + "version": "2.0.1", 3591 + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", 3592 + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", 3593 + "dependencies": { 3594 + "depd": "~2.0.0", 3595 + "inherits": "~2.0.4", 3596 + "setprototypeof": "~1.2.0", 3597 + "statuses": "~2.0.2", 3598 + "toidentifier": "~1.0.1" 3599 + }, 3600 + "engines": { 3601 + "node": ">= 0.8" 3602 + }, 3603 + "funding": { 3604 + "type": "opencollective", 3605 + "url": "https://opencollective.com/express" 3606 + } 3607 + }, 3608 + "node_modules/https-proxy-agent": { 3609 + "version": "7.0.6", 3610 + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", 3611 + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", 3612 + "dependencies": { 3613 + "agent-base": "^7.1.2", 3614 + "debug": "4" 3615 + }, 3616 + "engines": { 3617 + "node": ">= 14" 3618 + } 3619 + }, 3620 + "node_modules/human-signals": { 3621 + "version": "8.0.1", 3622 + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", 3623 + "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", 3624 + "engines": { 3625 + "node": ">=18.18.0" 3626 + } 3627 + }, 3628 + "node_modules/iceberg-js": { 3629 + "version": "0.8.1", 3630 + "resolved": "https://registry.npmjs.org/iceberg-js/-/iceberg-js-0.8.1.tgz", 3631 + "integrity": "sha512-1dhVQZXhcHje7798IVM+xoo/1ZdVfzOMIc8/rgVSijRK38EDqOJoGula9N/8ZI5RD8QTxNQtK/Gozpr+qUqRRA==", 3632 + "engines": { 3633 + "node": ">=20.0.0" 3634 + } 3635 + }, 3636 + "node_modules/iconv-lite": { 3637 + "version": "0.7.2", 3638 + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", 3639 + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", 3640 + "dependencies": { 3641 + "safer-buffer": ">= 2.1.2 < 3.0.0" 3642 + }, 3643 + "engines": { 3644 + "node": ">=0.10.0" 3645 + }, 3646 + "funding": { 3647 + "type": "opencollective", 3648 + "url": "https://opencollective.com/express" 3649 + } 3650 + }, 3651 + "node_modules/ignore": { 3652 + "version": "5.3.2", 3653 + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", 3654 + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", 3655 + "engines": { 3656 + "node": ">= 4" 3657 + } 3658 + }, 3659 + "node_modules/import-fresh": { 3660 + "version": "3.3.1", 3661 + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", 3662 + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", 3663 + "dependencies": { 3664 + "parent-module": "^1.0.0", 3665 + "resolve-from": "^4.0.0" 3666 + }, 3667 + "engines": { 3668 + "node": ">=6" 3669 + }, 3670 + "funding": { 3671 + "url": "https://github.com/sponsors/sindresorhus" 3672 + } 3673 + }, 3674 + "node_modules/inherits": { 3675 + "version": "2.0.4", 3676 + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 3677 + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 3678 + }, 3679 + "node_modules/ip-address": { 3680 + "version": "10.1.0", 3681 + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", 3682 + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", 3683 + "engines": { 3684 + "node": ">= 12" 3685 + } 3686 + }, 3687 + "node_modules/ipaddr.js": { 3688 + "version": "1.9.1", 3689 + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 3690 + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 3691 + "engines": { 3692 + "node": ">= 0.10" 3693 + } 3694 + }, 3695 + "node_modules/is-arrayish": { 3696 + "version": "0.2.1", 3697 + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 3698 + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" 3699 + }, 3700 + "node_modules/is-docker": { 3701 + "version": "3.0.0", 3702 + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", 3703 + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", 3704 + "bin": { 3705 + "is-docker": "cli.js" 3706 + }, 3707 + "engines": { 3708 + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 3709 + }, 3710 + "funding": { 3711 + "url": "https://github.com/sponsors/sindresorhus" 3712 + } 3713 + }, 3714 + "node_modules/is-extglob": { 3715 + "version": "2.1.1", 3716 + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 3717 + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 3718 + "engines": { 3719 + "node": ">=0.10.0" 3720 + } 3721 + }, 3722 + "node_modules/is-fullwidth-code-point": { 3723 + "version": "3.0.0", 3724 + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 3725 + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 3726 + "engines": { 3727 + "node": ">=8" 3728 + } 3729 + }, 3730 + "node_modules/is-glob": { 3731 + "version": "4.0.3", 3732 + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 3733 + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 3734 + "dependencies": { 3735 + "is-extglob": "^2.1.1" 3736 + }, 3737 + "engines": { 3738 + "node": ">=0.10.0" 3739 + } 3740 + }, 3741 + "node_modules/is-in-ssh": { 3742 + "version": "1.0.0", 3743 + "resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz", 3744 + "integrity": "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==", 3745 + "engines": { 3746 + "node": ">=20" 3747 + }, 3748 + "funding": { 3749 + "url": "https://github.com/sponsors/sindresorhus" 3750 + } 3751 + }, 3752 + "node_modules/is-inside-container": { 3753 + "version": "1.0.0", 3754 + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", 3755 + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", 3756 + "dependencies": { 3757 + "is-docker": "^3.0.0" 3758 + }, 3759 + "bin": { 3760 + "is-inside-container": "cli.js" 3761 + }, 3762 + "engines": { 3763 + "node": ">=14.16" 3764 + }, 3765 + "funding": { 3766 + "url": "https://github.com/sponsors/sindresorhus" 3767 + } 3768 + }, 3769 + "node_modules/is-interactive": { 3770 + "version": "2.0.0", 3771 + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", 3772 + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", 3773 + "engines": { 3774 + "node": ">=12" 3775 + }, 3776 + "funding": { 3777 + "url": "https://github.com/sponsors/sindresorhus" 3778 + } 3779 + }, 3780 + "node_modules/is-node-process": { 3781 + "version": "1.2.0", 3782 + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", 3783 + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==" 3784 + }, 3785 + "node_modules/is-number": { 3786 + "version": "7.0.0", 3787 + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 3788 + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 3789 + "engines": { 3790 + "node": ">=0.12.0" 3791 + } 3792 + }, 3793 + "node_modules/is-obj": { 3794 + "version": "3.0.0", 3795 + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-3.0.0.tgz", 3796 + "integrity": "sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==", 3797 + "engines": { 3798 + "node": ">=12" 3799 + }, 3800 + "funding": { 3801 + "url": "https://github.com/sponsors/sindresorhus" 3802 + } 3803 + }, 3804 + "node_modules/is-plain-obj": { 3805 + "version": "4.1.0", 3806 + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", 3807 + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", 3808 + "engines": { 3809 + "node": ">=12" 3810 + }, 3811 + "funding": { 3812 + "url": "https://github.com/sponsors/sindresorhus" 3813 + } 3814 + }, 3815 + "node_modules/is-promise": { 3816 + "version": "4.0.0", 3817 + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", 3818 + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" 3819 + }, 3820 + "node_modules/is-regexp": { 3821 + "version": "3.1.0", 3822 + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-3.1.0.tgz", 3823 + "integrity": "sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==", 3824 + "engines": { 3825 + "node": ">=12" 3826 + }, 3827 + "funding": { 3828 + "url": "https://github.com/sponsors/sindresorhus" 3829 + } 3830 + }, 3831 + "node_modules/is-stream": { 3832 + "version": "4.0.1", 3833 + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", 3834 + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", 3835 + "engines": { 3836 + "node": ">=18" 3837 + }, 3838 + "funding": { 3839 + "url": "https://github.com/sponsors/sindresorhus" 3840 + } 3841 + }, 3842 + "node_modules/is-unicode-supported": { 3843 + "version": "2.1.0", 3844 + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", 3845 + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", 3846 + "engines": { 3847 + "node": ">=18" 3848 + }, 3849 + "funding": { 3850 + "url": "https://github.com/sponsors/sindresorhus" 3851 + } 3852 + }, 3853 + "node_modules/is-wsl": { 3854 + "version": "3.1.1", 3855 + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", 3856 + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", 3857 + "dependencies": { 3858 + "is-inside-container": "^1.0.0" 3859 + }, 3860 + "engines": { 3861 + "node": ">=16" 3862 + }, 3863 + "funding": { 3864 + "url": "https://github.com/sponsors/sindresorhus" 3865 + } 3866 + }, 3867 + "node_modules/isexe": { 3868 + "version": "3.1.5", 3869 + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.5.tgz", 3870 + "integrity": "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==", 3871 + "engines": { 3872 + "node": ">=18" 3873 + } 3874 + }, 1359 3875 "node_modules/jiti": { 1360 3876 "version": "2.6.1", 1361 3877 "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", 1362 3878 "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", 1363 - "license": "MIT", 1364 3879 "bin": { 1365 3880 "jiti": "lib/jiti-cli.mjs" 1366 3881 } 1367 3882 }, 3883 + "node_modules/jose": { 3884 + "version": "6.2.1", 3885 + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.1.tgz", 3886 + "integrity": "sha512-jUaKr1yrbfaImV7R2TN/b3IcZzsw38/chqMpo2XJ7i2F8AfM/lA4G1goC3JVEwg0H7UldTmSt3P68nt31W7/mw==", 3887 + "funding": { 3888 + "url": "https://github.com/sponsors/panva" 3889 + } 3890 + }, 1368 3891 "node_modules/js-tokens": { 1369 3892 "version": "4.0.0", 1370 3893 "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 1371 - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 1372 - "license": "MIT" 3894 + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 3895 + }, 3896 + "node_modules/js-yaml": { 3897 + "version": "4.1.1", 3898 + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", 3899 + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", 3900 + "dependencies": { 3901 + "argparse": "^2.0.1" 3902 + }, 3903 + "bin": { 3904 + "js-yaml": "bin/js-yaml.js" 3905 + } 3906 + }, 3907 + "node_modules/jsesc": { 3908 + "version": "3.1.0", 3909 + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", 3910 + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", 3911 + "bin": { 3912 + "jsesc": "bin/jsesc" 3913 + }, 3914 + "engines": { 3915 + "node": ">=6" 3916 + } 3917 + }, 3918 + "node_modules/json-parse-even-better-errors": { 3919 + "version": "2.3.1", 3920 + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", 3921 + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" 3922 + }, 3923 + "node_modules/json-schema-traverse": { 3924 + "version": "1.0.0", 3925 + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", 3926 + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" 3927 + }, 3928 + "node_modules/json-schema-typed": { 3929 + "version": "8.0.2", 3930 + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz", 3931 + "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==" 3932 + }, 3933 + "node_modules/json5": { 3934 + "version": "2.2.3", 3935 + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", 3936 + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", 3937 + "bin": { 3938 + "json5": "lib/cli.js" 3939 + }, 3940 + "engines": { 3941 + "node": ">=6" 3942 + } 3943 + }, 3944 + "node_modules/jsonfile": { 3945 + "version": "6.2.0", 3946 + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", 3947 + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", 3948 + "dependencies": { 3949 + "universalify": "^2.0.0" 3950 + }, 3951 + "optionalDependencies": { 3952 + "graceful-fs": "^4.1.6" 3953 + } 3954 + }, 3955 + "node_modules/kleur": { 3956 + "version": "4.1.5", 3957 + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", 3958 + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", 3959 + "engines": { 3960 + "node": ">=6" 3961 + } 1373 3962 }, 1374 3963 "node_modules/lightningcss": { 1375 - "version": "1.30.2", 1376 - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", 1377 - "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", 1378 - "license": "MPL-2.0", 3964 + "version": "1.31.1", 3965 + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", 3966 + "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", 1379 3967 "dependencies": { 1380 3968 "detect-libc": "^2.0.3" 1381 3969 }, ··· 1387 3975 "url": "https://opencollective.com/parcel" 1388 3976 }, 1389 3977 "optionalDependencies": { 1390 - "lightningcss-android-arm64": "1.30.2", 1391 - "lightningcss-darwin-arm64": "1.30.2", 1392 - "lightningcss-darwin-x64": "1.30.2", 1393 - "lightningcss-freebsd-x64": "1.30.2", 1394 - "lightningcss-linux-arm-gnueabihf": "1.30.2", 1395 - "lightningcss-linux-arm64-gnu": "1.30.2", 1396 - "lightningcss-linux-arm64-musl": "1.30.2", 1397 - "lightningcss-linux-x64-gnu": "1.30.2", 1398 - "lightningcss-linux-x64-musl": "1.30.2", 1399 - "lightningcss-win32-arm64-msvc": "1.30.2", 1400 - "lightningcss-win32-x64-msvc": "1.30.2" 3978 + "lightningcss-android-arm64": "1.31.1", 3979 + "lightningcss-darwin-arm64": "1.31.1", 3980 + "lightningcss-darwin-x64": "1.31.1", 3981 + "lightningcss-freebsd-x64": "1.31.1", 3982 + "lightningcss-linux-arm-gnueabihf": "1.31.1", 3983 + "lightningcss-linux-arm64-gnu": "1.31.1", 3984 + "lightningcss-linux-arm64-musl": "1.31.1", 3985 + "lightningcss-linux-x64-gnu": "1.31.1", 3986 + "lightningcss-linux-x64-musl": "1.31.1", 3987 + "lightningcss-win32-arm64-msvc": "1.31.1", 3988 + "lightningcss-win32-x64-msvc": "1.31.1" 1401 3989 } 1402 3990 }, 1403 3991 "node_modules/lightningcss-android-arm64": { 1404 - "version": "1.30.2", 1405 - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", 1406 - "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", 3992 + "version": "1.31.1", 3993 + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz", 3994 + "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==", 1407 3995 "cpu": [ 1408 3996 "arm64" 1409 3997 ], 1410 - "license": "MPL-2.0", 1411 3998 "optional": true, 1412 3999 "os": [ 1413 4000 "android" ··· 1421 4008 } 1422 4009 }, 1423 4010 "node_modules/lightningcss-darwin-arm64": { 1424 - "version": "1.30.2", 1425 - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", 1426 - "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", 4011 + "version": "1.31.1", 4012 + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz", 4013 + "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==", 1427 4014 "cpu": [ 1428 4015 "arm64" 1429 4016 ], 1430 - "license": "MPL-2.0", 1431 4017 "optional": true, 1432 4018 "os": [ 1433 4019 "darwin" ··· 1441 4027 } 1442 4028 }, 1443 4029 "node_modules/lightningcss-darwin-x64": { 1444 - "version": "1.30.2", 1445 - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", 1446 - "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", 4030 + "version": "1.31.1", 4031 + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz", 4032 + "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==", 1447 4033 "cpu": [ 1448 4034 "x64" 1449 4035 ], 1450 - "license": "MPL-2.0", 1451 4036 "optional": true, 1452 4037 "os": [ 1453 4038 "darwin" ··· 1461 4046 } 1462 4047 }, 1463 4048 "node_modules/lightningcss-freebsd-x64": { 1464 - "version": "1.30.2", 1465 - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", 1466 - "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", 4049 + "version": "1.31.1", 4050 + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz", 4051 + "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==", 1467 4052 "cpu": [ 1468 4053 "x64" 1469 4054 ], 1470 - "license": "MPL-2.0", 1471 4055 "optional": true, 1472 4056 "os": [ 1473 4057 "freebsd" ··· 1481 4065 } 1482 4066 }, 1483 4067 "node_modules/lightningcss-linux-arm-gnueabihf": { 1484 - "version": "1.30.2", 1485 - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", 1486 - "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", 4068 + "version": "1.31.1", 4069 + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz", 4070 + "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==", 1487 4071 "cpu": [ 1488 4072 "arm" 1489 4073 ], 1490 - "license": "MPL-2.0", 1491 4074 "optional": true, 1492 4075 "os": [ 1493 4076 "linux" ··· 1501 4084 } 1502 4085 }, 1503 4086 "node_modules/lightningcss-linux-arm64-gnu": { 1504 - "version": "1.30.2", 1505 - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", 1506 - "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", 4087 + "version": "1.31.1", 4088 + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz", 4089 + "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==", 1507 4090 "cpu": [ 1508 4091 "arm64" 1509 4092 ], 1510 - "license": "MPL-2.0", 1511 4093 "optional": true, 1512 4094 "os": [ 1513 4095 "linux" ··· 1521 4103 } 1522 4104 }, 1523 4105 "node_modules/lightningcss-linux-arm64-musl": { 1524 - "version": "1.30.2", 1525 - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", 1526 - "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", 4106 + "version": "1.31.1", 4107 + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz", 4108 + "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==", 1527 4109 "cpu": [ 1528 4110 "arm64" 1529 4111 ], 1530 - "license": "MPL-2.0", 1531 4112 "optional": true, 1532 4113 "os": [ 1533 4114 "linux" ··· 1541 4122 } 1542 4123 }, 1543 4124 "node_modules/lightningcss-linux-x64-gnu": { 1544 - "version": "1.30.2", 1545 - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", 1546 - "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", 4125 + "version": "1.31.1", 4126 + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz", 4127 + "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==", 1547 4128 "cpu": [ 1548 4129 "x64" 1549 4130 ], 1550 - "license": "MPL-2.0", 1551 4131 "optional": true, 1552 4132 "os": [ 1553 4133 "linux" ··· 1561 4141 } 1562 4142 }, 1563 4143 "node_modules/lightningcss-linux-x64-musl": { 1564 - "version": "1.30.2", 1565 - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", 1566 - "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", 4144 + "version": "1.31.1", 4145 + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz", 4146 + "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==", 1567 4147 "cpu": [ 1568 4148 "x64" 1569 4149 ], 1570 - "license": "MPL-2.0", 1571 4150 "optional": true, 1572 4151 "os": [ 1573 4152 "linux" ··· 1581 4160 } 1582 4161 }, 1583 4162 "node_modules/lightningcss-win32-arm64-msvc": { 1584 - "version": "1.30.2", 1585 - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", 1586 - "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", 4163 + "version": "1.31.1", 4164 + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz", 4165 + "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==", 1587 4166 "cpu": [ 1588 4167 "arm64" 1589 4168 ], 1590 - "license": "MPL-2.0", 1591 4169 "optional": true, 1592 4170 "os": [ 1593 4171 "win32" ··· 1601 4179 } 1602 4180 }, 1603 4181 "node_modules/lightningcss-win32-x64-msvc": { 1604 - "version": "1.30.2", 1605 - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", 1606 - "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", 4182 + "version": "1.31.1", 4183 + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz", 4184 + "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==", 1607 4185 "cpu": [ 1608 4186 "x64" 1609 4187 ], 1610 - "license": "MPL-2.0", 1611 4188 "optional": true, 1612 4189 "os": [ 1613 4190 "win32" ··· 1620 4197 "url": "https://opencollective.com/parcel" 1621 4198 } 1622 4199 }, 4200 + "node_modules/lines-and-columns": { 4201 + "version": "1.2.4", 4202 + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", 4203 + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" 4204 + }, 4205 + "node_modules/log-symbols": { 4206 + "version": "6.0.0", 4207 + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", 4208 + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", 4209 + "dependencies": { 4210 + "chalk": "^5.3.0", 4211 + "is-unicode-supported": "^1.3.0" 4212 + }, 4213 + "engines": { 4214 + "node": ">=18" 4215 + }, 4216 + "funding": { 4217 + "url": "https://github.com/sponsors/sindresorhus" 4218 + } 4219 + }, 4220 + "node_modules/log-symbols/node_modules/is-unicode-supported": { 4221 + "version": "1.3.0", 4222 + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", 4223 + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", 4224 + "engines": { 4225 + "node": ">=12" 4226 + }, 4227 + "funding": { 4228 + "url": "https://github.com/sponsors/sindresorhus" 4229 + } 4230 + }, 1623 4231 "node_modules/loose-envify": { 1624 4232 "version": "1.4.0", 1625 4233 "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", 1626 4234 "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", 1627 - "license": "MIT", 1628 4235 "dependencies": { 1629 4236 "js-tokens": "^3.0.0 || ^4.0.0" 1630 4237 }, ··· 1632 4239 "loose-envify": "cli.js" 1633 4240 } 1634 4241 }, 4242 + "node_modules/lru-cache": { 4243 + "version": "5.1.1", 4244 + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", 4245 + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", 4246 + "dependencies": { 4247 + "yallist": "^3.0.2" 4248 + } 4249 + }, 1635 4250 "node_modules/lucide-react": { 1636 4251 "version": "0.562.0", 1637 4252 "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.562.0.tgz", 1638 4253 "integrity": "sha512-82hOAu7y0dbVuFfmO4bYF1XEwYk/mEbM5E+b1jgci/udUBEE/R7LF5Ip0CCEmXe8AybRM8L+04eP+LGZeDvkiw==", 1639 - "license": "ISC", 1640 4254 "peerDependencies": { 1641 4255 "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" 1642 4256 } ··· 1645 4259 "version": "0.30.21", 1646 4260 "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", 1647 4261 "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", 1648 - "license": "MIT", 1649 4262 "dependencies": { 1650 4263 "@jridgewell/sourcemap-codec": "^1.5.5" 1651 4264 } ··· 1654 4267 "version": "1.1.0", 1655 4268 "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 1656 4269 "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 1657 - "license": "MIT", 1658 4270 "engines": { 1659 4271 "node": ">= 0.4" 1660 4272 } 1661 4273 }, 4274 + "node_modules/media-typer": { 4275 + "version": "1.1.0", 4276 + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", 4277 + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", 4278 + "engines": { 4279 + "node": ">= 0.8" 4280 + } 4281 + }, 4282 + "node_modules/merge-descriptors": { 4283 + "version": "2.0.0", 4284 + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", 4285 + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", 4286 + "engines": { 4287 + "node": ">=18" 4288 + }, 4289 + "funding": { 4290 + "url": "https://github.com/sponsors/sindresorhus" 4291 + } 4292 + }, 4293 + "node_modules/merge-stream": { 4294 + "version": "2.0.0", 4295 + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", 4296 + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" 4297 + }, 4298 + "node_modules/merge2": { 4299 + "version": "1.4.1", 4300 + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 4301 + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 4302 + "engines": { 4303 + "node": ">= 8" 4304 + } 4305 + }, 4306 + "node_modules/micromatch": { 4307 + "version": "4.0.8", 4308 + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", 4309 + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", 4310 + "dependencies": { 4311 + "braces": "^3.0.3", 4312 + "picomatch": "^2.3.1" 4313 + }, 4314 + "engines": { 4315 + "node": ">=8.6" 4316 + } 4317 + }, 4318 + "node_modules/micromatch/node_modules/picomatch": { 4319 + "version": "2.3.1", 4320 + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 4321 + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 4322 + "engines": { 4323 + "node": ">=8.6" 4324 + }, 4325 + "funding": { 4326 + "url": "https://github.com/sponsors/jonschlinkert" 4327 + } 4328 + }, 4329 + "node_modules/mime-db": { 4330 + "version": "1.54.0", 4331 + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", 4332 + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", 4333 + "engines": { 4334 + "node": ">= 0.6" 4335 + } 4336 + }, 4337 + "node_modules/mime-types": { 4338 + "version": "3.0.2", 4339 + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", 4340 + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", 4341 + "dependencies": { 4342 + "mime-db": "^1.54.0" 4343 + }, 4344 + "engines": { 4345 + "node": ">=18" 4346 + }, 4347 + "funding": { 4348 + "type": "opencollective", 4349 + "url": "https://opencollective.com/express" 4350 + } 4351 + }, 4352 + "node_modules/mimic-fn": { 4353 + "version": "2.1.0", 4354 + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 4355 + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", 4356 + "engines": { 4357 + "node": ">=6" 4358 + } 4359 + }, 4360 + "node_modules/mimic-function": { 4361 + "version": "5.0.1", 4362 + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", 4363 + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", 4364 + "engines": { 4365 + "node": ">=18" 4366 + }, 4367 + "funding": { 4368 + "url": "https://github.com/sponsors/sindresorhus" 4369 + } 4370 + }, 4371 + "node_modules/minimatch": { 4372 + "version": "10.2.4", 4373 + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", 4374 + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", 4375 + "dependencies": { 4376 + "brace-expansion": "^5.0.2" 4377 + }, 4378 + "engines": { 4379 + "node": "18 || 20 || >=22" 4380 + }, 4381 + "funding": { 4382 + "url": "https://github.com/sponsors/isaacs" 4383 + } 4384 + }, 4385 + "node_modules/minimist": { 4386 + "version": "1.2.8", 4387 + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 4388 + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 4389 + "funding": { 4390 + "url": "https://github.com/sponsors/ljharb" 4391 + } 4392 + }, 4393 + "node_modules/motion-dom": { 4394 + "version": "12.35.2", 4395 + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.35.2.tgz", 4396 + "integrity": "sha512-pWXFMTwvGDbx1Fe9YL5HZebv2NhvGBzRtiNUv58aoK7+XrsuaydQ0JGRKK2r+bTKlwgSWwWxHbP5249Qr/BNpg==", 4397 + "dependencies": { 4398 + "motion-utils": "^12.29.2" 4399 + } 4400 + }, 4401 + "node_modules/motion-utils": { 4402 + "version": "12.29.2", 4403 + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.29.2.tgz", 4404 + "integrity": "sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A==" 4405 + }, 4406 + "node_modules/ms": { 4407 + "version": "2.1.3", 4408 + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 4409 + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 4410 + }, 4411 + "node_modules/msw": { 4412 + "version": "2.12.10", 4413 + "resolved": "https://registry.npmjs.org/msw/-/msw-2.12.10.tgz", 4414 + "integrity": "sha512-G3VUymSE0/iegFnuipujpwyTM2GuZAKXNeerUSrG2+Eg391wW63xFs5ixWsK9MWzr1AGoSkYGmyAzNgbR3+urw==", 4415 + "hasInstallScript": true, 4416 + "dependencies": { 4417 + "@inquirer/confirm": "^5.0.0", 4418 + "@mswjs/interceptors": "^0.41.2", 4419 + "@open-draft/deferred-promise": "^2.2.0", 4420 + "@types/statuses": "^2.0.6", 4421 + "cookie": "^1.0.2", 4422 + "graphql": "^16.12.0", 4423 + "headers-polyfill": "^4.0.2", 4424 + "is-node-process": "^1.2.0", 4425 + "outvariant": "^1.4.3", 4426 + "path-to-regexp": "^6.3.0", 4427 + "picocolors": "^1.1.1", 4428 + "rettime": "^0.10.1", 4429 + "statuses": "^2.0.2", 4430 + "strict-event-emitter": "^0.5.1", 4431 + "tough-cookie": "^6.0.0", 4432 + "type-fest": "^5.2.0", 4433 + "until-async": "^3.0.2", 4434 + "yargs": "^17.7.2" 4435 + }, 4436 + "bin": { 4437 + "msw": "cli/index.js" 4438 + }, 4439 + "engines": { 4440 + "node": ">=18" 4441 + }, 4442 + "funding": { 4443 + "url": "https://github.com/sponsors/mswjs" 4444 + }, 4445 + "peerDependencies": { 4446 + "typescript": ">= 4.8.x" 4447 + }, 4448 + "peerDependenciesMeta": { 4449 + "typescript": { 4450 + "optional": true 4451 + } 4452 + } 4453 + }, 4454 + "node_modules/mute-stream": { 4455 + "version": "2.0.0", 4456 + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", 4457 + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", 4458 + "engines": { 4459 + "node": "^18.17.0 || >=20.5.0" 4460 + } 4461 + }, 1662 4462 "node_modules/nanoid": { 1663 4463 "version": "3.3.11", 1664 4464 "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", ··· 1669 4469 "url": "https://github.com/sponsors/ai" 1670 4470 } 1671 4471 ], 1672 - "license": "MIT", 1673 4472 "bin": { 1674 4473 "nanoid": "bin/nanoid.cjs" 1675 4474 }, ··· 1677 4476 "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1678 4477 } 1679 4478 }, 4479 + "node_modules/negotiator": { 4480 + "version": "1.0.0", 4481 + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", 4482 + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", 4483 + "engines": { 4484 + "node": ">= 0.6" 4485 + } 4486 + }, 1680 4487 "node_modules/next": { 1681 - "version": "16.0.10", 1682 - "resolved": "https://registry.npmjs.org/next/-/next-16.0.10.tgz", 1683 - "integrity": "sha512-RtWh5PUgI+vxlV3HdR+IfWA1UUHu0+Ram/JBO4vWB54cVPentCD0e+lxyAYEsDTqGGMg7qpjhKh6dc6aW7W/sA==", 1684 - "license": "MIT", 4488 + "version": "16.1.6", 4489 + "resolved": "https://registry.npmjs.org/next/-/next-16.1.6.tgz", 4490 + "integrity": "sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw==", 1685 4491 "dependencies": { 1686 - "@next/env": "16.0.10", 4492 + "@next/env": "16.1.6", 1687 4493 "@swc/helpers": "0.5.15", 4494 + "baseline-browser-mapping": "^2.8.3", 1688 4495 "caniuse-lite": "^1.0.30001579", 1689 4496 "postcss": "8.4.31", 1690 4497 "styled-jsx": "5.1.6" ··· 1696 4503 "node": ">=20.9.0" 1697 4504 }, 1698 4505 "optionalDependencies": { 1699 - "@next/swc-darwin-arm64": "16.0.10", 1700 - "@next/swc-darwin-x64": "16.0.10", 1701 - "@next/swc-linux-arm64-gnu": "16.0.10", 1702 - "@next/swc-linux-arm64-musl": "16.0.10", 1703 - "@next/swc-linux-x64-gnu": "16.0.10", 1704 - "@next/swc-linux-x64-musl": "16.0.10", 1705 - "@next/swc-win32-arm64-msvc": "16.0.10", 1706 - "@next/swc-win32-x64-msvc": "16.0.10", 4506 + "@next/swc-darwin-arm64": "16.1.6", 4507 + "@next/swc-darwin-x64": "16.1.6", 4508 + "@next/swc-linux-arm64-gnu": "16.1.6", 4509 + "@next/swc-linux-arm64-musl": "16.1.6", 4510 + "@next/swc-linux-x64-gnu": "16.1.6", 4511 + "@next/swc-linux-x64-musl": "16.1.6", 4512 + "@next/swc-win32-arm64-msvc": "16.1.6", 4513 + "@next/swc-win32-x64-msvc": "16.1.6", 1707 4514 "sharp": "^0.34.4" 1708 4515 }, 1709 4516 "peerDependencies": { ··· 1747 4554 "url": "https://github.com/sponsors/ai" 1748 4555 } 1749 4556 ], 1750 - "license": "MIT", 1751 4557 "dependencies": { 1752 4558 "nanoid": "^3.3.6", 1753 4559 "picocolors": "^1.0.0", ··· 1757 4563 "node": "^10 || ^12 || >=14" 1758 4564 } 1759 4565 }, 4566 + "node_modules/node-domexception": { 4567 + "version": "1.0.0", 4568 + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", 4569 + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", 4570 + "deprecated": "Use your platform's native DOMException instead", 4571 + "funding": [ 4572 + { 4573 + "type": "github", 4574 + "url": "https://github.com/sponsors/jimmywarting" 4575 + }, 4576 + { 4577 + "type": "github", 4578 + "url": "https://paypal.me/jimmywarting" 4579 + } 4580 + ], 4581 + "engines": { 4582 + "node": ">=10.5.0" 4583 + } 4584 + }, 4585 + "node_modules/node-fetch": { 4586 + "version": "3.3.2", 4587 + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", 4588 + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", 4589 + "dependencies": { 4590 + "data-uri-to-buffer": "^4.0.0", 4591 + "fetch-blob": "^3.1.4", 4592 + "formdata-polyfill": "^4.0.10" 4593 + }, 4594 + "engines": { 4595 + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 4596 + }, 4597 + "funding": { 4598 + "type": "opencollective", 4599 + "url": "https://opencollective.com/node-fetch" 4600 + } 4601 + }, 4602 + "node_modules/node-releases": { 4603 + "version": "2.0.36", 4604 + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", 4605 + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==" 4606 + }, 4607 + "node_modules/npm-run-path": { 4608 + "version": "6.0.0", 4609 + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", 4610 + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", 4611 + "dependencies": { 4612 + "path-key": "^4.0.0", 4613 + "unicorn-magic": "^0.3.0" 4614 + }, 4615 + "engines": { 4616 + "node": ">=18" 4617 + }, 4618 + "funding": { 4619 + "url": "https://github.com/sponsors/sindresorhus" 4620 + } 4621 + }, 4622 + "node_modules/npm-run-path/node_modules/path-key": { 4623 + "version": "4.0.0", 4624 + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", 4625 + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", 4626 + "engines": { 4627 + "node": ">=12" 4628 + }, 4629 + "funding": { 4630 + "url": "https://github.com/sponsors/sindresorhus" 4631 + } 4632 + }, 1760 4633 "node_modules/object-assign": { 1761 4634 "version": "4.1.1", 1762 4635 "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1763 4636 "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 1764 - "license": "MIT", 1765 4637 "engines": { 1766 4638 "node": ">=0.10.0" 1767 4639 } ··· 1770 4642 "version": "1.13.4", 1771 4643 "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", 1772 4644 "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", 1773 - "license": "MIT", 1774 4645 "engines": { 1775 4646 "node": ">= 0.4" 1776 4647 }, ··· 1778 4649 "url": "https://github.com/sponsors/ljharb" 1779 4650 } 1780 4651 }, 4652 + "node_modules/object-treeify": { 4653 + "version": "1.1.33", 4654 + "resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-1.1.33.tgz", 4655 + "integrity": "sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==", 4656 + "engines": { 4657 + "node": ">= 10" 4658 + } 4659 + }, 4660 + "node_modules/on-finished": { 4661 + "version": "2.4.1", 4662 + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 4663 + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 4664 + "dependencies": { 4665 + "ee-first": "1.1.1" 4666 + }, 4667 + "engines": { 4668 + "node": ">= 0.8" 4669 + } 4670 + }, 4671 + "node_modules/once": { 4672 + "version": "1.4.0", 4673 + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 4674 + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 4675 + "dependencies": { 4676 + "wrappy": "1" 4677 + } 4678 + }, 4679 + "node_modules/onetime": { 4680 + "version": "7.0.0", 4681 + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", 4682 + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", 4683 + "dependencies": { 4684 + "mimic-function": "^5.0.0" 4685 + }, 4686 + "engines": { 4687 + "node": ">=18" 4688 + }, 4689 + "funding": { 4690 + "url": "https://github.com/sponsors/sindresorhus" 4691 + } 4692 + }, 4693 + "node_modules/open": { 4694 + "version": "11.0.0", 4695 + "resolved": "https://registry.npmjs.org/open/-/open-11.0.0.tgz", 4696 + "integrity": "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==", 4697 + "dependencies": { 4698 + "default-browser": "^5.4.0", 4699 + "define-lazy-prop": "^3.0.0", 4700 + "is-in-ssh": "^1.0.0", 4701 + "is-inside-container": "^1.0.0", 4702 + "powershell-utils": "^0.1.0", 4703 + "wsl-utils": "^0.3.0" 4704 + }, 4705 + "engines": { 4706 + "node": ">=20" 4707 + }, 4708 + "funding": { 4709 + "url": "https://github.com/sponsors/sindresorhus" 4710 + } 4711 + }, 4712 + "node_modules/ora": { 4713 + "version": "8.2.0", 4714 + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", 4715 + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", 4716 + "dependencies": { 4717 + "chalk": "^5.3.0", 4718 + "cli-cursor": "^5.0.0", 4719 + "cli-spinners": "^2.9.2", 4720 + "is-interactive": "^2.0.0", 4721 + "is-unicode-supported": "^2.0.0", 4722 + "log-symbols": "^6.0.0", 4723 + "stdin-discarder": "^0.2.2", 4724 + "string-width": "^7.2.0", 4725 + "strip-ansi": "^7.1.0" 4726 + }, 4727 + "engines": { 4728 + "node": ">=18" 4729 + }, 4730 + "funding": { 4731 + "url": "https://github.com/sponsors/sindresorhus" 4732 + } 4733 + }, 4734 + "node_modules/outvariant": { 4735 + "version": "1.4.3", 4736 + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", 4737 + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==" 4738 + }, 4739 + "node_modules/package-manager-detector": { 4740 + "version": "1.6.0", 4741 + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", 4742 + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==" 4743 + }, 4744 + "node_modules/parent-module": { 4745 + "version": "1.0.1", 4746 + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 4747 + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 4748 + "dependencies": { 4749 + "callsites": "^3.0.0" 4750 + }, 4751 + "engines": { 4752 + "node": ">=6" 4753 + } 4754 + }, 4755 + "node_modules/parse-json": { 4756 + "version": "5.2.0", 4757 + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", 4758 + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", 4759 + "dependencies": { 4760 + "@babel/code-frame": "^7.0.0", 4761 + "error-ex": "^1.3.1", 4762 + "json-parse-even-better-errors": "^2.3.0", 4763 + "lines-and-columns": "^1.1.6" 4764 + }, 4765 + "engines": { 4766 + "node": ">=8" 4767 + }, 4768 + "funding": { 4769 + "url": "https://github.com/sponsors/sindresorhus" 4770 + } 4771 + }, 4772 + "node_modules/parse-ms": { 4773 + "version": "4.0.0", 4774 + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", 4775 + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", 4776 + "engines": { 4777 + "node": ">=18" 4778 + }, 4779 + "funding": { 4780 + "url": "https://github.com/sponsors/sindresorhus" 4781 + } 4782 + }, 4783 + "node_modules/parseurl": { 4784 + "version": "1.3.3", 4785 + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 4786 + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 4787 + "engines": { 4788 + "node": ">= 0.8" 4789 + } 4790 + }, 4791 + "node_modules/path-browserify": { 4792 + "version": "1.0.1", 4793 + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", 4794 + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" 4795 + }, 4796 + "node_modules/path-key": { 4797 + "version": "3.1.1", 4798 + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 4799 + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 4800 + "engines": { 4801 + "node": ">=8" 4802 + } 4803 + }, 4804 + "node_modules/path-to-regexp": { 4805 + "version": "6.3.0", 4806 + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", 4807 + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==" 4808 + }, 1781 4809 "node_modules/picocolors": { 1782 4810 "version": "1.1.1", 1783 4811 "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 1784 - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 1785 - "license": "ISC" 4812 + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" 4813 + }, 4814 + "node_modules/picomatch": { 4815 + "version": "4.0.3", 4816 + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", 4817 + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", 4818 + "engines": { 4819 + "node": ">=12" 4820 + }, 4821 + "funding": { 4822 + "url": "https://github.com/sponsors/jonschlinkert" 4823 + } 4824 + }, 4825 + "node_modules/pkce-challenge": { 4826 + "version": "5.0.1", 4827 + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", 4828 + "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", 4829 + "engines": { 4830 + "node": ">=16.20.0" 4831 + } 1786 4832 }, 1787 4833 "node_modules/postcss": { 1788 - "version": "8.5.6", 1789 - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", 1790 - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", 4834 + "version": "8.5.8", 4835 + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", 4836 + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", 1791 4837 "funding": [ 1792 4838 { 1793 4839 "type": "opencollective", ··· 1802 4848 "url": "https://github.com/sponsors/ai" 1803 4849 } 1804 4850 ], 1805 - "license": "MIT", 1806 4851 "dependencies": { 1807 4852 "nanoid": "^3.3.11", 1808 4853 "picocolors": "^1.1.1", ··· 1812 4857 "node": "^10 || ^12 || >=14" 1813 4858 } 1814 4859 }, 1815 - "node_modules/prop-types": { 1816 - "version": "15.8.1", 1817 - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", 1818 - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", 1819 - "license": "MIT", 4860 + "node_modules/postcss-selector-parser": { 4861 + "version": "7.1.1", 4862 + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", 4863 + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", 4864 + "dependencies": { 4865 + "cssesc": "^3.0.0", 4866 + "util-deprecate": "^1.0.2" 4867 + }, 4868 + "engines": { 4869 + "node": ">=4" 4870 + } 4871 + }, 4872 + "node_modules/powershell-utils": { 4873 + "version": "0.1.0", 4874 + "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz", 4875 + "integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==", 4876 + "engines": { 4877 + "node": ">=20" 4878 + }, 4879 + "funding": { 4880 + "url": "https://github.com/sponsors/sindresorhus" 4881 + } 4882 + }, 4883 + "node_modules/pretty-ms": { 4884 + "version": "9.3.0", 4885 + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", 4886 + "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==", 1820 4887 "dependencies": { 1821 - "loose-envify": "^1.4.0", 1822 - "object-assign": "^4.1.1", 1823 - "react-is": "^16.13.1" 4888 + "parse-ms": "^4.0.0" 4889 + }, 4890 + "engines": { 4891 + "node": ">=18" 4892 + }, 4893 + "funding": { 4894 + "url": "https://github.com/sponsors/sindresorhus" 4895 + } 4896 + }, 4897 + "node_modules/prompts": { 4898 + "version": "2.4.2", 4899 + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", 4900 + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", 4901 + "dependencies": { 4902 + "kleur": "^3.0.3", 4903 + "sisteransi": "^1.0.5" 4904 + }, 4905 + "engines": { 4906 + "node": ">= 6" 4907 + } 4908 + }, 4909 + "node_modules/prompts/node_modules/kleur": { 4910 + "version": "3.0.3", 4911 + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", 4912 + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", 4913 + "engines": { 4914 + "node": ">=6" 4915 + } 4916 + }, 4917 + "node_modules/proxy-addr": { 4918 + "version": "2.0.7", 4919 + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 4920 + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 4921 + "dependencies": { 4922 + "forwarded": "0.2.0", 4923 + "ipaddr.js": "1.9.1" 4924 + }, 4925 + "engines": { 4926 + "node": ">= 0.10" 1824 4927 } 1825 4928 }, 1826 4929 "node_modules/qs": { 1827 - "version": "6.14.0", 1828 - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", 1829 - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", 1830 - "license": "BSD-3-Clause", 4930 + "version": "6.15.0", 4931 + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", 4932 + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", 1831 4933 "dependencies": { 1832 4934 "side-channel": "^1.1.0" 1833 4935 }, ··· 1838 4940 "url": "https://github.com/sponsors/ljharb" 1839 4941 } 1840 4942 }, 4943 + "node_modules/queue-microtask": { 4944 + "version": "1.2.3", 4945 + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 4946 + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 4947 + "funding": [ 4948 + { 4949 + "type": "github", 4950 + "url": "https://github.com/sponsors/feross" 4951 + }, 4952 + { 4953 + "type": "patreon", 4954 + "url": "https://www.patreon.com/feross" 4955 + }, 4956 + { 4957 + "type": "consulting", 4958 + "url": "https://feross.org/support" 4959 + } 4960 + ] 4961 + }, 4962 + "node_modules/radix-ui": { 4963 + "version": "1.4.3", 4964 + "resolved": "https://registry.npmjs.org/radix-ui/-/radix-ui-1.4.3.tgz", 4965 + "integrity": "sha512-aWizCQiyeAenIdUbqEpXgRA1ya65P13NKn/W8rWkcN0OPkRDxdBVLWnIEDsS2RpwCK2nobI7oMUSmexzTDyAmA==", 4966 + "dependencies": { 4967 + "@radix-ui/primitive": "1.1.3", 4968 + "@radix-ui/react-accessible-icon": "1.1.7", 4969 + "@radix-ui/react-accordion": "1.2.12", 4970 + "@radix-ui/react-alert-dialog": "1.1.15", 4971 + "@radix-ui/react-arrow": "1.1.7", 4972 + "@radix-ui/react-aspect-ratio": "1.1.7", 4973 + "@radix-ui/react-avatar": "1.1.10", 4974 + "@radix-ui/react-checkbox": "1.3.3", 4975 + "@radix-ui/react-collapsible": "1.1.12", 4976 + "@radix-ui/react-collection": "1.1.7", 4977 + "@radix-ui/react-compose-refs": "1.1.2", 4978 + "@radix-ui/react-context": "1.1.2", 4979 + "@radix-ui/react-context-menu": "2.2.16", 4980 + "@radix-ui/react-dialog": "1.1.15", 4981 + "@radix-ui/react-direction": "1.1.1", 4982 + "@radix-ui/react-dismissable-layer": "1.1.11", 4983 + "@radix-ui/react-dropdown-menu": "2.1.16", 4984 + "@radix-ui/react-focus-guards": "1.1.3", 4985 + "@radix-ui/react-focus-scope": "1.1.7", 4986 + "@radix-ui/react-form": "0.1.8", 4987 + "@radix-ui/react-hover-card": "1.1.15", 4988 + "@radix-ui/react-label": "2.1.7", 4989 + "@radix-ui/react-menu": "2.1.16", 4990 + "@radix-ui/react-menubar": "1.1.16", 4991 + "@radix-ui/react-navigation-menu": "1.2.14", 4992 + "@radix-ui/react-one-time-password-field": "0.1.8", 4993 + "@radix-ui/react-password-toggle-field": "0.1.3", 4994 + "@radix-ui/react-popover": "1.1.15", 4995 + "@radix-ui/react-popper": "1.2.8", 4996 + "@radix-ui/react-portal": "1.1.9", 4997 + "@radix-ui/react-presence": "1.1.5", 4998 + "@radix-ui/react-primitive": "2.1.3", 4999 + "@radix-ui/react-progress": "1.1.7", 5000 + "@radix-ui/react-radio-group": "1.3.8", 5001 + "@radix-ui/react-roving-focus": "1.1.11", 5002 + "@radix-ui/react-scroll-area": "1.2.10", 5003 + "@radix-ui/react-select": "2.2.6", 5004 + "@radix-ui/react-separator": "1.1.7", 5005 + "@radix-ui/react-slider": "1.3.6", 5006 + "@radix-ui/react-slot": "1.2.3", 5007 + "@radix-ui/react-switch": "1.2.6", 5008 + "@radix-ui/react-tabs": "1.1.13", 5009 + "@radix-ui/react-toast": "1.2.15", 5010 + "@radix-ui/react-toggle": "1.1.10", 5011 + "@radix-ui/react-toggle-group": "1.1.11", 5012 + "@radix-ui/react-toolbar": "1.1.11", 5013 + "@radix-ui/react-tooltip": "1.2.8", 5014 + "@radix-ui/react-use-callback-ref": "1.1.1", 5015 + "@radix-ui/react-use-controllable-state": "1.2.2", 5016 + "@radix-ui/react-use-effect-event": "0.0.2", 5017 + "@radix-ui/react-use-escape-keydown": "1.1.1", 5018 + "@radix-ui/react-use-is-hydrated": "0.1.0", 5019 + "@radix-ui/react-use-layout-effect": "1.1.1", 5020 + "@radix-ui/react-use-size": "1.1.1", 5021 + "@radix-ui/react-visually-hidden": "1.2.3" 5022 + }, 5023 + "peerDependencies": { 5024 + "@types/react": "*", 5025 + "@types/react-dom": "*", 5026 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5027 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5028 + }, 5029 + "peerDependenciesMeta": { 5030 + "@types/react": { 5031 + "optional": true 5032 + }, 5033 + "@types/react-dom": { 5034 + "optional": true 5035 + } 5036 + } 5037 + }, 5038 + "node_modules/radix-ui/node_modules/@radix-ui/react-accessible-icon": { 5039 + "version": "1.1.7", 5040 + "resolved": "https://registry.npmjs.org/@radix-ui/react-accessible-icon/-/react-accessible-icon-1.1.7.tgz", 5041 + "integrity": "sha512-XM+E4WXl0OqUJFovy6GjmxxFyx9opfCAIUku4dlKRd5YEPqt4kALOkQOp0Of6reHuUkJuiPBEc5k0o4z4lTC8A==", 5042 + "dependencies": { 5043 + "@radix-ui/react-visually-hidden": "1.2.3" 5044 + }, 5045 + "peerDependencies": { 5046 + "@types/react": "*", 5047 + "@types/react-dom": "*", 5048 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5049 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5050 + }, 5051 + "peerDependenciesMeta": { 5052 + "@types/react": { 5053 + "optional": true 5054 + }, 5055 + "@types/react-dom": { 5056 + "optional": true 5057 + } 5058 + } 5059 + }, 5060 + "node_modules/radix-ui/node_modules/@radix-ui/react-accordion": { 5061 + "version": "1.2.12", 5062 + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz", 5063 + "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==", 5064 + "dependencies": { 5065 + "@radix-ui/primitive": "1.1.3", 5066 + "@radix-ui/react-collapsible": "1.1.12", 5067 + "@radix-ui/react-collection": "1.1.7", 5068 + "@radix-ui/react-compose-refs": "1.1.2", 5069 + "@radix-ui/react-context": "1.1.2", 5070 + "@radix-ui/react-direction": "1.1.1", 5071 + "@radix-ui/react-id": "1.1.1", 5072 + "@radix-ui/react-primitive": "2.1.3", 5073 + "@radix-ui/react-use-controllable-state": "1.2.2" 5074 + }, 5075 + "peerDependencies": { 5076 + "@types/react": "*", 5077 + "@types/react-dom": "*", 5078 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5079 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5080 + }, 5081 + "peerDependenciesMeta": { 5082 + "@types/react": { 5083 + "optional": true 5084 + }, 5085 + "@types/react-dom": { 5086 + "optional": true 5087 + } 5088 + } 5089 + }, 5090 + "node_modules/radix-ui/node_modules/@radix-ui/react-alert-dialog": { 5091 + "version": "1.1.15", 5092 + "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz", 5093 + "integrity": "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==", 5094 + "dependencies": { 5095 + "@radix-ui/primitive": "1.1.3", 5096 + "@radix-ui/react-compose-refs": "1.1.2", 5097 + "@radix-ui/react-context": "1.1.2", 5098 + "@radix-ui/react-dialog": "1.1.15", 5099 + "@radix-ui/react-primitive": "2.1.3", 5100 + "@radix-ui/react-slot": "1.2.3" 5101 + }, 5102 + "peerDependencies": { 5103 + "@types/react": "*", 5104 + "@types/react-dom": "*", 5105 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5106 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5107 + }, 5108 + "peerDependenciesMeta": { 5109 + "@types/react": { 5110 + "optional": true 5111 + }, 5112 + "@types/react-dom": { 5113 + "optional": true 5114 + } 5115 + } 5116 + }, 5117 + "node_modules/radix-ui/node_modules/@radix-ui/react-arrow": { 5118 + "version": "1.1.7", 5119 + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", 5120 + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", 5121 + "dependencies": { 5122 + "@radix-ui/react-primitive": "2.1.3" 5123 + }, 5124 + "peerDependencies": { 5125 + "@types/react": "*", 5126 + "@types/react-dom": "*", 5127 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5128 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5129 + }, 5130 + "peerDependenciesMeta": { 5131 + "@types/react": { 5132 + "optional": true 5133 + }, 5134 + "@types/react-dom": { 5135 + "optional": true 5136 + } 5137 + } 5138 + }, 5139 + "node_modules/radix-ui/node_modules/@radix-ui/react-aspect-ratio": { 5140 + "version": "1.1.7", 5141 + "resolved": "https://registry.npmjs.org/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.1.7.tgz", 5142 + "integrity": "sha512-Yq6lvO9HQyPwev1onK1daHCHqXVLzPhSVjmsNjCa2Zcxy2f7uJD2itDtxknv6FzAKCwD1qQkeVDmX/cev13n/g==", 5143 + "dependencies": { 5144 + "@radix-ui/react-primitive": "2.1.3" 5145 + }, 5146 + "peerDependencies": { 5147 + "@types/react": "*", 5148 + "@types/react-dom": "*", 5149 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5150 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5151 + }, 5152 + "peerDependenciesMeta": { 5153 + "@types/react": { 5154 + "optional": true 5155 + }, 5156 + "@types/react-dom": { 5157 + "optional": true 5158 + } 5159 + } 5160 + }, 5161 + "node_modules/radix-ui/node_modules/@radix-ui/react-avatar": { 5162 + "version": "1.1.10", 5163 + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.10.tgz", 5164 + "integrity": "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==", 5165 + "dependencies": { 5166 + "@radix-ui/react-context": "1.1.2", 5167 + "@radix-ui/react-primitive": "2.1.3", 5168 + "@radix-ui/react-use-callback-ref": "1.1.1", 5169 + "@radix-ui/react-use-is-hydrated": "0.1.0", 5170 + "@radix-ui/react-use-layout-effect": "1.1.1" 5171 + }, 5172 + "peerDependencies": { 5173 + "@types/react": "*", 5174 + "@types/react-dom": "*", 5175 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5176 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5177 + }, 5178 + "peerDependenciesMeta": { 5179 + "@types/react": { 5180 + "optional": true 5181 + }, 5182 + "@types/react-dom": { 5183 + "optional": true 5184 + } 5185 + } 5186 + }, 5187 + "node_modules/radix-ui/node_modules/@radix-ui/react-checkbox": { 5188 + "version": "1.3.3", 5189 + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz", 5190 + "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==", 5191 + "dependencies": { 5192 + "@radix-ui/primitive": "1.1.3", 5193 + "@radix-ui/react-compose-refs": "1.1.2", 5194 + "@radix-ui/react-context": "1.1.2", 5195 + "@radix-ui/react-presence": "1.1.5", 5196 + "@radix-ui/react-primitive": "2.1.3", 5197 + "@radix-ui/react-use-controllable-state": "1.2.2", 5198 + "@radix-ui/react-use-previous": "1.1.1", 5199 + "@radix-ui/react-use-size": "1.1.1" 5200 + }, 5201 + "peerDependencies": { 5202 + "@types/react": "*", 5203 + "@types/react-dom": "*", 5204 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5205 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5206 + }, 5207 + "peerDependenciesMeta": { 5208 + "@types/react": { 5209 + "optional": true 5210 + }, 5211 + "@types/react-dom": { 5212 + "optional": true 5213 + } 5214 + } 5215 + }, 5216 + "node_modules/radix-ui/node_modules/@radix-ui/react-collapsible": { 5217 + "version": "1.1.12", 5218 + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", 5219 + "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", 5220 + "dependencies": { 5221 + "@radix-ui/primitive": "1.1.3", 5222 + "@radix-ui/react-compose-refs": "1.1.2", 5223 + "@radix-ui/react-context": "1.1.2", 5224 + "@radix-ui/react-id": "1.1.1", 5225 + "@radix-ui/react-presence": "1.1.5", 5226 + "@radix-ui/react-primitive": "2.1.3", 5227 + "@radix-ui/react-use-controllable-state": "1.2.2", 5228 + "@radix-ui/react-use-layout-effect": "1.1.1" 5229 + }, 5230 + "peerDependencies": { 5231 + "@types/react": "*", 5232 + "@types/react-dom": "*", 5233 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5234 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5235 + }, 5236 + "peerDependenciesMeta": { 5237 + "@types/react": { 5238 + "optional": true 5239 + }, 5240 + "@types/react-dom": { 5241 + "optional": true 5242 + } 5243 + } 5244 + }, 5245 + "node_modules/radix-ui/node_modules/@radix-ui/react-collection": { 5246 + "version": "1.1.7", 5247 + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", 5248 + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", 5249 + "dependencies": { 5250 + "@radix-ui/react-compose-refs": "1.1.2", 5251 + "@radix-ui/react-context": "1.1.2", 5252 + "@radix-ui/react-primitive": "2.1.3", 5253 + "@radix-ui/react-slot": "1.2.3" 5254 + }, 5255 + "peerDependencies": { 5256 + "@types/react": "*", 5257 + "@types/react-dom": "*", 5258 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5259 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5260 + }, 5261 + "peerDependenciesMeta": { 5262 + "@types/react": { 5263 + "optional": true 5264 + }, 5265 + "@types/react-dom": { 5266 + "optional": true 5267 + } 5268 + } 5269 + }, 5270 + "node_modules/radix-ui/node_modules/@radix-ui/react-context-menu": { 5271 + "version": "2.2.16", 5272 + "resolved": "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.16.tgz", 5273 + "integrity": "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==", 5274 + "dependencies": { 5275 + "@radix-ui/primitive": "1.1.3", 5276 + "@radix-ui/react-context": "1.1.2", 5277 + "@radix-ui/react-menu": "2.1.16", 5278 + "@radix-ui/react-primitive": "2.1.3", 5279 + "@radix-ui/react-use-callback-ref": "1.1.1", 5280 + "@radix-ui/react-use-controllable-state": "1.2.2" 5281 + }, 5282 + "peerDependencies": { 5283 + "@types/react": "*", 5284 + "@types/react-dom": "*", 5285 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5286 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5287 + }, 5288 + "peerDependenciesMeta": { 5289 + "@types/react": { 5290 + "optional": true 5291 + }, 5292 + "@types/react-dom": { 5293 + "optional": true 5294 + } 5295 + } 5296 + }, 5297 + "node_modules/radix-ui/node_modules/@radix-ui/react-dialog": { 5298 + "version": "1.1.15", 5299 + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", 5300 + "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", 5301 + "dependencies": { 5302 + "@radix-ui/primitive": "1.1.3", 5303 + "@radix-ui/react-compose-refs": "1.1.2", 5304 + "@radix-ui/react-context": "1.1.2", 5305 + "@radix-ui/react-dismissable-layer": "1.1.11", 5306 + "@radix-ui/react-focus-guards": "1.1.3", 5307 + "@radix-ui/react-focus-scope": "1.1.7", 5308 + "@radix-ui/react-id": "1.1.1", 5309 + "@radix-ui/react-portal": "1.1.9", 5310 + "@radix-ui/react-presence": "1.1.5", 5311 + "@radix-ui/react-primitive": "2.1.3", 5312 + "@radix-ui/react-slot": "1.2.3", 5313 + "@radix-ui/react-use-controllable-state": "1.2.2", 5314 + "aria-hidden": "^1.2.4", 5315 + "react-remove-scroll": "^2.6.3" 5316 + }, 5317 + "peerDependencies": { 5318 + "@types/react": "*", 5319 + "@types/react-dom": "*", 5320 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5321 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5322 + }, 5323 + "peerDependenciesMeta": { 5324 + "@types/react": { 5325 + "optional": true 5326 + }, 5327 + "@types/react-dom": { 5328 + "optional": true 5329 + } 5330 + } 5331 + }, 5332 + "node_modules/radix-ui/node_modules/@radix-ui/react-dismissable-layer": { 5333 + "version": "1.1.11", 5334 + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", 5335 + "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", 5336 + "dependencies": { 5337 + "@radix-ui/primitive": "1.1.3", 5338 + "@radix-ui/react-compose-refs": "1.1.2", 5339 + "@radix-ui/react-primitive": "2.1.3", 5340 + "@radix-ui/react-use-callback-ref": "1.1.1", 5341 + "@radix-ui/react-use-escape-keydown": "1.1.1" 5342 + }, 5343 + "peerDependencies": { 5344 + "@types/react": "*", 5345 + "@types/react-dom": "*", 5346 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5347 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5348 + }, 5349 + "peerDependenciesMeta": { 5350 + "@types/react": { 5351 + "optional": true 5352 + }, 5353 + "@types/react-dom": { 5354 + "optional": true 5355 + } 5356 + } 5357 + }, 5358 + "node_modules/radix-ui/node_modules/@radix-ui/react-dropdown-menu": { 5359 + "version": "2.1.16", 5360 + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz", 5361 + "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==", 5362 + "dependencies": { 5363 + "@radix-ui/primitive": "1.1.3", 5364 + "@radix-ui/react-compose-refs": "1.1.2", 5365 + "@radix-ui/react-context": "1.1.2", 5366 + "@radix-ui/react-id": "1.1.1", 5367 + "@radix-ui/react-menu": "2.1.16", 5368 + "@radix-ui/react-primitive": "2.1.3", 5369 + "@radix-ui/react-use-controllable-state": "1.2.2" 5370 + }, 5371 + "peerDependencies": { 5372 + "@types/react": "*", 5373 + "@types/react-dom": "*", 5374 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5375 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5376 + }, 5377 + "peerDependenciesMeta": { 5378 + "@types/react": { 5379 + "optional": true 5380 + }, 5381 + "@types/react-dom": { 5382 + "optional": true 5383 + } 5384 + } 5385 + }, 5386 + "node_modules/radix-ui/node_modules/@radix-ui/react-focus-scope": { 5387 + "version": "1.1.7", 5388 + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", 5389 + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", 5390 + "dependencies": { 5391 + "@radix-ui/react-compose-refs": "1.1.2", 5392 + "@radix-ui/react-primitive": "2.1.3", 5393 + "@radix-ui/react-use-callback-ref": "1.1.1" 5394 + }, 5395 + "peerDependencies": { 5396 + "@types/react": "*", 5397 + "@types/react-dom": "*", 5398 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5399 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5400 + }, 5401 + "peerDependenciesMeta": { 5402 + "@types/react": { 5403 + "optional": true 5404 + }, 5405 + "@types/react-dom": { 5406 + "optional": true 5407 + } 5408 + } 5409 + }, 5410 + "node_modules/radix-ui/node_modules/@radix-ui/react-form": { 5411 + "version": "0.1.8", 5412 + "resolved": "https://registry.npmjs.org/@radix-ui/react-form/-/react-form-0.1.8.tgz", 5413 + "integrity": "sha512-QM70k4Zwjttifr5a4sZFts9fn8FzHYvQ5PiB19O2HsYibaHSVt9fH9rzB0XZo/YcM+b7t/p7lYCT/F5eOeF5yQ==", 5414 + "dependencies": { 5415 + "@radix-ui/primitive": "1.1.3", 5416 + "@radix-ui/react-compose-refs": "1.1.2", 5417 + "@radix-ui/react-context": "1.1.2", 5418 + "@radix-ui/react-id": "1.1.1", 5419 + "@radix-ui/react-label": "2.1.7", 5420 + "@radix-ui/react-primitive": "2.1.3" 5421 + }, 5422 + "peerDependencies": { 5423 + "@types/react": "*", 5424 + "@types/react-dom": "*", 5425 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5426 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5427 + }, 5428 + "peerDependenciesMeta": { 5429 + "@types/react": { 5430 + "optional": true 5431 + }, 5432 + "@types/react-dom": { 5433 + "optional": true 5434 + } 5435 + } 5436 + }, 5437 + "node_modules/radix-ui/node_modules/@radix-ui/react-hover-card": { 5438 + "version": "1.1.15", 5439 + "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.15.tgz", 5440 + "integrity": "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==", 5441 + "dependencies": { 5442 + "@radix-ui/primitive": "1.1.3", 5443 + "@radix-ui/react-compose-refs": "1.1.2", 5444 + "@radix-ui/react-context": "1.1.2", 5445 + "@radix-ui/react-dismissable-layer": "1.1.11", 5446 + "@radix-ui/react-popper": "1.2.8", 5447 + "@radix-ui/react-portal": "1.1.9", 5448 + "@radix-ui/react-presence": "1.1.5", 5449 + "@radix-ui/react-primitive": "2.1.3", 5450 + "@radix-ui/react-use-controllable-state": "1.2.2" 5451 + }, 5452 + "peerDependencies": { 5453 + "@types/react": "*", 5454 + "@types/react-dom": "*", 5455 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5456 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5457 + }, 5458 + "peerDependenciesMeta": { 5459 + "@types/react": { 5460 + "optional": true 5461 + }, 5462 + "@types/react-dom": { 5463 + "optional": true 5464 + } 5465 + } 5466 + }, 5467 + "node_modules/radix-ui/node_modules/@radix-ui/react-label": { 5468 + "version": "2.1.7", 5469 + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", 5470 + "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", 5471 + "dependencies": { 5472 + "@radix-ui/react-primitive": "2.1.3" 5473 + }, 5474 + "peerDependencies": { 5475 + "@types/react": "*", 5476 + "@types/react-dom": "*", 5477 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5478 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5479 + }, 5480 + "peerDependenciesMeta": { 5481 + "@types/react": { 5482 + "optional": true 5483 + }, 5484 + "@types/react-dom": { 5485 + "optional": true 5486 + } 5487 + } 5488 + }, 5489 + "node_modules/radix-ui/node_modules/@radix-ui/react-menu": { 5490 + "version": "2.1.16", 5491 + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", 5492 + "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==", 5493 + "dependencies": { 5494 + "@radix-ui/primitive": "1.1.3", 5495 + "@radix-ui/react-collection": "1.1.7", 5496 + "@radix-ui/react-compose-refs": "1.1.2", 5497 + "@radix-ui/react-context": "1.1.2", 5498 + "@radix-ui/react-direction": "1.1.1", 5499 + "@radix-ui/react-dismissable-layer": "1.1.11", 5500 + "@radix-ui/react-focus-guards": "1.1.3", 5501 + "@radix-ui/react-focus-scope": "1.1.7", 5502 + "@radix-ui/react-id": "1.1.1", 5503 + "@radix-ui/react-popper": "1.2.8", 5504 + "@radix-ui/react-portal": "1.1.9", 5505 + "@radix-ui/react-presence": "1.1.5", 5506 + "@radix-ui/react-primitive": "2.1.3", 5507 + "@radix-ui/react-roving-focus": "1.1.11", 5508 + "@radix-ui/react-slot": "1.2.3", 5509 + "@radix-ui/react-use-callback-ref": "1.1.1", 5510 + "aria-hidden": "^1.2.4", 5511 + "react-remove-scroll": "^2.6.3" 5512 + }, 5513 + "peerDependencies": { 5514 + "@types/react": "*", 5515 + "@types/react-dom": "*", 5516 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5517 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5518 + }, 5519 + "peerDependenciesMeta": { 5520 + "@types/react": { 5521 + "optional": true 5522 + }, 5523 + "@types/react-dom": { 5524 + "optional": true 5525 + } 5526 + } 5527 + }, 5528 + "node_modules/radix-ui/node_modules/@radix-ui/react-menubar": { 5529 + "version": "1.1.16", 5530 + "resolved": "https://registry.npmjs.org/@radix-ui/react-menubar/-/react-menubar-1.1.16.tgz", 5531 + "integrity": "sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA==", 5532 + "dependencies": { 5533 + "@radix-ui/primitive": "1.1.3", 5534 + "@radix-ui/react-collection": "1.1.7", 5535 + "@radix-ui/react-compose-refs": "1.1.2", 5536 + "@radix-ui/react-context": "1.1.2", 5537 + "@radix-ui/react-direction": "1.1.1", 5538 + "@radix-ui/react-id": "1.1.1", 5539 + "@radix-ui/react-menu": "2.1.16", 5540 + "@radix-ui/react-primitive": "2.1.3", 5541 + "@radix-ui/react-roving-focus": "1.1.11", 5542 + "@radix-ui/react-use-controllable-state": "1.2.2" 5543 + }, 5544 + "peerDependencies": { 5545 + "@types/react": "*", 5546 + "@types/react-dom": "*", 5547 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5548 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5549 + }, 5550 + "peerDependenciesMeta": { 5551 + "@types/react": { 5552 + "optional": true 5553 + }, 5554 + "@types/react-dom": { 5555 + "optional": true 5556 + } 5557 + } 5558 + }, 5559 + "node_modules/radix-ui/node_modules/@radix-ui/react-navigation-menu": { 5560 + "version": "1.2.14", 5561 + "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.14.tgz", 5562 + "integrity": "sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==", 5563 + "dependencies": { 5564 + "@radix-ui/primitive": "1.1.3", 5565 + "@radix-ui/react-collection": "1.1.7", 5566 + "@radix-ui/react-compose-refs": "1.1.2", 5567 + "@radix-ui/react-context": "1.1.2", 5568 + "@radix-ui/react-direction": "1.1.1", 5569 + "@radix-ui/react-dismissable-layer": "1.1.11", 5570 + "@radix-ui/react-id": "1.1.1", 5571 + "@radix-ui/react-presence": "1.1.5", 5572 + "@radix-ui/react-primitive": "2.1.3", 5573 + "@radix-ui/react-use-callback-ref": "1.1.1", 5574 + "@radix-ui/react-use-controllable-state": "1.2.2", 5575 + "@radix-ui/react-use-layout-effect": "1.1.1", 5576 + "@radix-ui/react-use-previous": "1.1.1", 5577 + "@radix-ui/react-visually-hidden": "1.2.3" 5578 + }, 5579 + "peerDependencies": { 5580 + "@types/react": "*", 5581 + "@types/react-dom": "*", 5582 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5583 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5584 + }, 5585 + "peerDependenciesMeta": { 5586 + "@types/react": { 5587 + "optional": true 5588 + }, 5589 + "@types/react-dom": { 5590 + "optional": true 5591 + } 5592 + } 5593 + }, 5594 + "node_modules/radix-ui/node_modules/@radix-ui/react-one-time-password-field": { 5595 + "version": "0.1.8", 5596 + "resolved": "https://registry.npmjs.org/@radix-ui/react-one-time-password-field/-/react-one-time-password-field-0.1.8.tgz", 5597 + "integrity": "sha512-ycS4rbwURavDPVjCb5iS3aG4lURFDILi6sKI/WITUMZ13gMmn/xGjpLoqBAalhJaDk8I3UbCM5GzKHrnzwHbvg==", 5598 + "dependencies": { 5599 + "@radix-ui/number": "1.1.1", 5600 + "@radix-ui/primitive": "1.1.3", 5601 + "@radix-ui/react-collection": "1.1.7", 5602 + "@radix-ui/react-compose-refs": "1.1.2", 5603 + "@radix-ui/react-context": "1.1.2", 5604 + "@radix-ui/react-direction": "1.1.1", 5605 + "@radix-ui/react-primitive": "2.1.3", 5606 + "@radix-ui/react-roving-focus": "1.1.11", 5607 + "@radix-ui/react-use-controllable-state": "1.2.2", 5608 + "@radix-ui/react-use-effect-event": "0.0.2", 5609 + "@radix-ui/react-use-is-hydrated": "0.1.0", 5610 + "@radix-ui/react-use-layout-effect": "1.1.1" 5611 + }, 5612 + "peerDependencies": { 5613 + "@types/react": "*", 5614 + "@types/react-dom": "*", 5615 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5616 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5617 + }, 5618 + "peerDependenciesMeta": { 5619 + "@types/react": { 5620 + "optional": true 5621 + }, 5622 + "@types/react-dom": { 5623 + "optional": true 5624 + } 5625 + } 5626 + }, 5627 + "node_modules/radix-ui/node_modules/@radix-ui/react-password-toggle-field": { 5628 + "version": "0.1.3", 5629 + "resolved": "https://registry.npmjs.org/@radix-ui/react-password-toggle-field/-/react-password-toggle-field-0.1.3.tgz", 5630 + "integrity": "sha512-/UuCrDBWravcaMix4TdT+qlNdVwOM1Nck9kWx/vafXsdfj1ChfhOdfi3cy9SGBpWgTXwYCuboT/oYpJy3clqfw==", 5631 + "dependencies": { 5632 + "@radix-ui/primitive": "1.1.3", 5633 + "@radix-ui/react-compose-refs": "1.1.2", 5634 + "@radix-ui/react-context": "1.1.2", 5635 + "@radix-ui/react-id": "1.1.1", 5636 + "@radix-ui/react-primitive": "2.1.3", 5637 + "@radix-ui/react-use-controllable-state": "1.2.2", 5638 + "@radix-ui/react-use-effect-event": "0.0.2", 5639 + "@radix-ui/react-use-is-hydrated": "0.1.0" 5640 + }, 5641 + "peerDependencies": { 5642 + "@types/react": "*", 5643 + "@types/react-dom": "*", 5644 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5645 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5646 + }, 5647 + "peerDependenciesMeta": { 5648 + "@types/react": { 5649 + "optional": true 5650 + }, 5651 + "@types/react-dom": { 5652 + "optional": true 5653 + } 5654 + } 5655 + }, 5656 + "node_modules/radix-ui/node_modules/@radix-ui/react-popover": { 5657 + "version": "1.1.15", 5658 + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz", 5659 + "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==", 5660 + "dependencies": { 5661 + "@radix-ui/primitive": "1.1.3", 5662 + "@radix-ui/react-compose-refs": "1.1.2", 5663 + "@radix-ui/react-context": "1.1.2", 5664 + "@radix-ui/react-dismissable-layer": "1.1.11", 5665 + "@radix-ui/react-focus-guards": "1.1.3", 5666 + "@radix-ui/react-focus-scope": "1.1.7", 5667 + "@radix-ui/react-id": "1.1.1", 5668 + "@radix-ui/react-popper": "1.2.8", 5669 + "@radix-ui/react-portal": "1.1.9", 5670 + "@radix-ui/react-presence": "1.1.5", 5671 + "@radix-ui/react-primitive": "2.1.3", 5672 + "@radix-ui/react-slot": "1.2.3", 5673 + "@radix-ui/react-use-controllable-state": "1.2.2", 5674 + "aria-hidden": "^1.2.4", 5675 + "react-remove-scroll": "^2.6.3" 5676 + }, 5677 + "peerDependencies": { 5678 + "@types/react": "*", 5679 + "@types/react-dom": "*", 5680 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5681 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5682 + }, 5683 + "peerDependenciesMeta": { 5684 + "@types/react": { 5685 + "optional": true 5686 + }, 5687 + "@types/react-dom": { 5688 + "optional": true 5689 + } 5690 + } 5691 + }, 5692 + "node_modules/radix-ui/node_modules/@radix-ui/react-popper": { 5693 + "version": "1.2.8", 5694 + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", 5695 + "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", 5696 + "dependencies": { 5697 + "@floating-ui/react-dom": "^2.0.0", 5698 + "@radix-ui/react-arrow": "1.1.7", 5699 + "@radix-ui/react-compose-refs": "1.1.2", 5700 + "@radix-ui/react-context": "1.1.2", 5701 + "@radix-ui/react-primitive": "2.1.3", 5702 + "@radix-ui/react-use-callback-ref": "1.1.1", 5703 + "@radix-ui/react-use-layout-effect": "1.1.1", 5704 + "@radix-ui/react-use-rect": "1.1.1", 5705 + "@radix-ui/react-use-size": "1.1.1", 5706 + "@radix-ui/rect": "1.1.1" 5707 + }, 5708 + "peerDependencies": { 5709 + "@types/react": "*", 5710 + "@types/react-dom": "*", 5711 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5712 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5713 + }, 5714 + "peerDependenciesMeta": { 5715 + "@types/react": { 5716 + "optional": true 5717 + }, 5718 + "@types/react-dom": { 5719 + "optional": true 5720 + } 5721 + } 5722 + }, 5723 + "node_modules/radix-ui/node_modules/@radix-ui/react-portal": { 5724 + "version": "1.1.9", 5725 + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", 5726 + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", 5727 + "dependencies": { 5728 + "@radix-ui/react-primitive": "2.1.3", 5729 + "@radix-ui/react-use-layout-effect": "1.1.1" 5730 + }, 5731 + "peerDependencies": { 5732 + "@types/react": "*", 5733 + "@types/react-dom": "*", 5734 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5735 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5736 + }, 5737 + "peerDependenciesMeta": { 5738 + "@types/react": { 5739 + "optional": true 5740 + }, 5741 + "@types/react-dom": { 5742 + "optional": true 5743 + } 5744 + } 5745 + }, 5746 + "node_modules/radix-ui/node_modules/@radix-ui/react-presence": { 5747 + "version": "1.1.5", 5748 + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", 5749 + "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", 5750 + "dependencies": { 5751 + "@radix-ui/react-compose-refs": "1.1.2", 5752 + "@radix-ui/react-use-layout-effect": "1.1.1" 5753 + }, 5754 + "peerDependencies": { 5755 + "@types/react": "*", 5756 + "@types/react-dom": "*", 5757 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5758 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5759 + }, 5760 + "peerDependenciesMeta": { 5761 + "@types/react": { 5762 + "optional": true 5763 + }, 5764 + "@types/react-dom": { 5765 + "optional": true 5766 + } 5767 + } 5768 + }, 5769 + "node_modules/radix-ui/node_modules/@radix-ui/react-primitive": { 5770 + "version": "2.1.3", 5771 + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", 5772 + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", 5773 + "dependencies": { 5774 + "@radix-ui/react-slot": "1.2.3" 5775 + }, 5776 + "peerDependencies": { 5777 + "@types/react": "*", 5778 + "@types/react-dom": "*", 5779 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5780 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5781 + }, 5782 + "peerDependenciesMeta": { 5783 + "@types/react": { 5784 + "optional": true 5785 + }, 5786 + "@types/react-dom": { 5787 + "optional": true 5788 + } 5789 + } 5790 + }, 5791 + "node_modules/radix-ui/node_modules/@radix-ui/react-progress": { 5792 + "version": "1.1.7", 5793 + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.7.tgz", 5794 + "integrity": "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==", 5795 + "dependencies": { 5796 + "@radix-ui/react-context": "1.1.2", 5797 + "@radix-ui/react-primitive": "2.1.3" 5798 + }, 5799 + "peerDependencies": { 5800 + "@types/react": "*", 5801 + "@types/react-dom": "*", 5802 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5803 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5804 + }, 5805 + "peerDependenciesMeta": { 5806 + "@types/react": { 5807 + "optional": true 5808 + }, 5809 + "@types/react-dom": { 5810 + "optional": true 5811 + } 5812 + } 5813 + }, 5814 + "node_modules/radix-ui/node_modules/@radix-ui/react-radio-group": { 5815 + "version": "1.3.8", 5816 + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz", 5817 + "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==", 5818 + "dependencies": { 5819 + "@radix-ui/primitive": "1.1.3", 5820 + "@radix-ui/react-compose-refs": "1.1.2", 5821 + "@radix-ui/react-context": "1.1.2", 5822 + "@radix-ui/react-direction": "1.1.1", 5823 + "@radix-ui/react-presence": "1.1.5", 5824 + "@radix-ui/react-primitive": "2.1.3", 5825 + "@radix-ui/react-roving-focus": "1.1.11", 5826 + "@radix-ui/react-use-controllable-state": "1.2.2", 5827 + "@radix-ui/react-use-previous": "1.1.1", 5828 + "@radix-ui/react-use-size": "1.1.1" 5829 + }, 5830 + "peerDependencies": { 5831 + "@types/react": "*", 5832 + "@types/react-dom": "*", 5833 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5834 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5835 + }, 5836 + "peerDependenciesMeta": { 5837 + "@types/react": { 5838 + "optional": true 5839 + }, 5840 + "@types/react-dom": { 5841 + "optional": true 5842 + } 5843 + } 5844 + }, 5845 + "node_modules/radix-ui/node_modules/@radix-ui/react-roving-focus": { 5846 + "version": "1.1.11", 5847 + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", 5848 + "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", 5849 + "dependencies": { 5850 + "@radix-ui/primitive": "1.1.3", 5851 + "@radix-ui/react-collection": "1.1.7", 5852 + "@radix-ui/react-compose-refs": "1.1.2", 5853 + "@radix-ui/react-context": "1.1.2", 5854 + "@radix-ui/react-direction": "1.1.1", 5855 + "@radix-ui/react-id": "1.1.1", 5856 + "@radix-ui/react-primitive": "2.1.3", 5857 + "@radix-ui/react-use-callback-ref": "1.1.1", 5858 + "@radix-ui/react-use-controllable-state": "1.2.2" 5859 + }, 5860 + "peerDependencies": { 5861 + "@types/react": "*", 5862 + "@types/react-dom": "*", 5863 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5864 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5865 + }, 5866 + "peerDependenciesMeta": { 5867 + "@types/react": { 5868 + "optional": true 5869 + }, 5870 + "@types/react-dom": { 5871 + "optional": true 5872 + } 5873 + } 5874 + }, 5875 + "node_modules/radix-ui/node_modules/@radix-ui/react-scroll-area": { 5876 + "version": "1.2.10", 5877 + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz", 5878 + "integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==", 5879 + "dependencies": { 5880 + "@radix-ui/number": "1.1.1", 5881 + "@radix-ui/primitive": "1.1.3", 5882 + "@radix-ui/react-compose-refs": "1.1.2", 5883 + "@radix-ui/react-context": "1.1.2", 5884 + "@radix-ui/react-direction": "1.1.1", 5885 + "@radix-ui/react-presence": "1.1.5", 5886 + "@radix-ui/react-primitive": "2.1.3", 5887 + "@radix-ui/react-use-callback-ref": "1.1.1", 5888 + "@radix-ui/react-use-layout-effect": "1.1.1" 5889 + }, 5890 + "peerDependencies": { 5891 + "@types/react": "*", 5892 + "@types/react-dom": "*", 5893 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5894 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5895 + }, 5896 + "peerDependenciesMeta": { 5897 + "@types/react": { 5898 + "optional": true 5899 + }, 5900 + "@types/react-dom": { 5901 + "optional": true 5902 + } 5903 + } 5904 + }, 5905 + "node_modules/radix-ui/node_modules/@radix-ui/react-select": { 5906 + "version": "2.2.6", 5907 + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz", 5908 + "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==", 5909 + "dependencies": { 5910 + "@radix-ui/number": "1.1.1", 5911 + "@radix-ui/primitive": "1.1.3", 5912 + "@radix-ui/react-collection": "1.1.7", 5913 + "@radix-ui/react-compose-refs": "1.1.2", 5914 + "@radix-ui/react-context": "1.1.2", 5915 + "@radix-ui/react-direction": "1.1.1", 5916 + "@radix-ui/react-dismissable-layer": "1.1.11", 5917 + "@radix-ui/react-focus-guards": "1.1.3", 5918 + "@radix-ui/react-focus-scope": "1.1.7", 5919 + "@radix-ui/react-id": "1.1.1", 5920 + "@radix-ui/react-popper": "1.2.8", 5921 + "@radix-ui/react-portal": "1.1.9", 5922 + "@radix-ui/react-primitive": "2.1.3", 5923 + "@radix-ui/react-slot": "1.2.3", 5924 + "@radix-ui/react-use-callback-ref": "1.1.1", 5925 + "@radix-ui/react-use-controllable-state": "1.2.2", 5926 + "@radix-ui/react-use-layout-effect": "1.1.1", 5927 + "@radix-ui/react-use-previous": "1.1.1", 5928 + "@radix-ui/react-visually-hidden": "1.2.3", 5929 + "aria-hidden": "^1.2.4", 5930 + "react-remove-scroll": "^2.6.3" 5931 + }, 5932 + "peerDependencies": { 5933 + "@types/react": "*", 5934 + "@types/react-dom": "*", 5935 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5936 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5937 + }, 5938 + "peerDependenciesMeta": { 5939 + "@types/react": { 5940 + "optional": true 5941 + }, 5942 + "@types/react-dom": { 5943 + "optional": true 5944 + } 5945 + } 5946 + }, 5947 + "node_modules/radix-ui/node_modules/@radix-ui/react-separator": { 5948 + "version": "1.1.7", 5949 + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz", 5950 + "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", 5951 + "dependencies": { 5952 + "@radix-ui/react-primitive": "2.1.3" 5953 + }, 5954 + "peerDependencies": { 5955 + "@types/react": "*", 5956 + "@types/react-dom": "*", 5957 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5958 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5959 + }, 5960 + "peerDependenciesMeta": { 5961 + "@types/react": { 5962 + "optional": true 5963 + }, 5964 + "@types/react-dom": { 5965 + "optional": true 5966 + } 5967 + } 5968 + }, 5969 + "node_modules/radix-ui/node_modules/@radix-ui/react-slider": { 5970 + "version": "1.3.6", 5971 + "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.6.tgz", 5972 + "integrity": "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==", 5973 + "dependencies": { 5974 + "@radix-ui/number": "1.1.1", 5975 + "@radix-ui/primitive": "1.1.3", 5976 + "@radix-ui/react-collection": "1.1.7", 5977 + "@radix-ui/react-compose-refs": "1.1.2", 5978 + "@radix-ui/react-context": "1.1.2", 5979 + "@radix-ui/react-direction": "1.1.1", 5980 + "@radix-ui/react-primitive": "2.1.3", 5981 + "@radix-ui/react-use-controllable-state": "1.2.2", 5982 + "@radix-ui/react-use-layout-effect": "1.1.1", 5983 + "@radix-ui/react-use-previous": "1.1.1", 5984 + "@radix-ui/react-use-size": "1.1.1" 5985 + }, 5986 + "peerDependencies": { 5987 + "@types/react": "*", 5988 + "@types/react-dom": "*", 5989 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 5990 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 5991 + }, 5992 + "peerDependenciesMeta": { 5993 + "@types/react": { 5994 + "optional": true 5995 + }, 5996 + "@types/react-dom": { 5997 + "optional": true 5998 + } 5999 + } 6000 + }, 6001 + "node_modules/radix-ui/node_modules/@radix-ui/react-slot": { 6002 + "version": "1.2.3", 6003 + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", 6004 + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", 6005 + "dependencies": { 6006 + "@radix-ui/react-compose-refs": "1.1.2" 6007 + }, 6008 + "peerDependencies": { 6009 + "@types/react": "*", 6010 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 6011 + }, 6012 + "peerDependenciesMeta": { 6013 + "@types/react": { 6014 + "optional": true 6015 + } 6016 + } 6017 + }, 6018 + "node_modules/radix-ui/node_modules/@radix-ui/react-switch": { 6019 + "version": "1.2.6", 6020 + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz", 6021 + "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==", 6022 + "dependencies": { 6023 + "@radix-ui/primitive": "1.1.3", 6024 + "@radix-ui/react-compose-refs": "1.1.2", 6025 + "@radix-ui/react-context": "1.1.2", 6026 + "@radix-ui/react-primitive": "2.1.3", 6027 + "@radix-ui/react-use-controllable-state": "1.2.2", 6028 + "@radix-ui/react-use-previous": "1.1.1", 6029 + "@radix-ui/react-use-size": "1.1.1" 6030 + }, 6031 + "peerDependencies": { 6032 + "@types/react": "*", 6033 + "@types/react-dom": "*", 6034 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 6035 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 6036 + }, 6037 + "peerDependenciesMeta": { 6038 + "@types/react": { 6039 + "optional": true 6040 + }, 6041 + "@types/react-dom": { 6042 + "optional": true 6043 + } 6044 + } 6045 + }, 6046 + "node_modules/radix-ui/node_modules/@radix-ui/react-tabs": { 6047 + "version": "1.1.13", 6048 + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz", 6049 + "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==", 6050 + "dependencies": { 6051 + "@radix-ui/primitive": "1.1.3", 6052 + "@radix-ui/react-context": "1.1.2", 6053 + "@radix-ui/react-direction": "1.1.1", 6054 + "@radix-ui/react-id": "1.1.1", 6055 + "@radix-ui/react-presence": "1.1.5", 6056 + "@radix-ui/react-primitive": "2.1.3", 6057 + "@radix-ui/react-roving-focus": "1.1.11", 6058 + "@radix-ui/react-use-controllable-state": "1.2.2" 6059 + }, 6060 + "peerDependencies": { 6061 + "@types/react": "*", 6062 + "@types/react-dom": "*", 6063 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 6064 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 6065 + }, 6066 + "peerDependenciesMeta": { 6067 + "@types/react": { 6068 + "optional": true 6069 + }, 6070 + "@types/react-dom": { 6071 + "optional": true 6072 + } 6073 + } 6074 + }, 6075 + "node_modules/radix-ui/node_modules/@radix-ui/react-toast": { 6076 + "version": "1.2.15", 6077 + "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.15.tgz", 6078 + "integrity": "sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==", 6079 + "dependencies": { 6080 + "@radix-ui/primitive": "1.1.3", 6081 + "@radix-ui/react-collection": "1.1.7", 6082 + "@radix-ui/react-compose-refs": "1.1.2", 6083 + "@radix-ui/react-context": "1.1.2", 6084 + "@radix-ui/react-dismissable-layer": "1.1.11", 6085 + "@radix-ui/react-portal": "1.1.9", 6086 + "@radix-ui/react-presence": "1.1.5", 6087 + "@radix-ui/react-primitive": "2.1.3", 6088 + "@radix-ui/react-use-callback-ref": "1.1.1", 6089 + "@radix-ui/react-use-controllable-state": "1.2.2", 6090 + "@radix-ui/react-use-layout-effect": "1.1.1", 6091 + "@radix-ui/react-visually-hidden": "1.2.3" 6092 + }, 6093 + "peerDependencies": { 6094 + "@types/react": "*", 6095 + "@types/react-dom": "*", 6096 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 6097 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 6098 + }, 6099 + "peerDependenciesMeta": { 6100 + "@types/react": { 6101 + "optional": true 6102 + }, 6103 + "@types/react-dom": { 6104 + "optional": true 6105 + } 6106 + } 6107 + }, 6108 + "node_modules/radix-ui/node_modules/@radix-ui/react-toggle": { 6109 + "version": "1.1.10", 6110 + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.1.10.tgz", 6111 + "integrity": "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==", 6112 + "dependencies": { 6113 + "@radix-ui/primitive": "1.1.3", 6114 + "@radix-ui/react-primitive": "2.1.3", 6115 + "@radix-ui/react-use-controllable-state": "1.2.2" 6116 + }, 6117 + "peerDependencies": { 6118 + "@types/react": "*", 6119 + "@types/react-dom": "*", 6120 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 6121 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 6122 + }, 6123 + "peerDependenciesMeta": { 6124 + "@types/react": { 6125 + "optional": true 6126 + }, 6127 + "@types/react-dom": { 6128 + "optional": true 6129 + } 6130 + } 6131 + }, 6132 + "node_modules/radix-ui/node_modules/@radix-ui/react-toggle-group": { 6133 + "version": "1.1.11", 6134 + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.1.11.tgz", 6135 + "integrity": "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==", 6136 + "dependencies": { 6137 + "@radix-ui/primitive": "1.1.3", 6138 + "@radix-ui/react-context": "1.1.2", 6139 + "@radix-ui/react-direction": "1.1.1", 6140 + "@radix-ui/react-primitive": "2.1.3", 6141 + "@radix-ui/react-roving-focus": "1.1.11", 6142 + "@radix-ui/react-toggle": "1.1.10", 6143 + "@radix-ui/react-use-controllable-state": "1.2.2" 6144 + }, 6145 + "peerDependencies": { 6146 + "@types/react": "*", 6147 + "@types/react-dom": "*", 6148 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 6149 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 6150 + }, 6151 + "peerDependenciesMeta": { 6152 + "@types/react": { 6153 + "optional": true 6154 + }, 6155 + "@types/react-dom": { 6156 + "optional": true 6157 + } 6158 + } 6159 + }, 6160 + "node_modules/radix-ui/node_modules/@radix-ui/react-toolbar": { 6161 + "version": "1.1.11", 6162 + "resolved": "https://registry.npmjs.org/@radix-ui/react-toolbar/-/react-toolbar-1.1.11.tgz", 6163 + "integrity": "sha512-4ol06/1bLoFu1nwUqzdD4Y5RZ9oDdKeiHIsntug54Hcr1pgaHiPqHFEaXI1IFP/EsOfROQZ8Mig9VTIRza6Tjg==", 6164 + "dependencies": { 6165 + "@radix-ui/primitive": "1.1.3", 6166 + "@radix-ui/react-context": "1.1.2", 6167 + "@radix-ui/react-direction": "1.1.1", 6168 + "@radix-ui/react-primitive": "2.1.3", 6169 + "@radix-ui/react-roving-focus": "1.1.11", 6170 + "@radix-ui/react-separator": "1.1.7", 6171 + "@radix-ui/react-toggle-group": "1.1.11" 6172 + }, 6173 + "peerDependencies": { 6174 + "@types/react": "*", 6175 + "@types/react-dom": "*", 6176 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 6177 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 6178 + }, 6179 + "peerDependenciesMeta": { 6180 + "@types/react": { 6181 + "optional": true 6182 + }, 6183 + "@types/react-dom": { 6184 + "optional": true 6185 + } 6186 + } 6187 + }, 6188 + "node_modules/radix-ui/node_modules/@radix-ui/react-tooltip": { 6189 + "version": "1.2.8", 6190 + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz", 6191 + "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==", 6192 + "dependencies": { 6193 + "@radix-ui/primitive": "1.1.3", 6194 + "@radix-ui/react-compose-refs": "1.1.2", 6195 + "@radix-ui/react-context": "1.1.2", 6196 + "@radix-ui/react-dismissable-layer": "1.1.11", 6197 + "@radix-ui/react-id": "1.1.1", 6198 + "@radix-ui/react-popper": "1.2.8", 6199 + "@radix-ui/react-portal": "1.1.9", 6200 + "@radix-ui/react-presence": "1.1.5", 6201 + "@radix-ui/react-primitive": "2.1.3", 6202 + "@radix-ui/react-slot": "1.2.3", 6203 + "@radix-ui/react-use-controllable-state": "1.2.2", 6204 + "@radix-ui/react-visually-hidden": "1.2.3" 6205 + }, 6206 + "peerDependencies": { 6207 + "@types/react": "*", 6208 + "@types/react-dom": "*", 6209 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 6210 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 6211 + }, 6212 + "peerDependenciesMeta": { 6213 + "@types/react": { 6214 + "optional": true 6215 + }, 6216 + "@types/react-dom": { 6217 + "optional": true 6218 + } 6219 + } 6220 + }, 6221 + "node_modules/radix-ui/node_modules/@radix-ui/react-visually-hidden": { 6222 + "version": "1.2.3", 6223 + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", 6224 + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", 6225 + "dependencies": { 6226 + "@radix-ui/react-primitive": "2.1.3" 6227 + }, 6228 + "peerDependencies": { 6229 + "@types/react": "*", 6230 + "@types/react-dom": "*", 6231 + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 6232 + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 6233 + }, 6234 + "peerDependenciesMeta": { 6235 + "@types/react": { 6236 + "optional": true 6237 + }, 6238 + "@types/react-dom": { 6239 + "optional": true 6240 + } 6241 + } 6242 + }, 6243 + "node_modules/range-parser": { 6244 + "version": "1.2.1", 6245 + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 6246 + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 6247 + "engines": { 6248 + "node": ">= 0.6" 6249 + } 6250 + }, 6251 + "node_modules/raw-body": { 6252 + "version": "3.0.2", 6253 + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", 6254 + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", 6255 + "dependencies": { 6256 + "bytes": "~3.1.2", 6257 + "http-errors": "~2.0.1", 6258 + "iconv-lite": "~0.7.0", 6259 + "unpipe": "~1.0.0" 6260 + }, 6261 + "engines": { 6262 + "node": ">= 0.10" 6263 + } 6264 + }, 1841 6265 "node_modules/react": { 1842 6266 "version": "18.2.0", 1843 6267 "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", 1844 6268 "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", 1845 - "license": "MIT", 1846 6269 "dependencies": { 1847 6270 "loose-envify": "^1.1.0" 1848 6271 }, ··· 1854 6277 "version": "18.2.0", 1855 6278 "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", 1856 6279 "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", 1857 - "license": "MIT", 1858 6280 "dependencies": { 1859 6281 "loose-envify": "^1.1.0", 1860 6282 "scheduler": "^0.23.0" ··· 1863 6285 "react": "^18.2.0" 1864 6286 } 1865 6287 }, 1866 - "node_modules/react-is": { 1867 - "version": "16.13.1", 1868 - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", 1869 - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", 1870 - "license": "MIT" 6288 + "node_modules/react-remove-scroll": { 6289 + "version": "2.7.2", 6290 + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", 6291 + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", 6292 + "dependencies": { 6293 + "react-remove-scroll-bar": "^2.3.7", 6294 + "react-style-singleton": "^2.2.3", 6295 + "tslib": "^2.1.0", 6296 + "use-callback-ref": "^1.3.3", 6297 + "use-sidecar": "^1.1.3" 6298 + }, 6299 + "engines": { 6300 + "node": ">=10" 6301 + }, 6302 + "peerDependencies": { 6303 + "@types/react": "*", 6304 + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" 6305 + }, 6306 + "peerDependenciesMeta": { 6307 + "@types/react": { 6308 + "optional": true 6309 + } 6310 + } 6311 + }, 6312 + "node_modules/react-remove-scroll-bar": { 6313 + "version": "2.3.8", 6314 + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", 6315 + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", 6316 + "dependencies": { 6317 + "react-style-singleton": "^2.2.2", 6318 + "tslib": "^2.0.0" 6319 + }, 6320 + "engines": { 6321 + "node": ">=10" 6322 + }, 6323 + "peerDependencies": { 6324 + "@types/react": "*", 6325 + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 6326 + }, 6327 + "peerDependenciesMeta": { 6328 + "@types/react": { 6329 + "optional": true 6330 + } 6331 + } 6332 + }, 6333 + "node_modules/react-style-singleton": { 6334 + "version": "2.2.3", 6335 + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", 6336 + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", 6337 + "dependencies": { 6338 + "get-nonce": "^1.0.0", 6339 + "tslib": "^2.0.0" 6340 + }, 6341 + "engines": { 6342 + "node": ">=10" 6343 + }, 6344 + "peerDependencies": { 6345 + "@types/react": "*", 6346 + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" 6347 + }, 6348 + "peerDependenciesMeta": { 6349 + "@types/react": { 6350 + "optional": true 6351 + } 6352 + } 6353 + }, 6354 + "node_modules/recast": { 6355 + "version": "0.23.11", 6356 + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", 6357 + "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", 6358 + "dependencies": { 6359 + "ast-types": "^0.16.1", 6360 + "esprima": "~4.0.0", 6361 + "source-map": "~0.6.1", 6362 + "tiny-invariant": "^1.3.3", 6363 + "tslib": "^2.0.1" 6364 + }, 6365 + "engines": { 6366 + "node": ">= 4" 6367 + } 6368 + }, 6369 + "node_modules/require-directory": { 6370 + "version": "2.1.1", 6371 + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 6372 + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", 6373 + "engines": { 6374 + "node": ">=0.10.0" 6375 + } 6376 + }, 6377 + "node_modules/require-from-string": { 6378 + "version": "2.0.2", 6379 + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", 6380 + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", 6381 + "engines": { 6382 + "node": ">=0.10.0" 6383 + } 6384 + }, 6385 + "node_modules/reselect": { 6386 + "version": "5.1.1", 6387 + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", 6388 + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==" 6389 + }, 6390 + "node_modules/resolve-from": { 6391 + "version": "4.0.0", 6392 + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 6393 + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 6394 + "engines": { 6395 + "node": ">=4" 6396 + } 6397 + }, 6398 + "node_modules/restore-cursor": { 6399 + "version": "5.1.0", 6400 + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", 6401 + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", 6402 + "dependencies": { 6403 + "onetime": "^7.0.0", 6404 + "signal-exit": "^4.1.0" 6405 + }, 6406 + "engines": { 6407 + "node": ">=18" 6408 + }, 6409 + "funding": { 6410 + "url": "https://github.com/sponsors/sindresorhus" 6411 + } 6412 + }, 6413 + "node_modules/rettime": { 6414 + "version": "0.10.1", 6415 + "resolved": "https://registry.npmjs.org/rettime/-/rettime-0.10.1.tgz", 6416 + "integrity": "sha512-uyDrIlUEH37cinabq0AX4QbgV4HbFZ/gqoiunWQ1UqBtRvTTytwhNYjE++pO/MjPTZL5KQCf2bEoJ/BJNVQ5Kw==" 6417 + }, 6418 + "node_modules/reusify": { 6419 + "version": "1.1.0", 6420 + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", 6421 + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", 6422 + "engines": { 6423 + "iojs": ">=1.0.0", 6424 + "node": ">=0.10.0" 6425 + } 6426 + }, 6427 + "node_modules/router": { 6428 + "version": "2.2.0", 6429 + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", 6430 + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", 6431 + "dependencies": { 6432 + "debug": "^4.4.0", 6433 + "depd": "^2.0.0", 6434 + "is-promise": "^4.0.0", 6435 + "parseurl": "^1.3.3", 6436 + "path-to-regexp": "^8.0.0" 6437 + }, 6438 + "engines": { 6439 + "node": ">= 18" 6440 + } 6441 + }, 6442 + "node_modules/router/node_modules/path-to-regexp": { 6443 + "version": "8.3.0", 6444 + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", 6445 + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", 6446 + "funding": { 6447 + "type": "opencollective", 6448 + "url": "https://opencollective.com/express" 6449 + } 6450 + }, 6451 + "node_modules/run-applescript": { 6452 + "version": "7.1.0", 6453 + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", 6454 + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", 6455 + "engines": { 6456 + "node": ">=18" 6457 + }, 6458 + "funding": { 6459 + "url": "https://github.com/sponsors/sindresorhus" 6460 + } 6461 + }, 6462 + "node_modules/run-parallel": { 6463 + "version": "1.2.0", 6464 + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 6465 + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 6466 + "funding": [ 6467 + { 6468 + "type": "github", 6469 + "url": "https://github.com/sponsors/feross" 6470 + }, 6471 + { 6472 + "type": "patreon", 6473 + "url": "https://www.patreon.com/feross" 6474 + }, 6475 + { 6476 + "type": "consulting", 6477 + "url": "https://feross.org/support" 6478 + } 6479 + ], 6480 + "dependencies": { 6481 + "queue-microtask": "^1.2.2" 6482 + } 6483 + }, 6484 + "node_modules/safer-buffer": { 6485 + "version": "2.1.2", 6486 + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 6487 + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1871 6488 }, 1872 6489 "node_modules/scheduler": { 1873 6490 "version": "0.23.2", 1874 6491 "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", 1875 6492 "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", 1876 - "license": "MIT", 1877 6493 "dependencies": { 1878 6494 "loose-envify": "^1.1.0" 1879 6495 } 1880 6496 }, 1881 6497 "node_modules/semver": { 1882 - "version": "7.7.3", 1883 - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", 1884 - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", 1885 - "license": "ISC", 1886 - "optional": true, 6498 + "version": "6.3.1", 6499 + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", 6500 + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", 1887 6501 "bin": { 1888 6502 "semver": "bin/semver.js" 6503 + } 6504 + }, 6505 + "node_modules/send": { 6506 + "version": "1.2.1", 6507 + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", 6508 + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", 6509 + "dependencies": { 6510 + "debug": "^4.4.3", 6511 + "encodeurl": "^2.0.0", 6512 + "escape-html": "^1.0.3", 6513 + "etag": "^1.8.1", 6514 + "fresh": "^2.0.0", 6515 + "http-errors": "^2.0.1", 6516 + "mime-types": "^3.0.2", 6517 + "ms": "^2.1.3", 6518 + "on-finished": "^2.4.1", 6519 + "range-parser": "^1.2.1", 6520 + "statuses": "^2.0.2" 1889 6521 }, 1890 6522 "engines": { 1891 - "node": ">=10" 6523 + "node": ">= 18" 6524 + }, 6525 + "funding": { 6526 + "type": "opencollective", 6527 + "url": "https://opencollective.com/express" 6528 + } 6529 + }, 6530 + "node_modules/serve-static": { 6531 + "version": "2.2.1", 6532 + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", 6533 + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", 6534 + "dependencies": { 6535 + "encodeurl": "^2.0.0", 6536 + "escape-html": "^1.0.3", 6537 + "parseurl": "^1.3.3", 6538 + "send": "^1.2.0" 6539 + }, 6540 + "engines": { 6541 + "node": ">= 18" 6542 + }, 6543 + "funding": { 6544 + "type": "opencollective", 6545 + "url": "https://opencollective.com/express" 1892 6546 } 1893 6547 }, 1894 6548 "node_modules/server-only": { 1895 6549 "version": "0.0.1", 1896 6550 "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", 1897 - "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==", 1898 - "license": "MIT" 6551 + "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==" 6552 + }, 6553 + "node_modules/setprototypeof": { 6554 + "version": "1.2.0", 6555 + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 6556 + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 6557 + }, 6558 + "node_modules/shadcn": { 6559 + "version": "3.8.5", 6560 + "resolved": "https://registry.npmjs.org/shadcn/-/shadcn-3.8.5.tgz", 6561 + "integrity": "sha512-jPRx44e+eyeV7xwY3BLJXcfrks00+M0h5BGB9l6DdcBW4BpAj4x3lVmVy0TXPEs2iHEisxejr62sZAAw6B1EVA==", 6562 + "dependencies": { 6563 + "@antfu/ni": "^25.0.0", 6564 + "@babel/core": "^7.28.0", 6565 + "@babel/parser": "^7.28.0", 6566 + "@babel/plugin-transform-typescript": "^7.28.0", 6567 + "@babel/preset-typescript": "^7.27.1", 6568 + "@dotenvx/dotenvx": "^1.48.4", 6569 + "@modelcontextprotocol/sdk": "^1.26.0", 6570 + "@types/validate-npm-package-name": "^4.0.2", 6571 + "browserslist": "^4.26.2", 6572 + "commander": "^14.0.0", 6573 + "cosmiconfig": "^9.0.0", 6574 + "dedent": "^1.6.0", 6575 + "deepmerge": "^4.3.1", 6576 + "diff": "^8.0.2", 6577 + "execa": "^9.6.0", 6578 + "fast-glob": "^3.3.3", 6579 + "fs-extra": "^11.3.1", 6580 + "fuzzysort": "^3.1.0", 6581 + "https-proxy-agent": "^7.0.6", 6582 + "kleur": "^4.1.5", 6583 + "msw": "^2.10.4", 6584 + "node-fetch": "^3.3.2", 6585 + "open": "^11.0.0", 6586 + "ora": "^8.2.0", 6587 + "postcss": "^8.5.6", 6588 + "postcss-selector-parser": "^7.1.0", 6589 + "prompts": "^2.4.2", 6590 + "recast": "^0.23.11", 6591 + "stringify-object": "^5.0.0", 6592 + "tailwind-merge": "^3.0.1", 6593 + "ts-morph": "^26.0.0", 6594 + "tsconfig-paths": "^4.2.0", 6595 + "validate-npm-package-name": "^7.0.1", 6596 + "zod": "^3.24.1", 6597 + "zod-to-json-schema": "^3.24.6" 6598 + }, 6599 + "bin": { 6600 + "shadcn": "dist/index.js" 6601 + } 1899 6602 }, 1900 6603 "node_modules/sharp": { 1901 6604 "version": "0.34.5", 1902 6605 "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", 1903 6606 "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", 1904 6607 "hasInstallScript": true, 1905 - "license": "Apache-2.0", 1906 6608 "optional": true, 1907 6609 "dependencies": { 1908 6610 "@img/colour": "^1.0.0", ··· 1942 6644 "@img/sharp-win32-x64": "0.34.5" 1943 6645 } 1944 6646 }, 6647 + "node_modules/sharp/node_modules/semver": { 6648 + "version": "7.7.4", 6649 + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", 6650 + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", 6651 + "optional": true, 6652 + "bin": { 6653 + "semver": "bin/semver.js" 6654 + }, 6655 + "engines": { 6656 + "node": ">=10" 6657 + } 6658 + }, 6659 + "node_modules/shebang-command": { 6660 + "version": "2.0.0", 6661 + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 6662 + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 6663 + "dependencies": { 6664 + "shebang-regex": "^3.0.0" 6665 + }, 6666 + "engines": { 6667 + "node": ">=8" 6668 + } 6669 + }, 6670 + "node_modules/shebang-regex": { 6671 + "version": "3.0.0", 6672 + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 6673 + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 6674 + "engines": { 6675 + "node": ">=8" 6676 + } 6677 + }, 1945 6678 "node_modules/side-channel": { 1946 6679 "version": "1.1.0", 1947 6680 "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", 1948 6681 "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", 1949 - "license": "MIT", 1950 6682 "dependencies": { 1951 6683 "es-errors": "^1.3.0", 1952 6684 "object-inspect": "^1.13.3", ··· 1965 6697 "version": "1.0.0", 1966 6698 "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", 1967 6699 "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", 1968 - "license": "MIT", 1969 6700 "dependencies": { 1970 6701 "es-errors": "^1.3.0", 1971 6702 "object-inspect": "^1.13.3" ··· 1981 6712 "version": "1.0.1", 1982 6713 "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", 1983 6714 "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", 1984 - "license": "MIT", 1985 6715 "dependencies": { 1986 6716 "call-bound": "^1.0.2", 1987 6717 "es-errors": "^1.3.0", ··· 1999 6729 "version": "1.0.2", 2000 6730 "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", 2001 6731 "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", 2002 - "license": "MIT", 2003 6732 "dependencies": { 2004 6733 "call-bound": "^1.0.2", 2005 6734 "es-errors": "^1.3.0", ··· 2014 6743 "url": "https://github.com/sponsors/ljharb" 2015 6744 } 2016 6745 }, 6746 + "node_modules/signal-exit": { 6747 + "version": "4.1.0", 6748 + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", 6749 + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", 6750 + "engines": { 6751 + "node": ">=14" 6752 + }, 6753 + "funding": { 6754 + "url": "https://github.com/sponsors/isaacs" 6755 + } 6756 + }, 6757 + "node_modules/sisteransi": { 6758 + "version": "1.0.5", 6759 + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", 6760 + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" 6761 + }, 6762 + "node_modules/source-map": { 6763 + "version": "0.6.1", 6764 + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 6765 + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 6766 + "engines": { 6767 + "node": ">=0.10.0" 6768 + } 6769 + }, 2017 6770 "node_modules/source-map-js": { 2018 6771 "version": "1.2.1", 2019 6772 "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 2020 6773 "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 2021 - "license": "BSD-3-Clause", 2022 6774 "engines": { 2023 6775 "node": ">=0.10.0" 2024 6776 } 2025 6777 }, 6778 + "node_modules/statuses": { 6779 + "version": "2.0.2", 6780 + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", 6781 + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", 6782 + "engines": { 6783 + "node": ">= 0.8" 6784 + } 6785 + }, 6786 + "node_modules/stdin-discarder": { 6787 + "version": "0.2.2", 6788 + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", 6789 + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", 6790 + "engines": { 6791 + "node": ">=18" 6792 + }, 6793 + "funding": { 6794 + "url": "https://github.com/sponsors/sindresorhus" 6795 + } 6796 + }, 6797 + "node_modules/strict-event-emitter": { 6798 + "version": "0.5.1", 6799 + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", 6800 + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==" 6801 + }, 6802 + "node_modules/string-width": { 6803 + "version": "7.2.0", 6804 + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", 6805 + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", 6806 + "dependencies": { 6807 + "emoji-regex": "^10.3.0", 6808 + "get-east-asian-width": "^1.0.0", 6809 + "strip-ansi": "^7.1.0" 6810 + }, 6811 + "engines": { 6812 + "node": ">=18" 6813 + }, 6814 + "funding": { 6815 + "url": "https://github.com/sponsors/sindresorhus" 6816 + } 6817 + }, 6818 + "node_modules/stringify-object": { 6819 + "version": "5.0.0", 6820 + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-5.0.0.tgz", 6821 + "integrity": "sha512-zaJYxz2FtcMb4f+g60KsRNFOpVMUyuJgA51Zi5Z1DOTC3S59+OQiVOzE9GZt0x72uBGWKsQIuBKeF9iusmKFsg==", 6822 + "dependencies": { 6823 + "get-own-enumerable-keys": "^1.0.0", 6824 + "is-obj": "^3.0.0", 6825 + "is-regexp": "^3.1.0" 6826 + }, 6827 + "engines": { 6828 + "node": ">=14.16" 6829 + }, 6830 + "funding": { 6831 + "url": "https://github.com/yeoman/stringify-object?sponsor=1" 6832 + } 6833 + }, 6834 + "node_modules/strip-ansi": { 6835 + "version": "7.2.0", 6836 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", 6837 + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", 6838 + "dependencies": { 6839 + "ansi-regex": "^6.2.2" 6840 + }, 6841 + "engines": { 6842 + "node": ">=12" 6843 + }, 6844 + "funding": { 6845 + "url": "https://github.com/chalk/strip-ansi?sponsor=1" 6846 + } 6847 + }, 6848 + "node_modules/strip-bom": { 6849 + "version": "3.0.0", 6850 + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", 6851 + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", 6852 + "engines": { 6853 + "node": ">=4" 6854 + } 6855 + }, 6856 + "node_modules/strip-final-newline": { 6857 + "version": "4.0.0", 6858 + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", 6859 + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", 6860 + "engines": { 6861 + "node": ">=18" 6862 + }, 6863 + "funding": { 6864 + "url": "https://github.com/sponsors/sindresorhus" 6865 + } 6866 + }, 2026 6867 "node_modules/stripe": { 2027 6868 "version": "14.8.0", 2028 6869 "resolved": "https://registry.npmjs.org/stripe/-/stripe-14.8.0.tgz", 2029 6870 "integrity": "sha512-Qdecqk7lx095BE829NWxrG1+69NjPuHrpZqeR61i2KO00fpKkjMX9TYjwFU+WjQD6ZcNmCGOwNfnz5VnI5bjIg==", 2030 - "license": "MIT", 2031 6871 "dependencies": { 2032 6872 "@types/node": ">=8.1.0", 2033 6873 "qs": "^6.11.0" ··· 2040 6880 "version": "5.1.6", 2041 6881 "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", 2042 6882 "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", 2043 - "license": "MIT", 2044 6883 "dependencies": { 2045 6884 "client-only": "0.0.1" 2046 6885 }, ··· 2059 6898 } 2060 6899 } 2061 6900 }, 6901 + "node_modules/tabbable": { 6902 + "version": "6.4.0", 6903 + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", 6904 + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==" 6905 + }, 6906 + "node_modules/tagged-tag": { 6907 + "version": "1.0.0", 6908 + "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", 6909 + "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", 6910 + "engines": { 6911 + "node": ">=20" 6912 + }, 6913 + "funding": { 6914 + "url": "https://github.com/sponsors/sindresorhus" 6915 + } 6916 + }, 2062 6917 "node_modules/tailwind-merge": { 2063 - "version": "3.4.0", 2064 - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz", 2065 - "integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==", 2066 - "license": "MIT", 6918 + "version": "3.5.0", 6919 + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.5.0.tgz", 6920 + "integrity": "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==", 2067 6921 "funding": { 2068 6922 "type": "github", 2069 6923 "url": "https://github.com/sponsors/dcastil" 2070 6924 } 2071 6925 }, 2072 6926 "node_modules/tailwindcss": { 2073 - "version": "4.1.18", 2074 - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", 2075 - "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", 2076 - "license": "MIT" 6927 + "version": "4.2.1", 6928 + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz", 6929 + "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==" 2077 6930 }, 2078 6931 "node_modules/tapable": { 2079 6932 "version": "2.3.0", 2080 6933 "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", 2081 6934 "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", 2082 - "license": "MIT", 2083 6935 "engines": { 2084 6936 "node": ">=6" 2085 6937 }, ··· 2088 6940 "url": "https://opencollective.com/webpack" 2089 6941 } 2090 6942 }, 6943 + "node_modules/tiny-invariant": { 6944 + "version": "1.3.3", 6945 + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", 6946 + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" 6947 + }, 6948 + "node_modules/tinyexec": { 6949 + "version": "1.0.2", 6950 + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", 6951 + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", 6952 + "engines": { 6953 + "node": ">=18" 6954 + } 6955 + }, 6956 + "node_modules/tldts": { 6957 + "version": "7.0.25", 6958 + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.25.tgz", 6959 + "integrity": "sha512-keinCnPbwXEUG3ilrWQZU+CqcTTzHq9m2HhoUP2l7Xmi8l1LuijAXLpAJ5zRW+ifKTNscs4NdCkfkDCBYm352w==", 6960 + "dependencies": { 6961 + "tldts-core": "^7.0.25" 6962 + }, 6963 + "bin": { 6964 + "tldts": "bin/cli.js" 6965 + } 6966 + }, 6967 + "node_modules/tldts-core": { 6968 + "version": "7.0.25", 6969 + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.25.tgz", 6970 + "integrity": "sha512-ZjCZK0rppSBu7rjHYDYsEaMOIbbT+nWF57hKkv4IUmZWBNrBWBOjIElc0mKRgLM8bm7x/BBlof6t2gi/Oq/Asw==" 6971 + }, 6972 + "node_modules/to-regex-range": { 6973 + "version": "5.0.1", 6974 + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 6975 + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 6976 + "dependencies": { 6977 + "is-number": "^7.0.0" 6978 + }, 6979 + "engines": { 6980 + "node": ">=8.0" 6981 + } 6982 + }, 6983 + "node_modules/toidentifier": { 6984 + "version": "1.0.1", 6985 + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 6986 + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 6987 + "engines": { 6988 + "node": ">=0.6" 6989 + } 6990 + }, 6991 + "node_modules/tough-cookie": { 6992 + "version": "6.0.0", 6993 + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", 6994 + "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", 6995 + "dependencies": { 6996 + "tldts": "^7.0.5" 6997 + }, 6998 + "engines": { 6999 + "node": ">=16" 7000 + } 7001 + }, 7002 + "node_modules/ts-morph": { 7003 + "version": "26.0.0", 7004 + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-26.0.0.tgz", 7005 + "integrity": "sha512-ztMO++owQnz8c/gIENcM9XfCEzgoGphTv+nKpYNM1bgsdOVC/jRZuEBf6N+mLLDNg68Kl+GgUZfOySaRiG1/Ug==", 7006 + "dependencies": { 7007 + "@ts-morph/common": "~0.27.0", 7008 + "code-block-writer": "^13.0.3" 7009 + } 7010 + }, 7011 + "node_modules/tsconfig-paths": { 7012 + "version": "4.2.0", 7013 + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", 7014 + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", 7015 + "dependencies": { 7016 + "json5": "^2.2.2", 7017 + "minimist": "^1.2.6", 7018 + "strip-bom": "^3.0.0" 7019 + }, 7020 + "engines": { 7021 + "node": ">=6" 7022 + } 7023 + }, 2091 7024 "node_modules/tslib": { 2092 7025 "version": "2.8.1", 2093 7026 "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", 2094 - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", 2095 - "license": "0BSD" 7027 + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" 2096 7028 }, 2097 7029 "node_modules/tw-animate-css": { 2098 7030 "version": "1.4.0", 2099 7031 "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.4.0.tgz", 2100 7032 "integrity": "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==", 2101 7033 "dev": true, 2102 - "license": "MIT", 2103 7034 "funding": { 2104 7035 "url": "https://github.com/sponsors/Wombosvideo" 2105 7036 } 2106 7037 }, 7038 + "node_modules/type-fest": { 7039 + "version": "5.4.4", 7040 + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.4.4.tgz", 7041 + "integrity": "sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw==", 7042 + "dependencies": { 7043 + "tagged-tag": "^1.0.0" 7044 + }, 7045 + "engines": { 7046 + "node": ">=20" 7047 + }, 7048 + "funding": { 7049 + "url": "https://github.com/sponsors/sindresorhus" 7050 + } 7051 + }, 7052 + "node_modules/type-is": { 7053 + "version": "2.0.1", 7054 + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", 7055 + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", 7056 + "dependencies": { 7057 + "content-type": "^1.0.5", 7058 + "media-typer": "^1.1.0", 7059 + "mime-types": "^3.0.0" 7060 + }, 7061 + "engines": { 7062 + "node": ">= 0.6" 7063 + } 7064 + }, 2107 7065 "node_modules/typescript": { 2108 7066 "version": "5.1.6", 2109 7067 "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", 2110 7068 "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", 2111 - "dev": true, 2112 - "license": "Apache-2.0", 7069 + "devOptional": true, 2113 7070 "bin": { 2114 7071 "tsc": "bin/tsc", 2115 7072 "tsserver": "bin/tsserver" 2116 7073 }, 2117 7074 "engines": { 2118 7075 "node": ">=14.17" 7076 + } 7077 + }, 7078 + "node_modules/unicorn-magic": { 7079 + "version": "0.3.0", 7080 + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", 7081 + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", 7082 + "engines": { 7083 + "node": ">=18" 7084 + }, 7085 + "funding": { 7086 + "url": "https://github.com/sponsors/sindresorhus" 7087 + } 7088 + }, 7089 + "node_modules/universalify": { 7090 + "version": "2.0.1", 7091 + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", 7092 + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", 7093 + "engines": { 7094 + "node": ">= 10.0.0" 7095 + } 7096 + }, 7097 + "node_modules/unpipe": { 7098 + "version": "1.0.0", 7099 + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 7100 + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 7101 + "engines": { 7102 + "node": ">= 0.8" 7103 + } 7104 + }, 7105 + "node_modules/until-async": { 7106 + "version": "3.0.2", 7107 + "resolved": "https://registry.npmjs.org/until-async/-/until-async-3.0.2.tgz", 7108 + "integrity": "sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==", 7109 + "funding": { 7110 + "url": "https://github.com/sponsors/kettanaito" 7111 + } 7112 + }, 7113 + "node_modules/update-browserslist-db": { 7114 + "version": "1.2.3", 7115 + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", 7116 + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", 7117 + "funding": [ 7118 + { 7119 + "type": "opencollective", 7120 + "url": "https://opencollective.com/browserslist" 7121 + }, 7122 + { 7123 + "type": "tidelift", 7124 + "url": "https://tidelift.com/funding/github/npm/browserslist" 7125 + }, 7126 + { 7127 + "type": "github", 7128 + "url": "https://github.com/sponsors/ai" 7129 + } 7130 + ], 7131 + "dependencies": { 7132 + "escalade": "^3.2.0", 7133 + "picocolors": "^1.1.1" 7134 + }, 7135 + "bin": { 7136 + "update-browserslist-db": "cli.js" 7137 + }, 7138 + "peerDependencies": { 7139 + "browserslist": ">= 4.21.0" 7140 + } 7141 + }, 7142 + "node_modules/use-callback-ref": { 7143 + "version": "1.3.3", 7144 + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", 7145 + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", 7146 + "dependencies": { 7147 + "tslib": "^2.0.0" 7148 + }, 7149 + "engines": { 7150 + "node": ">=10" 7151 + }, 7152 + "peerDependencies": { 7153 + "@types/react": "*", 7154 + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" 7155 + }, 7156 + "peerDependenciesMeta": { 7157 + "@types/react": { 7158 + "optional": true 7159 + } 7160 + } 7161 + }, 7162 + "node_modules/use-sidecar": { 7163 + "version": "1.1.3", 7164 + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", 7165 + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", 7166 + "dependencies": { 7167 + "detect-node-es": "^1.1.0", 7168 + "tslib": "^2.0.0" 7169 + }, 7170 + "engines": { 7171 + "node": ">=10" 7172 + }, 7173 + "peerDependencies": { 7174 + "@types/react": "*", 7175 + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" 7176 + }, 7177 + "peerDependenciesMeta": { 7178 + "@types/react": { 7179 + "optional": true 7180 + } 7181 + } 7182 + }, 7183 + "node_modules/use-sync-external-store": { 7184 + "version": "1.6.0", 7185 + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", 7186 + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", 7187 + "peerDependencies": { 7188 + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 7189 + } 7190 + }, 7191 + "node_modules/util-deprecate": { 7192 + "version": "1.0.2", 7193 + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 7194 + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" 7195 + }, 7196 + "node_modules/validate-npm-package-name": { 7197 + "version": "7.0.2", 7198 + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-7.0.2.tgz", 7199 + "integrity": "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==", 7200 + "engines": { 7201 + "node": "^20.17.0 || >=22.9.0" 7202 + } 7203 + }, 7204 + "node_modules/vary": { 7205 + "version": "1.1.2", 7206 + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 7207 + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 7208 + "engines": { 7209 + "node": ">= 0.8" 7210 + } 7211 + }, 7212 + "node_modules/web-streams-polyfill": { 7213 + "version": "3.3.3", 7214 + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", 7215 + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", 7216 + "engines": { 7217 + "node": ">= 8" 7218 + } 7219 + }, 7220 + "node_modules/which": { 7221 + "version": "4.0.0", 7222 + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", 7223 + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", 7224 + "dependencies": { 7225 + "isexe": "^3.1.1" 7226 + }, 7227 + "bin": { 7228 + "node-which": "bin/which.js" 7229 + }, 7230 + "engines": { 7231 + "node": "^16.13.0 || >=18.0.0" 7232 + } 7233 + }, 7234 + "node_modules/wrap-ansi": { 7235 + "version": "6.2.0", 7236 + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", 7237 + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", 7238 + "dependencies": { 7239 + "ansi-styles": "^4.0.0", 7240 + "string-width": "^4.1.0", 7241 + "strip-ansi": "^6.0.0" 7242 + }, 7243 + "engines": { 7244 + "node": ">=8" 7245 + } 7246 + }, 7247 + "node_modules/wrap-ansi/node_modules/ansi-regex": { 7248 + "version": "5.0.1", 7249 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 7250 + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 7251 + "engines": { 7252 + "node": ">=8" 7253 + } 7254 + }, 7255 + "node_modules/wrap-ansi/node_modules/emoji-regex": { 7256 + "version": "8.0.0", 7257 + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 7258 + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 7259 + }, 7260 + "node_modules/wrap-ansi/node_modules/string-width": { 7261 + "version": "4.2.3", 7262 + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 7263 + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 7264 + "dependencies": { 7265 + "emoji-regex": "^8.0.0", 7266 + "is-fullwidth-code-point": "^3.0.0", 7267 + "strip-ansi": "^6.0.1" 7268 + }, 7269 + "engines": { 7270 + "node": ">=8" 7271 + } 7272 + }, 7273 + "node_modules/wrap-ansi/node_modules/strip-ansi": { 7274 + "version": "6.0.1", 7275 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 7276 + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 7277 + "dependencies": { 7278 + "ansi-regex": "^5.0.1" 7279 + }, 7280 + "engines": { 7281 + "node": ">=8" 7282 + } 7283 + }, 7284 + "node_modules/wrappy": { 7285 + "version": "1.0.2", 7286 + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 7287 + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 7288 + }, 7289 + "node_modules/ws": { 7290 + "version": "8.19.0", 7291 + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", 7292 + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", 7293 + "engines": { 7294 + "node": ">=10.0.0" 7295 + }, 7296 + "peerDependencies": { 7297 + "bufferutil": "^4.0.1", 7298 + "utf-8-validate": ">=5.0.2" 7299 + }, 7300 + "peerDependenciesMeta": { 7301 + "bufferutil": { 7302 + "optional": true 7303 + }, 7304 + "utf-8-validate": { 7305 + "optional": true 7306 + } 7307 + } 7308 + }, 7309 + "node_modules/wsl-utils": { 7310 + "version": "0.3.1", 7311 + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.1.tgz", 7312 + "integrity": "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==", 7313 + "dependencies": { 7314 + "is-wsl": "^3.1.0", 7315 + "powershell-utils": "^0.1.0" 7316 + }, 7317 + "engines": { 7318 + "node": ">=20" 7319 + }, 7320 + "funding": { 7321 + "url": "https://github.com/sponsors/sindresorhus" 7322 + } 7323 + }, 7324 + "node_modules/y18n": { 7325 + "version": "5.0.8", 7326 + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 7327 + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 7328 + "engines": { 7329 + "node": ">=10" 7330 + } 7331 + }, 7332 + "node_modules/yallist": { 7333 + "version": "3.1.1", 7334 + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", 7335 + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" 7336 + }, 7337 + "node_modules/yargs": { 7338 + "version": "17.7.2", 7339 + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", 7340 + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", 7341 + "dependencies": { 7342 + "cliui": "^8.0.1", 7343 + "escalade": "^3.1.1", 7344 + "get-caller-file": "^2.0.5", 7345 + "require-directory": "^2.1.1", 7346 + "string-width": "^4.2.3", 7347 + "y18n": "^5.0.5", 7348 + "yargs-parser": "^21.1.1" 7349 + }, 7350 + "engines": { 7351 + "node": ">=12" 7352 + } 7353 + }, 7354 + "node_modules/yargs-parser": { 7355 + "version": "21.1.1", 7356 + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", 7357 + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", 7358 + "engines": { 7359 + "node": ">=12" 7360 + } 7361 + }, 7362 + "node_modules/yargs/node_modules/ansi-regex": { 7363 + "version": "5.0.1", 7364 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 7365 + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 7366 + "engines": { 7367 + "node": ">=8" 7368 + } 7369 + }, 7370 + "node_modules/yargs/node_modules/emoji-regex": { 7371 + "version": "8.0.0", 7372 + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 7373 + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 7374 + }, 7375 + "node_modules/yargs/node_modules/string-width": { 7376 + "version": "4.2.3", 7377 + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 7378 + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 7379 + "dependencies": { 7380 + "emoji-regex": "^8.0.0", 7381 + "is-fullwidth-code-point": "^3.0.0", 7382 + "strip-ansi": "^6.0.1" 7383 + }, 7384 + "engines": { 7385 + "node": ">=8" 7386 + } 7387 + }, 7388 + "node_modules/yargs/node_modules/strip-ansi": { 7389 + "version": "6.0.1", 7390 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 7391 + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 7392 + "dependencies": { 7393 + "ansi-regex": "^5.0.1" 7394 + }, 7395 + "engines": { 7396 + "node": ">=8" 7397 + } 7398 + }, 7399 + "node_modules/yoctocolors": { 7400 + "version": "2.1.2", 7401 + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", 7402 + "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", 7403 + "engines": { 7404 + "node": ">=18" 7405 + }, 7406 + "funding": { 7407 + "url": "https://github.com/sponsors/sindresorhus" 7408 + } 7409 + }, 7410 + "node_modules/yoctocolors-cjs": { 7411 + "version": "2.1.3", 7412 + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", 7413 + "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", 7414 + "engines": { 7415 + "node": ">=18" 7416 + }, 7417 + "funding": { 7418 + "url": "https://github.com/sponsors/sindresorhus" 7419 + } 7420 + }, 7421 + "node_modules/zod": { 7422 + "version": "3.25.76", 7423 + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", 7424 + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", 7425 + "funding": { 7426 + "url": "https://github.com/sponsors/colinhacks" 7427 + } 7428 + }, 7429 + "node_modules/zod-to-json-schema": { 7430 + "version": "3.25.1", 7431 + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", 7432 + "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", 7433 + "peerDependencies": { 7434 + "zod": "^3.25 || ^4" 2119 7435 } 2120 7436 } 2121 7437 }
+8 -3
package.json
··· 6 6 "start": "next start" 7 7 }, 8 8 "dependencies": { 9 + "@base-ui/react": "^1.2.0", 9 10 "@radix-ui/react-slot": "^1.2.4", 10 - "@stripe/react-stripe-js": "2.4.0", 11 - "@stripe/stripe-js": "2.2.2", 11 + "@supabase/ssr": "^0.8.0", 12 + "@supabase/supabase-js": "^2.90.1", 12 13 "@tailwindcss/postcss": "^4.1.18", 13 14 "@vercel/analytics": "^1.6.1", 14 15 "@vercel/speed-insights": "^1.3.1", 15 16 "class-variance-authority": "^0.7.1", 16 17 "clsx": "^2.1.1", 18 + "framer-motion": "^12.35.2", 17 19 "lucide-react": "^0.562.0", 18 20 "next": "latest", 19 21 "postcss": "^8.5.6", 22 + "radix-ui": "^1.4.3", 20 23 "react": "18.2.0", 21 24 "react-dom": "18.2.0", 22 25 "server-only": "0.0.1", 26 + "shadcn": "^3.8.5", 23 27 "stripe": "14.8.0", 24 - "tailwind-merge": "^3.4.0", 28 + "tailwind-merge": "^3.5.0", 25 29 "tailwindcss": "^4.1.18" 26 30 }, 27 31 "devDependencies": { 28 32 "@types/node": "20.4.6", 29 33 "@types/react": "18.2.8", 34 + "@types/react-dom": "^18.2.8", 30 35 "tw-animate-css": "^1.4.0", 31 36 "typescript": "5.1.6" 32 37 }
public/apple-touch-icon.png

This is a binary file and will not be displayed.

+10
public/atmosphere-icons/logo-anisota.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <g clip-path="url(#clip0_1_128)"> 3 + <path d="M9.83652 0C9.90386 0.229663 10.0321 0.239807 10.1771 0.28125C10.4844 0.369237 10.7666 0.341946 11.0756 0.344531C11.502 0.348847 11.901 0.471629 12.3248 0.407812C12.8135 0.333561 13.8077 0.396379 14.2998 0.36875L14.6818 0.346875C14.8985 0.389181 15.082 0.421503 15.3021 0.400781C15.8321 0.350734 16.3379 0.372871 16.867 0.395312L17.5717 0.425781C18.0171 0.444772 18.4661 0.386904 18.9193 0.385156L19.6498 0.383594L20.667 0.380469C21.2453 0.378742 21.6753 0.445793 22.0568 0.432031C22.6767 0.409583 23.2711 0.414721 23.885 0.424219C24.1569 0.428536 24.4352 0.411063 24.7037 0.434375C25.0567 0.465419 25.3849 0.428748 25.731 0.446875L27.2482 0.524219C27.678 0.54576 28.0914 0.508263 28.5271 0.561719C29.0115 0.621293 29.4767 0.672574 29.9576 0.673437H30.5396L31.6209 0.675L34.5943 0.720312L35.3623 0.7125L35.967 0.707031L36.5162 0.709375L37.6123 0.667187L38.1732 0.696875C38.2889 0.702919 38.3962 0.689021 38.5084 0.68125C38.9461 0.65277 39.376 0.687333 39.8232 0.672656L41.1818 0.627344L41.7935 0.625L43.4162 0.585156L44.4732 0.560937L45.092 0.546875L46.6865 0.475L47.7553 0.424219L48.5459 0.401562L49.0357 0.385937L49.8732 0.366406L51.2303 0.360156L52.7162 0.424219L53.285 0.419531C53.8004 0.416078 53.4137 0.604556 53.8092 1.30391L53.8623 1.67031L54.0185 2.62969C54.1187 3.24529 53.9447 3.87248 53.9404 4.49844C53.9361 5.11564 53.973 5.70007 53.9998 6.31641L54.067 7.81719L54.0506 9.02266C54.048 9.22722 54.0622 9.43795 54.0303 9.63906C54.0139 9.74223 53.9544 10.5854 53.9576 10.6539L54.0264 12.0492L54.0287 12.6273L54.0365 14.1414C54.0365 14.2363 54.0469 14.353 54.0529 14.4453C54.0719 14.7233 54.0711 14.9931 54.085 15.2711L54.1092 15.7633L54.1115 16.0937L54.1201 16.7703V17.1336C54.1176 17.8143 54.2433 17.6058 54.0818 18.4164C53.9982 18.8368 54.0558 19.298 54.0584 19.6312C54.061 19.9247 54.0179 20.24 53.9998 20.543L53.9553 21.2758L53.9287 21.7141C53.9045 22.1103 53.9336 22.4792 53.9396 22.8633L53.956 23.807L53.999 24.6492L54.0154 25.6523L54.0131 27.2852L53.9959 28.6312L53.9631 29.7414L53.9076 30.8391L53.8459 32.5352C53.8286 32.9996 53.8396 33.4538 53.881 33.907C53.9009 34.1254 53.8969 34.3473 53.8865 34.5734C53.8701 34.9274 53.8942 35.2639 53.8959 35.6187L53.9084 38.1969L53.8998 39.1602L53.9092 39.4875C53.9161 39.7197 53.8991 39.9359 53.8896 40.175C53.8854 40.2769 53.9206 40.4329 53.924 40.5484L53.9576 41.7367L53.9748 42.3375L53.9576 43.0602L53.9545 45.0414L53.9232 46.1945L53.9209 47.2273L53.942 47.8352L53.9482 48.2937L53.931 48.8898C53.9207 49.2377 53.971 49.5649 54.0107 49.9016C54.0427 50.1683 54.0121 50.426 54.0303 50.7031L54.0701 51.3187L54.0865 52.1492L54.1334 53.4789C54.1446 53.7879 54.1498 54.0857 54.1662 54.4008L54.21 55.243L54.2646 55.6078L54.249 56.5312L54.231 56.9281C54.2242 57.0679 54.2246 57.1966 54.2271 57.3312L54.2365 57.9312L54.2717 58.5453C54.2777 58.654 54.2478 58.7782 54.2443 58.8852C54.2184 59.5749 54.2746 60.1844 54.2514 60.7766L54.2373 61.1234L54.2256 61.6383L54.206 62.4047L54.2021 63.0359C54.2006 63.2577 54.3874 63.4769 54.106 63.6961C54.0483 63.7409 53.9967 63.797 53.9545 63.8031C53.9123 63.8092 53.8175 63.7412 53.7717 63.7375C53.6499 63.7271 53.5245 63.7175 53.3959 63.6727L53.1389 63.7602L52.8935 63.6969C52.8833 63.6943 52.8225 63.6929 52.8115 63.6937L52.7303 63.7008L52.6607 63.7055C52.6455 63.7061 52.6465 63.6869 52.631 63.6234C52.5189 63.5932 52.3349 63.6403 52.1959 63.6516C52.0293 63.6654 51.8895 63.5894 51.7264 63.7102C51.6452 63.7706 51.4695 63.74 51.3529 63.7383C51.0085 63.7331 50.6607 63.7193 50.324 63.7633C50.0633 63.7978 49.8413 63.7723 49.5771 63.768L48.8482 63.7539L47.5232 63.7586L46.4451 63.7547C46.2624 63.7547 46.1039 63.7294 45.9264 63.657L45.7959 63.7484C45.0199 63.8641 44.9542 63.6899 44.324 63.7711C44.1928 63.7883 44.007 63.7446 43.874 63.7523L43.3021 63.7859L42.7467 63.8227L42.3435 63.8516C42.2037 63.8619 42.049 63.8541 41.9092 63.8516L41.5537 63.8422L40.3896 63.8609C40.204 63.8644 40.04 63.8496 39.8717 63.8047C39.7974 63.8142 39.665 63.8319 39.5795 63.8336L39.2162 63.8422C39.117 63.8448 38.9712 63.8449 38.8779 63.8328C38.5455 63.7896 38.2571 63.7859 37.9342 63.7781L37.4975 63.768C37.3973 63.7654 37.3157 63.767 37.206 63.7773L36.9389 63.7266L36.5685 63.7375L35.9982 63.7539L35.6834 63.7695L35.3264 63.7891C35.0624 63.8037 34.813 63.8309 34.549 63.8344L33.781 63.843C33.5463 63.8455 33.2857 63.7778 33.0639 63.8062L32.5154 63.8766C32.461 63.8835 32.3187 63.8911 32.2678 63.8617C32.1244 63.778 31.8893 63.8577 31.7451 63.8586L30.5826 63.868C30.0059 63.8723 30.1117 63.9148 29.4857 63.907L29.0553 63.9016L28.6482 63.8961C28.3789 63.8926 28.1302 63.8863 27.8678 63.907C27.7288 63.9182 27.5844 63.9018 27.442 63.8992L26.3537 63.8781C25.7028 63.866 25.4565 63.7775 24.8256 63.85C24.6037 63.8759 24.4004 63.85 24.1803 63.8336C23.734 63.8008 22.6882 63.8773 22.4037 63.7781C22.2966 63.741 21.215 63.8258 21.0717 63.8258L20.3318 63.8273L19.724 63.8586C19.5247 63.869 19.3254 63.8969 19.1373 63.8961L18.2904 63.8914C18.0815 63.8905 17.8875 63.8566 17.6803 63.8695C17.3679 63.8902 17.066 63.8964 16.7459 63.893C16.3617 63.8886 15.9962 63.8995 15.6154 63.9133L14.8139 63.9422L13.2123 63.9992C12.9948 64.007 12.7825 63.9881 12.5693 63.982L11.8607 63.9609L10.9982 63.9328C10.8782 63.9285 10.7489 63.9085 10.635 63.9094L9.8248 63.918C9.75319 63.899 9.79445 63.7145 9.81777 63.6367C9.89201 63.3838 9.85383 63.1211 9.86074 62.8664L9.89277 61.7687L9.9412 60.4141C9.94811 60.2173 9.95156 60.0469 9.9412 59.8484C9.92136 59.4802 9.90134 58.1535 9.95136 57.8562C10.055 57.2424 10.1308 56.6619 10.174 56.0445L10.2303 55.232C10.2338 55.1829 10.2754 55.1242 10.3271 55.0414L10.2373 55.0344C10.214 54.7918 10.2014 54.5276 10.2014 54.2617V52.1562L10.2154 51.1227L10.2185 50.6703C10.2203 50.3396 10.2255 50.0311 10.1935 49.6953C10.1746 49.4882 10.1791 49.2801 10.1834 49.0781L10.1896 48.7711L10.2365 47.2891C10.2486 46.891 10.2151 46.9139 10.2185 46.5703L10.2381 44.7969L10.2475 43.9461L10.2748 43.1898L10.2834 42.393L10.2951 41.9758L10.3217 41.0391L10.3295 40.3344L10.3037 39.3641L10.2654 38.5453L10.2553 38.1859L10.2357 37.5125L10.1834 35.8422L10.1912 35.343L10.1826 34.668V33.7727L10.1771 33.4922L10.1482 32.65L10.1287 32.082C10.1244 31.9578 10.0823 31.8361 10.0779 31.7187L10.0568 31.1859C10.0396 30.7466 10.0247 30.3226 10.0178 29.8781C10.0143 29.6571 10.0683 29.4362 10.0787 29.2195L10.1123 28.507C10.1339 28.0581 10.044 27.8134 10.0881 27.5164C10.1235 27.2755 10.1199 27.0205 10.0975 26.7719L10.0623 26.3797L10.0553 25.9664L10.0498 25.3375L10.042 24.9047C10.0316 24.3461 10.0329 23.8083 10.0709 23.2445C10.0925 22.92 10.0611 22.6012 10.0576 22.2836L10.0521 21.7531L10.0271 20.8125C10.0107 20.2005 10.0625 20.0325 10.06 19.3922L10.0537 17.9141L10.0568 17.3695L10.0428 16.8969L10.0154 15.8125L9.95917 14.8C9.92034 14.1042 9.91962 13.4402 9.9412 12.7461C9.95759 12.191 9.92718 11.6558 9.91855 11.1016L9.89589 9.63359L9.90058 8.77109C9.90231 8.49917 9.90711 8.24343 9.89589 7.96719L9.83574 6.55937L9.78574 5.43047C9.76502 4.96779 9.74812 4.52745 9.75761 4.06562L9.77089 3.42187L9.82167 2.59531C9.83635 2.35875 9.79581 2.13306 9.79667 1.89219L9.80058 1.04375C9.80058 0.833231 9.81861 0.602 9.75917 0.399219C9.71774 0.255925 9.68208 0.121718 9.83652 0ZM28.9764 41.7852C28.9434 41.8871 28.8049 42.0784 28.785 42.1828C28.7003 42.6439 28.653 43.0802 28.6115 43.543C28.5943 43.7329 28.6058 43.9385 28.567 44.1094C28.5333 44.2595 28.487 44.413 28.474 44.5562L28.4209 45.1141C28.3803 45.5457 28.4233 45.9601 28.381 46.3883L28.2545 47.6805C28.2338 47.89 28.2512 47.9843 28.1787 48.1836C28.0786 48.4573 28.157 49.0916 28.0975 49.4258L28.0014 49.9617L27.8506 51.0211C27.8186 51.2473 27.7488 51.4825 27.7428 51.707C27.7315 52.0877 27.7322 52.4441 27.6615 52.8109L27.4404 53.9586C27.4335 53.9931 27.4257 54.5787 27.3998 54.8437C27.3463 55.3946 27.3192 55.9353 27.2959 56.4922L27.2678 57.1906L27.1959 58.0742C27.1596 58.5249 27.1728 58.9642 27.1201 59.4227C27.0813 59.7636 27.1242 60.1217 27.056 60.4445C27.0198 60.6146 26.9247 60.7661 26.942 60.95L26.9818 61.3828C27.1018 61.2974 27.196 61.2345 27.2521 61.2086C27.3298 61.3795 27.3611 61.4408 27.456 61.5547C27.7106 61.3837 27.6851 61.1343 27.7498 60.8805L27.8732 60.3961L27.8748 60.3953C27.9836 59.9688 28.0568 59.5551 28.0982 59.1398L28.1857 58.2672L28.285 57.5727C28.3324 57.2413 28.3266 56.8978 28.3568 56.5578L28.474 55.2359C28.4861 55.097 28.5309 54.9207 28.5318 54.793L28.5381 54.2172C28.5398 54.0403 28.5015 53.8293 28.5498 53.6602C28.6758 53.2199 28.514 53.4182 28.5865 52.8633L28.7068 51.9375C28.7155 51.8736 28.7188 51.7666 28.724 51.6984L28.781 50.9977L28.8467 50.182C28.8855 49.6986 28.9288 49.2376 29.0756 48.7602C29.1127 48.6402 29.0931 48.4971 29.0982 48.3711L29.1185 47.882L29.1646 47.0758L29.2107 46.2273C29.2246 45.977 29.2908 45.7199 29.3365 45.4695C29.3865 45.1925 29.3702 44.9146 29.4021 44.6367C29.422 44.4675 29.4912 44.2897 29.499 44.1102L29.5334 43.2969C29.542 43.0914 29.5178 42.8784 29.5092 42.6617C29.4867 42.1365 29.4012 42.4624 29.4279 41.8094L28.9764 41.7852ZM22.7709 51.2711C22.3853 51.1229 22.6221 51.5976 22.5271 52.2148C22.4978 52.4064 22.5192 52.6178 22.5037 52.8086L22.474 53.1516C22.4671 53.2379 22.4327 53.3502 22.4318 53.4391C22.4283 53.9173 22.2428 54.3991 22.2834 54.8687C22.3067 55.1407 22.2912 55.3453 22.2506 55.6164L22.1326 56.4016L22.0568 56.8164C22.0102 57.0771 21.8922 58.3243 22.0209 58.5781L21.9459 58.8242L21.9521 59.4578C21.9582 60.1508 22.145 60.0025 22.0381 60.4391L21.9435 60.825C22.0161 60.9787 22.3222 61.0987 22.481 61.0141C22.6744 60.9114 22.8596 60.9237 23.0115 61.0852L23.3951 61.1203C23.5574 61.135 23.716 61.1127 23.817 61.2828C24 61.5884 24.1167 61.2834 24.5303 61.318C24.2455 60.8311 24.7581 60.8585 24.4654 60.0867C24.4302 59.9927 24.459 59.825 24.4256 59.7516L24.4271 59.7531C24.384 59.6581 24.3199 59.5274 24.2975 59.4445L24.2185 59.1469L24.0584 58.5641L23.9748 58.1273C23.9446 57.9693 23.8553 57.5436 23.7232 57.4383L23.71 57.268L23.6662 56.6562L23.6232 56.3258C23.5973 56.1299 23.5448 55.9452 23.4904 55.7648C23.3963 55.4516 23.2982 55.3257 23.3568 55.1867C23.1764 55.1505 23.272 54.9065 23.2115 54.8219C23.1278 54.7046 23.0193 54.589 23.0209 54.4148L23.0256 54.0102C22.9818 53.9895 22.8142 53.8348 22.8271 53.7453L22.8982 53.2578C22.9077 53.1931 22.8949 53.1142 22.8803 53.0391C22.8432 52.8482 22.8732 52.383 22.8326 52.1836C22.8119 52.0791 22.7835 51.8934 22.856 51.8148C22.8827 51.7852 22.9006 51.6582 22.8662 51.6555L22.7021 51.6406L22.706 51.3969L22.635 51.3437C22.6212 51.3334 22.6701 51.3077 22.6857 51.3016L22.7709 51.2711ZM47.0115 43.6156C46.6958 43.7824 46.5273 43.178 46.4678 43.5008C46.4212 43.7544 46.3605 43.9666 46.2725 44.2047C46.1404 44.5587 46.1956 44.6325 46.0428 45.0625C45.9867 45.2186 45.9617 45.3576 45.9264 45.5172C45.8305 45.9506 45.6176 46.3611 45.5951 46.8031C45.564 47.4168 45.4313 47.4575 45.3217 48.0531C45.2353 48.5219 45.1736 48.9718 45.0303 49.4242C44.8948 49.8507 45.0838 49.9425 44.8326 50.5969C44.7895 50.709 44.7557 50.8032 44.7342 50.9102L44.5771 51.6711L44.3279 52.6367L44.256 52.918L43.9795 53.7734L43.7904 54.5867L43.6529 55.1969L43.4967 55.8641C43.4492 56.0661 43.4055 56.285 43.3451 56.4836C43.2157 56.9125 43.1622 57.3225 43.0475 57.7531L42.885 58.3641C42.8479 58.5022 42.8263 58.6679 42.7857 58.8086L42.542 59.6641L42.4076 60.1758C42.3765 60.294 42.3715 60.5063 42.3232 60.6039C42.2335 60.7843 42.1397 60.9797 42.1396 61.1859C42.9081 61.2023 42.7384 61.4723 43.7123 61.4023H43.71L44.1021 61.0875C44.0858 60.4904 44.3245 60.9078 44.4678 60.25L44.6193 59.5477C44.7151 59.1057 44.9232 58.717 44.9975 58.2742C45.0527 57.9435 45.1325 57.6192 45.2076 57.2859L45.3271 56.7578C45.5689 55.6915 45.6513 56.0102 45.7834 54.6383C45.8076 54.3914 45.9087 54.1333 45.9459 53.8898L46.0232 53.3766L46.1037 52.8805L46.1537 52.5719C46.2141 52.2033 46.2457 51.8414 46.3545 51.4797L46.6889 50.3711C46.7743 50.0863 46.8523 49.8042 46.9248 49.5125L47.1334 48.675C47.2059 48.3858 47.2517 48.1058 47.3225 47.8148L47.6357 46.5297C47.7229 46.1732 47.7866 45.8173 47.9178 45.4781L48.0498 45.1391C48.1483 44.8851 48.6207 43.8568 48.5139 43.7062C47.6481 43.4188 48.1351 43.49 47.567 43.5539C47.3857 43.5746 47.1971 43.5181 47.0115 43.6156ZM16.7271 56.8633C16.671 56.8618 16.5609 56.9366 16.5264 56.9875C16.4176 57.1472 16.2895 57.1051 16.1271 57.0922L15.7404 57.0617C15.6585 57.0556 15.5371 56.9492 15.4654 56.9516L14.2951 56.9945C14.1501 56.9997 13.9906 57.018 13.8404 57.0508C13.5115 57.1212 13.3544 57.8253 13.3459 57.8422L12.9935 58.2758C12.8511 58.451 12.7977 58.6743 12.6717 58.8789C12.657 58.979 12.6722 59.1452 12.5912 59.2367C12.3866 59.4664 12.4236 59.7936 12.3045 60.0578C12.2389 60.2037 12.1344 60.349 12.0826 60.4992L11.9146 60.9883C11.8793 61.0909 11.8451 61.211 11.8795 61.343C11.9986 61.3853 12.1841 61.3195 12.3326 61.3281L13.0435 61.3687V61.3664C13.2058 61.3759 13.332 61.3376 13.4623 61.3445L13.8029 61.3625C14.5195 61.4005 14.1254 61.2801 14.8584 61.1937L15.4607 61.1234C15.6265 61.1044 15.958 60.8818 16.1178 60.9914C16.1747 61.0303 16.2253 61.12 16.3029 61.2305C16.3979 60.9801 16.4419 60.7092 16.4592 60.4398L16.4756 60.1852C16.4928 59.9151 16.5182 59.6657 16.5545 59.3844C16.6149 59.1876 16.8854 58.8776 16.9045 58.7273C16.9105 58.6756 16.8196 58.5797 16.8092 58.5219C16.7013 57.9159 16.5888 58.3223 16.7467 57.7891L16.8771 57.3484C16.9142 57.2215 16.8178 57.0014 16.7271 56.8633ZM21.1592 43.1094C21.098 43.1189 21.0221 43.2247 20.985 43.2852C20.7061 43.1479 20.8682 43.3292 20.3467 43.2687C20.1361 43.2447 19.8575 43.4786 19.8865 43.7047C19.9133 43.9101 20.1301 44.1169 20.0068 44.3344C19.9291 44.4708 19.947 44.6403 19.9029 44.7836C19.8347 45.0045 19.665 45.209 19.6045 45.4531C19.5225 45.7837 19.5348 46.1258 19.5443 46.4719C19.5452 46.5168 19.5416 46.5979 19.5701 46.6117C19.5986 46.6254 19.6655 46.613 19.6709 46.5812L19.6842 46.4937C19.6876 46.4748 19.7632 46.4851 19.7631 46.5039L19.756 46.5914L19.7482 46.6883C19.7451 46.7107 19.5406 46.7384 19.5756 46.7805L19.6326 46.8484C19.6853 46.9123 19.7426 46.9728 19.7685 47.0203C19.7945 47.0678 19.6979 47.2036 19.71 47.2641C19.7557 47.4979 19.7365 47.8413 19.6787 48.0977C19.6286 48.3213 19.6264 48.5422 19.5935 48.7641C19.5479 49.072 19.5332 49.4137 19.5935 49.7156L19.667 50.0805C19.7498 50.4931 19.6141 50.1349 19.5623 50.6961C19.5338 51.0112 19.4762 51.311 19.5021 51.6148C19.5185 51.8132 19.4843 51.9583 19.342 52.1023C19.3066 52.1438 19.4274 52.2426 19.499 52.2711L19.4639 52.8625C19.4553 53.0092 19.4721 53.1759 19.4514 53.3148C19.4272 53.4753 19.3938 53.623 19.4154 53.7922C19.4352 53.9501 19.403 54.0849 19.3857 54.2359C19.359 54.4706 19.3361 54.7097 19.324 54.9461L19.2881 55.6055C19.276 55.8247 19.3028 56.05 19.2467 56.2562C19.1992 56.4288 19.2546 56.6273 19.2357 56.8094L19.1631 57.493L19.131 58.0375L19.081 58.6406C19.0456 59.0654 19.0543 59.4113 19.0154 59.7852C18.9956 59.9775 18.982 60.1475 18.9717 60.3477L18.9725 60.3469C18.9638 60.523 18.8376 60.7927 19.0068 60.9437C19.0458 60.9756 19.1837 60.9876 19.1865 61.0367L19.2006 61.2766L19.5412 61.2281C19.7161 60.9944 19.4275 60.9246 19.574 60.6555C19.6396 60.5346 19.6236 60.4425 19.6037 60.3078C19.5667 60.0618 19.6775 59.7848 19.6568 59.5492C19.6473 59.4396 19.6388 59.3626 19.6475 59.2547L19.6803 58.8383L19.7279 58.7602C19.7382 58.7429 19.6894 58.688 19.6967 58.668L19.7396 58.5664C19.7486 58.544 19.6531 58.5037 19.6467 58.4805C19.6234 58.3951 19.7224 58.2079 19.7209 58.118C19.7183 58.0057 19.683 57.8544 19.7037 57.7258C19.7814 57.2302 19.7531 56.7188 19.8412 56.2336L19.8842 55.9992C19.9938 55.4 19.8471 55.004 20.0146 54.6414C20.0784 54.5026 20.1171 54.4004 20.1326 54.2391L20.306 52.432L20.3342 52.125L20.442 50.9406C20.4541 50.812 20.4826 50.6966 20.5076 50.568C20.562 50.2832 20.5766 49.9897 20.6068 49.6945L20.6654 49.1242L20.7201 48.4453C20.74 48.1941 20.7692 47.9494 20.7787 47.7008C20.7934 47.3296 20.8145 46.9782 20.874 46.607C20.8921 46.4957 20.8501 46.3493 20.8553 46.2578C20.8898 45.5614 20.8884 45.7339 21.1318 45.2703C21.1835 45.1719 21.1473 45.0481 21.1568 44.9445C21.1726 44.7715 21.3323 44.2394 21.4014 44.0539C21.4601 43.8977 21.5682 43.8191 21.4982 43.6266L21.3662 43.2648C21.3325 43.1733 21.2438 43.0956 21.1592 43.1094ZM35.3342 40.3586C35.2297 40.3476 35.0591 40.4639 34.9443 40.507C34.7294 40.589 34.5074 40.6177 34.2795 40.6695C34.1051 40.7092 33.9056 40.8284 33.7217 40.8336C33.4454 40.8422 33.2581 40.8697 33.006 40.95L32.5935 41.0828C32.3777 41.1519 32.3161 41.2179 32.235 41.4406C32.1641 41.6342 31.9758 42.2409 31.9904 42.4109L32.0279 42.8391C32.053 43.1309 31.9697 43.2889 31.8756 43.6773L31.7365 44.2523L31.4881 45.5422C31.2921 46.56 31.3881 45.9854 31.3381 46.9227L31.2912 47.8008L31.2318 48.5109V48.8586C31.2336 49.3662 31.1105 49.6918 31.1623 50.0578C31.1822 50.1985 31.3022 50.3911 31.285 50.5336L31.2225 51.0492C31.1983 51.2478 31.1184 51.4475 31.1115 51.6469L31.0889 52.3047L31.042 52.9117C31.0126 53.2924 30.9952 53.6214 31.0193 54.0047C31.0253 54.1006 30.9809 54.2843 30.9662 54.4008L30.8717 55.1703L30.7967 55.8922C30.7803 56.0527 30.7545 56.209 30.7295 56.3703L30.531 57.6586C30.4974 57.8769 30.4527 58.0797 30.4467 58.3023C30.4406 58.5406 30.3985 58.7608 30.3631 58.9922L30.281 59.5297C30.2223 59.9164 30.0635 60.4191 30.281 60.7695C30.3485 60.879 30.5513 60.9477 30.6506 61.0383C31.1332 61.4777 31.2483 61.0598 31.6748 61.2602C31.9016 61.1944 31.9553 60.9318 32.2935 61.1898L32.299 61.1867C32.3982 61.1571 32.5165 61.0042 32.5967 60.9602C32.7668 60.8669 32.9127 60.7559 33.0482 60.6039L33.5553 60.0352C33.6182 59.9654 33.6645 59.9074 33.7412 59.8453C33.8845 59.7305 33.9636 59.5318 34.081 59.3859L34.674 58.6414C34.7033 58.5292 34.7229 58.3404 34.76 58.2266L34.9021 57.7891C34.979 57.5516 35.0028 57.3363 34.9795 57.0859C34.9216 56.4652 34.9373 56.1421 34.7318 55.5437L34.6404 55.2773L34.5779 55.093C34.4874 55.0402 34.4373 54.9297 34.3795 54.8133C34.1939 54.4378 34.0131 54.0714 33.9475 53.657C33.5457 53.474 33.773 53.2342 33.4709 52.9227C33.4113 52.302 33.4217 52.775 33.331 52.4367C33.2646 52.1881 33.1481 51.9744 33.0428 51.7344C32.973 51.5747 32.9859 51.3608 32.9428 51.1891L32.71 50.2586C32.653 50.0324 32.6561 49.8022 32.6639 49.5734L32.6889 48.8523L32.6451 48.4953C32.6253 48.3322 32.6354 48.1802 32.6475 48.0258L32.7139 47.1922C32.7536 46.6915 32.6676 46.4213 32.8092 45.9672C33.0112 45.318 32.8593 45.5009 32.9576 44.9961L33.031 44.6156C33.0923 44.3006 33.1487 43.9991 33.2514 43.6953L33.4162 43.2094C33.4343 43.1549 33.4392 43.0298 33.4435 42.9539C33.6559 42.7735 33.8094 42.5262 33.9053 42.2586C33.9647 42.2224 34.1215 42.1873 34.1607 42.1391L34.3873 41.8547L34.9342 41.3391L35.1584 41.1359C35.5114 41.0643 35.7329 40.7446 35.6881 40.3977L35.3342 40.3586ZM50.1092 57.2203C50.1143 57.2324 50.0642 57.2934 50.0451 57.2937L48.756 57.3297C48.4271 57.3383 48.1454 57.3341 47.8225 57.3289C47.7913 57.8577 47.5541 57.8087 47.5256 58.1969C47.4746 58.8988 47.1338 58.8913 47.1131 59.8695C47.1096 60.0413 47.2335 60.2781 47.0514 60.4094C46.977 60.4629 46.8294 60.5494 46.8217 60.6719L46.8014 60.9898C47.1596 60.8088 47.6766 61.1113 47.9123 61.1148C48.7377 61.1278 48.7654 61.1937 49.7014 61.1445C50.0847 61.1238 50.7877 61.1863 50.9232 61.1664L50.9248 61.1672L51.2639 61.1164C51.3821 61.0983 51.5162 61.0206 51.6482 60.9602L51.2396 60.7461L51.481 60.2773C51.4897 60.2601 51.5521 60.2249 51.5443 60.2094C51.5363 60.1935 51.5085 60.1515 51.5076 60.1344C51.4938 59.8817 51.4499 59.7466 51.5842 59.7266C51.5592 59.7153 51.4993 59.6281 51.5076 59.5789C51.5145 59.54 51.5516 59.4894 51.5904 59.4367C51.4162 59.34 51.5055 59.1608 51.4943 59.0391L51.467 58.7258C51.4532 58.5756 51.358 58.5882 51.4451 58.0531C51.4555 57.9866 51.4634 57.886 51.5092 57.8609L51.7193 57.7437L51.2365 57.5477C51.183 57.5261 51.0757 57.4145 51.0498 57.4016C50.9436 57.4292 50.8926 57.4237 50.7795 57.4047L50.1771 57.3016C50.159 57.2981 50.0991 57.1976 50.1092 57.2203ZM44.4857 38.5867C44.1784 38.7395 43.7135 38.8926 43.356 38.9453C43.2542 38.9739 43.1232 39.1025 43.0412 39.1086C42.4498 39.1526 42.3954 39.0516 41.8006 39.2898C41.5277 39.3986 41.2838 39.5265 41.0334 39.6836L40.6904 39.8992L40.1779 40.2359L39.4732 40.7016L39.024 40.9781L38.7193 41.1992C38.6434 41.2545 38.5261 41.3447 38.4545 41.4086L37.1271 42.6078C36.8095 42.8953 36.5719 43.3424 36.3803 43.5945C36.0971 43.9675 35.64 44.651 35.506 45.0672C35.424 45.3219 35.327 45.5555 35.2959 45.8102L35.206 46.5297C35.1827 46.7136 35.1824 46.8987 35.1678 47.0844L35.1404 47.443L35.1006 47.9109C35.0799 48.1526 35.0794 48.3865 35.0881 48.6273L35.1006 48.9477C35.1248 49.5787 35.1499 49.8036 35.3545 50.382L35.6928 51.3375C35.8533 51.7915 35.9903 51.8315 36.1975 52.3156C36.346 52.6627 36.6596 53.3865 36.8443 53.6758C37.1034 54.0808 37.6397 55.5018 37.6553 55.7703L37.7014 56.568C37.7144 56.7985 37.9651 57.1542 37.7373 57.868C37.6769 58.0561 37.6274 58.2202 37.592 58.4109L37.5303 58.7414C37.4344 59.2498 37.1499 59.6837 36.8357 60.0937C36.6035 60.3977 36.4583 60.7393 36.3357 61.1141C36.7389 61.2012 36.8929 60.8123 37.1959 60.9969C37.4359 61.1428 37.6555 61.085 37.899 61.0375L38.3834 60.943C38.475 60.925 38.6891 60.9675 38.7428 60.8883C38.8351 60.7502 38.8959 60.752 39.0451 60.6727C39.1945 60.5932 39.447 60.3514 39.4678 60.1891C39.4885 60.0267 39.4871 59.8962 39.5381 59.7312H39.5357L39.6529 59.3437L39.9146 58.1391L40.006 57.7594C40.1502 57.1611 40.2721 56.5733 40.4982 55.9992C40.7244 55.4251 40.7087 54.8191 40.8615 54.2484C40.9617 53.8738 41.1158 53.5268 41.2185 53.1461L41.4412 52.318L41.706 51.6281C41.8105 51.3571 41.868 51.1257 41.9975 50.8633C42.063 50.7295 42.132 50.5515 42.1717 50.4031L42.3271 49.8156C42.448 49.3563 42.5476 48.9092 42.6365 48.443C42.6521 48.3627 42.6942 48.2451 42.7287 48.1719C43.0324 47.5254 43.1166 46.8384 43.2443 46.1453L43.4225 45.1703L43.6264 44.2406C43.6592 44.0922 43.7715 43.8908 43.6818 43.7414C43.6447 43.6792 43.5066 43.6158 43.4435 43.5727C43.4186 43.5553 43.373 43.4709 43.3514 43.4898L43.2584 43.5727C43.1229 43.6935 42.8995 43.6659 42.7217 43.6875C42.5318 43.7099 42.436 43.6748 42.3178 43.5367C42.2418 43.4486 42.0566 43.537 42.01 43.6492C41.9347 43.8299 41.7244 43.6735 41.4467 43.757C41.2317 43.5921 40.9722 43.6498 40.5475 43.5453L40.249 43.4719C40.1964 43.4589 40.1036 43.438 40.0881 43.4328L40.0959 42.9477L40.1053 42.3445C40.1079 42.1547 40.1846 41.9319 40.1045 41.7437C40.0389 41.5901 40.0064 41.4159 40.1592 41.3062L40.6373 40.9648C40.7176 41.0779 40.8162 41.097 40.956 41.1039C41.3316 41.122 41.6952 41.1954 42.0639 41.0633C42.1898 41.0184 42.3053 41.0421 42.4381 41.043L43.567 41.0477L44.1123 41.0328C44.1779 41.0311 44.2613 41.0273 44.3131 41.0195C44.4439 41.001 44.3296 40.6383 44.6685 40.3906C44.8309 40.2715 44.8586 40.1138 44.8975 39.9273L45.0154 39.3602C44.9818 39.273 44.9328 39.1608 44.9725 39.0703C45.0467 38.9011 45.3878 38.7747 45.2264 38.6789C45.0132 38.553 44.7955 38.6021 44.5935 38.6539C44.5879 38.6321 44.5185 38.5707 44.4857 38.5867ZM17.3678 48.2023C17.259 48.4009 17.2038 48.5664 17.1373 48.7641L16.8748 49.5414L16.5107 50.4117L16.4037 50.7156C16.3545 50.8546 16.3295 51.0208 16.231 51.1391C16.0101 51.4066 15.8409 51.6766 15.7123 51.9984C15.6389 52.1831 15.5559 52.3716 15.5162 52.5641C15.3884 53.1761 15.3278 53.0349 15.1639 53.5664L14.824 53.9937C14.7221 54.1224 14.6599 54.1559 14.6685 54.3398C14.6719 54.4089 14.637 54.5213 14.6732 54.5695C14.877 54.8387 15.164 54.8167 15.3271 54.8469C15.5952 54.896 15.8745 54.8741 16.1443 54.8336C16.228 54.8215 16.3895 55.0325 16.4646 54.8758C16.4862 54.83 16.5283 54.7664 16.5568 54.7422C16.6302 54.6792 16.8271 54.8066 16.8935 54.7203C16.9177 54.6892 16.9453 54.6134 16.96 54.5617L17.11 54.0078C17.0651 53.9095 17.0548 53.8267 17.0685 53.7344L17.0998 53.5227C17.0646 53.5201 17.0187 53.5286 17.0217 53.5117C17.0251 53.4944 17.045 53.4085 17.0381 53.393C16.9779 53.2616 17.1075 52.9896 17.117 52.843L17.1865 51.7859C17.2072 51.4743 17.1971 51.158 17.2748 50.8602C17.3456 50.5865 17.2975 50.3331 17.3131 50.0758C17.3425 49.5872 17.5979 49.1253 17.5771 48.6203L17.5654 48.3594L17.3678 48.2023ZM51.6068 42.2734C51.6119 42.2052 51.4661 42.1165 51.4264 42.1734C51.3892 42.2265 51.2161 42.8391 51.324 42.8633C51.2852 42.9746 51.2316 43.1273 51.185 43.2594L51.0498 43.6422C51.0309 43.6958 51.0355 43.7975 51.0381 43.8492L50.9396 44.2547L50.8115 44.7617L50.4896 45.9508L50.3404 46.5078L50.2365 46.9719L50.0975 47.5969L50.0615 47.8469C50.033 48.0393 49.968 48.2274 49.924 48.4164L49.7404 49.2016C49.7266 49.2593 49.6888 49.3513 49.6826 49.4117C49.674 49.4945 49.6733 49.6207 49.6553 49.682L49.4818 50.2734C49.3929 50.5756 49.3095 50.8791 49.2404 51.1891L49.0881 51.8695L49.0264 52.2469C48.9875 52.4842 48.9434 52.712 48.8709 52.9477L48.742 53.3641L48.5459 54.0773C48.5037 54.23 48.5045 54.4016 48.5553 54.5508C48.7131 54.4438 48.9481 54.3569 49.0975 54.4859C49.2546 54.6224 49.3935 54.4657 49.5092 54.5062L49.5045 54.5039C49.7193 54.5781 49.8119 54.6185 50.0225 54.5461C50.1606 54.4986 50.3929 54.461 50.556 54.4937L51.0662 54.5977C51.2586 54.6365 51.2499 54.4003 51.249 54.2828L51.2404 52.9086C51.2405 52.7818 51.2694 52.691 51.31 52.5219C51.397 52.5408 51.3415 52.5289 51.2646 52.5125C51.2215 52.2078 51.1954 51.9099 51.2006 51.5836L51.2092 51.0398C51.2135 50.7618 51.1954 50.4992 51.2256 50.2203L51.3029 49.5055C51.3107 49.4348 51.2613 49.2846 51.2646 49.2172C51.3234 48.2398 51.1305 48.6394 51.3006 47.5766C51.3265 47.4168 51.3369 47.3044 51.3248 47.1516C51.3119 46.9832 51.3817 46.7761 51.3826 46.6078L51.3842 46.1539L51.3912 45.7203L51.3998 45.4336C51.4033 45.3248 51.4419 45.1884 51.4428 45.1055L51.4475 44.8617C51.4509 44.6572 51.4764 44.5002 51.3935 44.3086C51.3306 44.1637 51.4372 43.9489 51.4529 43.8047L51.5076 43.2937L51.5318 43.0352C51.556 42.7744 51.5878 42.5342 51.6068 42.2734ZM16.767 44.1461C16.5883 44.1668 16.4716 44.2164 16.324 44.3398C16.2023 44.4414 16.0096 44.3554 15.8568 44.3477C15.5115 44.3306 14.9771 44.6097 14.2193 44.6633C13.2135 44.7349 13.6147 44.9305 12.9076 45.0125C12.6514 45.3535 12.7478 45.7742 12.7771 46.1531C12.8487 47.0983 12.6932 47.9589 12.6975 48.8687C12.6992 49.2918 12.6079 50.4798 12.4818 50.8719C12.3826 51.18 12.3361 51.4686 12.4482 51.7914C12.1089 52.4951 12.4483 52.1561 12.2584 52.6828C12.1972 52.8545 12.162 53.0814 12.149 53.2609C12.2854 53.3671 12.3109 53.5325 12.235 53.6586C12.1767 53.6663 12.1362 53.6694 12.106 53.6805C12.0758 53.6917 12.0558 53.7984 12.0584 53.832L12.06 53.8297L12.0756 54.1039C12.1231 54.1107 12.215 54.0501 12.2357 54.007L12.3975 53.6711C12.6115 53.2248 12.5936 52.9458 12.8889 52.8094C12.9837 52.7143 12.9999 52.4621 13.0646 52.3258C13.182 52.0781 13.2954 51.8374 13.4326 51.6078C13.5603 51.3955 13.6819 51.2046 13.7631 50.9664C13.8201 50.7998 13.9079 50.6814 14.0115 50.5398C14.16 50.3378 14.156 50.0396 14.2553 49.8117L14.6201 48.982C14.7176 48.7611 14.7622 48.5055 14.8881 48.307C15.2075 47.8028 15.4446 47.2879 15.6795 46.7414C15.7235 46.6396 15.8004 46.526 15.86 46.432C16.2321 45.8406 16.1711 45.6647 16.5631 45.1648C16.791 44.8739 16.9842 44.5608 17.0498 44.2C16.9764 44.1275 16.8645 44.1349 16.767 44.1461ZM25.7193 42.4547C25.5407 42.372 25.3093 42.3564 25.2178 42.5703C25.185 42.6463 25.1247 42.7439 25.0678 42.775C25.0186 42.8018 24.8709 42.7382 24.8053 42.7469C24.567 42.778 24.2576 42.8411 23.9865 42.7789C23.6665 42.705 23.8506 43.2348 23.8834 43.7492C23.8887 43.8376 23.985 45.0096 23.9764 44.9656C24.1041 45.595 24.2383 46.2161 24.2771 46.8758L24.2982 47.2414L24.4201 48.4203L24.481 49.1859L24.5123 49.65C24.5313 49.9271 24.5732 50.1553 24.7631 50.3789C24.7717 50.4911 24.7796 50.6557 24.7787 50.7766L24.7717 51.5844C24.7682 51.9985 24.7595 52.5057 25.1092 52.8227C25.142 52.8086 25.2114 52.7111 25.2123 52.6594C25.2123 52.2113 25.2512 51.4778 25.3514 51.0867C25.31 51.0004 25.345 50.9013 25.3545 50.8047L25.4076 50.2344L25.574 48.1648C25.6293 47.4776 25.6661 47.3908 25.6834 46.625L25.7076 45.5492L25.7701 45.2281L25.8412 43.9469L25.8756 43.5031C25.8972 43.2225 25.8398 43.0478 25.8467 42.6523C25.8468 42.6065 25.8706 42.5247 25.8404 42.5109L25.7193 42.4547ZM38.7482 44.3234C39.1808 44.1792 39.6508 44.1804 40.1006 44.2797L40.8967 44.4555C41.1339 44.5083 41.2978 44.7657 41.4842 44.8891C41.7414 45.06 41.843 45.2565 41.956 45.5328C42.1313 45.9593 42.2003 46.2127 42.0717 46.7281C41.9388 47.2579 42.1198 46.9094 42.0412 47.5016C41.9765 47.9856 42.0249 48.2067 41.8568 48.5156C41.7515 48.7073 41.8247 48.9971 41.7185 49.1922L41.1881 50.1703C40.9041 50.6951 40.9046 50.6047 40.3279 51.0812C40.1596 51.2202 39.9135 51.3856 39.7193 51.4469L38.924 51.6969C38.9042 51.7467 38.8842 51.765 38.867 51.7547C38.8117 51.7106 38.6988 51.6023 38.6435 51.6273L38.642 51.625C38.5669 51.6587 38.4403 51.7399 38.3514 51.7969C38.2789 51.7727 37.6667 51.3805 37.7412 51.2695C37.6092 51.2126 37.4257 51.1851 37.2506 51.1773L37.2389 51.068C37.0206 51.0782 36.9945 50.8981 36.9264 50.7453C36.4162 50.4293 36.8174 50.4648 36.5154 50.243L36.5514 50.1734C36.5617 50.1536 36.5084 50.1348 36.4756 50.1141L36.4076 50.0711C36.3895 50.0599 36.4554 50.0211 36.485 49.9969C36.4296 49.9804 36.3221 49.9401 36.3178 49.8875L36.299 49.6539C36.2878 49.5149 36.2368 49.3496 36.242 49.2141C36.2463 49.1185 36.2351 49.053 36.2334 48.9867C36.2222 48.6388 36.2626 48.3079 36.3006 47.9695L36.3459 47.5633C36.3554 47.4813 36.3794 47.3677 36.3967 47.2789L36.481 46.857C36.5295 46.6142 36.7179 45.9867 36.8154 45.7398C37.1169 44.9777 38.0145 44.5686 38.7482 44.3234ZM39.1365 46.2914C39.1141 46.3277 39.0813 46.3706 39.0537 46.3836L38.756 46.5242C38.6197 46.589 38.6011 46.6813 38.5303 46.8039C38.2748 47.2474 38.0216 47.4719 38.1396 47.8516C38.0602 48.0968 38.0293 48.4806 38.0967 48.7586C38.1218 48.8621 38.2001 48.9435 38.2545 49.0539C38.3374 49.2215 38.4893 49.5994 38.781 49.482L39.5975 49.1539H39.5967C39.6778 49.1211 39.8235 48.9953 39.8701 48.9297C39.9927 48.7562 39.9848 48.5048 40.0029 48.2898L40.0514 47.7156C40.2888 47.3513 40.1045 47.2014 39.9154 46.7102C39.9062 46.6878 39.8331 46.668 39.8107 46.6508L39.5787 46.4734C39.5541 46.5099 39.5909 46.4532 39.6193 46.4102L39.1365 46.2914ZM12.2873 48.4109C12.2528 48.3574 12.1258 48.36 12.1232 48.4109C12.1344 48.4604 12.2865 48.4571 12.2873 48.4109ZM18.8912 29.5617C18.8558 29.5548 18.7743 29.5905 18.7467 29.6164C18.3067 30.0399 18.3132 29.7172 18.0475 30.1312L17.7928 30.2641C17.7892 30.4692 17.6451 30.4622 17.5217 30.532C16.9527 30.8541 15.895 31.9267 15.4115 32.4344C14.2538 33.6482 13.8235 33.4122 13.5826 33.7023C12.9247 34.4967 12.8765 35.0695 12.867 36.1211L12.8389 39.268C12.8345 39.7178 12.8725 40.1315 12.7404 40.5805C12.68 40.786 12.7021 40.9976 12.7107 41.2117C12.7254 41.5914 12.8735 41.5098 12.8217 41.5875L12.7318 41.7234C13.1618 41.9763 14.258 41.8945 14.7631 41.8039L16.1482 41.5547C16.32 41.5236 16.5262 41.5648 16.7006 41.5234L17.5435 41.3195L17.9115 41.2328C18.4657 41.1025 18.9915 41.0249 19.5646 40.9687C19.9747 40.9282 20.3701 40.8068 20.7732 40.7352L21.456 40.6133L22.974 40.2789C23.3884 40.1874 23.7933 40.1804 24.2068 40.132L25.3123 40.0039C26.0167 39.9219 25.5982 39.6314 26.1904 39.6711C26.446 39.6884 26.8303 39.7033 27.0357 39.7016C27.073 39.701 27.1616 39.5706 27.1779 39.6008L27.2568 39.7469C27.2904 39.8098 27.3607 39.9137 27.4193 39.9219C27.4703 39.9288 27.5858 39.8412 27.61 39.7937C27.628 39.628 27.4815 39.4467 27.3693 39.325L27.2459 39.1906L26.906 38.8164C26.6911 38.5798 26.3747 38.3112 26.2443 38.1445L25.9842 37.8086C25.8486 37.6351 25.4826 37.2071 25.3029 37.168C25.3063 37.037 25.236 36.9362 25.1326 36.8422L24.8209 36.5594C24.7492 36.4938 24.658 36.4203 24.5959 36.3383L24.0998 35.6758C24.0385 35.5929 23.9395 35.5251 23.8834 35.4414C23.7651 35.2687 23.6443 35.1322 23.4803 34.9992C23.3499 34.8939 23.2558 34.7418 23.135 34.6141L22.9068 34.3734C22.7264 34.1826 22.5832 33.9829 22.3967 33.793C22.2206 33.6134 22.0779 33.3889 21.8889 33.2266C21.7293 33.0894 21.6368 32.9542 21.5084 32.793L21.0818 32.2594L20.8396 31.8945C20.6791 31.6529 20.489 31.4477 20.2818 31.2414L19.8428 30.8023C19.4335 30.394 19.5586 30.1857 19.2521 29.9578C18.8499 29.66 19.0533 29.5954 18.8912 29.5617ZM48.931 38.2289C48.7602 38.2462 48.5967 38.29 48.4232 38.2469C48.2498 38.2038 48.0735 38.2162 47.9303 38.2922C47.7697 38.6885 47.9037 39.0318 47.7639 39.2555C47.6475 39.4418 47.6404 39.6264 47.574 39.8352C47.5421 39.937 47.448 40.0967 47.3935 40.2133L47.1451 40.7469L46.8303 41.4344L47.3131 41.4977C47.4391 41.5141 47.5972 41.512 47.7396 41.5008H47.742L48.0584 41.4758L48.4881 41.4625C48.5346 41.4599 48.6278 41.3775 48.6685 41.3961L48.8225 41.4672C49.3103 41.0113 49.0685 40.6547 49.4217 40.5148L49.3045 40.3195L49.392 39.6477L49.4498 39.1203C49.4662 38.9709 49.3667 38.7572 49.5256 38.6406C49.5618 38.6148 49.6408 38.6 49.6592 38.5656C49.6738 38.5381 49.6645 38.4395 49.649 38.4125L49.5115 38.1687L48.931 38.2289ZM28.6365 31.6695C28.6158 31.8541 28.638 32.0155 28.6725 32.2078C28.6906 32.3097 28.4902 32.3367 28.4271 32.3859C28.2036 32.5586 27.9736 32.7412 27.731 32.8914C27.2227 33.2056 26.7261 33.6473 26.4404 34.1625L26.5592 34.4602C26.5742 34.4965 26.6423 34.5644 26.6639 34.5937C26.8529 34.8502 27.0686 35.0666 27.2818 35.3023L27.9506 36.0406L28.4467 36.6695C28.5148 36.7558 28.5968 36.8516 28.6701 36.9266L29.4021 37.6758C29.4961 37.7715 29.6028 37.8503 29.6693 37.9812C29.8437 38.3266 30.0496 38.6222 30.2896 38.9305C30.3388 38.9943 30.3879 39.2028 30.5068 39.1852C30.9782 39.1144 31.0995 38.7768 31.3576 38.8328C31.5562 38.876 31.7263 38.868 31.9162 38.7773L32.2334 38.6258C32.5519 38.6456 32.8153 38.6141 33.0803 38.4492C33.4911 38.194 33.7877 38.5766 34.2029 38.2055L34.0357 37.9648C33.9735 37.7458 33.8492 37.6139 33.6818 37.4664L33.0334 36.8945C32.9332 36.6226 32.733 36.4462 32.5646 36.2062L32.2732 35.7883C32.2017 35.6857 32.1021 35.6333 32.0287 35.5437L31.7685 35.2305L31.367 34.7523C31.2807 34.6497 31.1546 34.5574 31.0873 34.4383C30.9785 34.2466 30.7576 34.1557 30.6428 33.9891L30.2334 33.3953C30.1704 33.3038 30.1091 33.2382 30.0271 33.157C29.9106 33.0431 29.8175 32.8356 29.6975 32.7328C29.2089 32.511 29.0671 31.6457 28.6365 31.6695ZM13.2764 2.83281C13.2401 2.83818 13.2074 2.97637 13.2428 2.98672L13.381 3.02656C13.444 3.04475 13.5354 3.10548 13.5365 3.14687L13.2451 3.33594L12.9615 3.52344L12.9654 3.67891C12.9663 3.71344 12.8688 3.76094 12.8576 3.79375C12.7229 4.19348 12.8551 4.08592 12.8482 4.62812C12.8456 4.8525 12.8235 5.08129 12.8459 5.29531L12.9162 5.99766C12.9274 6.1099 12.919 6.23735 12.9146 6.35391L12.899 6.73047C12.8818 7.15351 12.9101 7.73385 12.9576 8.11797C12.9642 8.16976 13.1162 8.26075 13.0865 8.29531C13.0606 8.32466 12.9564 8.39137 12.9451 8.43281C12.9002 8.60022 12.9284 8.90042 12.9146 9.09297C12.8758 9.62568 12.8553 10.119 12.8795 10.65L12.9201 11.5367L12.9139 12.4266V13.9711L12.9115 15.7578L12.9381 18.8875C12.9441 19.6067 12.8365 20.3052 12.8943 21.0312C12.9202 21.3542 12.8889 21.6679 12.8967 21.9891L12.9357 23.6883C12.9625 24.8564 13.0319 25.991 12.9982 27.1539C12.9931 27.3188 13.0165 27.4874 12.9889 27.6453C12.9657 27.7765 13.0673 27.9257 13.0553 28.0172L12.981 28.5547L12.9443 29.1047L12.9014 29.6289C12.897 29.6833 12.859 29.8118 12.8779 29.8594L13.0092 30.182C13.0773 30.3502 13.1269 30.5012 12.9631 30.6711C12.7628 30.8791 12.6232 31.252 12.7318 31.543C13.0159 31.6292 13.3249 31.3749 13.4389 31.1125C13.4717 31.0365 13.5477 30.9095 13.6029 30.875L14.0068 30.8094C14.2338 30.7723 14.3685 30.1902 14.4342 30.118C14.5706 29.9669 14.7836 29.7507 14.9623 29.6203L15.524 29.2109L16.0912 28.7617C16.459 28.4708 16.9328 27.8619 17.2514 27.4742C17.3377 27.3689 17.4042 27.3074 17.5225 27.2289C17.7331 27.0891 17.9126 26.892 18.1154 26.7383C18.4314 26.4991 18.7565 26.2961 19.0146 25.9836L19.1248 25.7516C19.4468 25.9847 19.5864 25.6445 19.6537 25.9734C19.797 26.1487 20.0171 26.2655 20.2217 26.3734C20.4926 26.9289 20.6193 26.6792 20.71 26.9617C20.8144 27.2881 20.8503 27.4277 21.124 27.7117L21.4271 28.0258C21.5765 28.1811 21.7395 28.3223 21.8889 28.4828L22.8771 29.5477C23.0248 29.7074 23.1412 29.8927 23.2725 30.0766C23.3916 30.244 23.3307 30.344 23.6248 30.7219L24.0506 31.2687L24.4209 31.7555C25.0892 31.5828 24.7839 31.7572 25.3373 31.4516C25.5505 31.3342 25.7576 31.1788 25.9303 31.0148L26.5107 30.4641L27.1771 29.8383C27.6356 29.4074 28.1776 28.9234 28.649 28.6281C28.7017 28.5953 28.7925 28.4988 28.8279 28.5125C29.3071 28.699 29.3177 28.8729 29.7779 28.8703C30.0896 29.3347 30.4359 29.768 30.7709 30.2039C31.0523 30.5699 31.3282 30.8989 31.6553 31.2234C31.7648 31.3321 31.8797 31.4568 31.9764 31.575L32.1795 31.8227L32.674 32.4031L32.899 32.6758C33.1088 32.9313 33.2986 33.1733 33.492 33.4461L33.8404 33.9398C34.0071 34.1755 34.1518 34.4244 34.3529 34.6359L35.6623 36.0203C35.9662 36.3415 36.2288 36.6782 36.5076 37.0227C36.6872 37.2445 36.8585 37.4696 37.1529 37.5594L37.6154 37.3922L38.0818 37.3789C38.3244 37.372 38.5648 37.2462 38.81 37.2289C39.1845 37.2022 39.5418 37.1823 39.9154 37.1133C40.2228 37.0563 40.5234 37.0447 40.8334 37.0102L41.6857 36.9164L42.5217 36.8281C42.6294 36.8169 42.7199 36.7995 42.8225 36.7633C43.1143 36.6588 43.4142 36.606 43.7225 36.543L45.0365 36.275C45.2194 36.2379 45.3928 36.2265 45.574 36.1773L46.6764 35.8742C46.9258 35.8062 47.4282 35.9153 47.5779 35.825C47.5961 35.8138 47.5961 35.7587 47.5771 35.7492L47.4842 35.7047C47.3694 35.6512 47.251 35.5796 47.1396 35.5398C47.0085 35.4924 46.9357 35.44 46.8537 35.3312C46.6396 35.0463 46.289 35.5261 45.8935 35.4656C45.8392 35.5837 45.786 35.6813 45.7248 35.7633L45.6662 35.7008L45.6889 35.6266C45.726 35.5065 45.6407 35.7215 45.3178 35.6594C45.2166 35.6404 44.5301 35.7434 44.3709 35.7711L43.667 35.8922C43.5375 35.9146 43.3639 35.9396 43.2568 35.9422C43.2292 35.7497 43.1659 35.7176 43.0701 35.6062C42.8724 35.3753 42.5536 34.4398 42.5381 34.1844C42.5243 33.9616 42.852 33.8725 43.0014 33.8906C43.2863 33.926 43.4697 33.7764 43.7037 33.7125C43.9307 33.6513 44.2173 33.743 44.4279 33.6273L44.4935 33.5914C44.5027 33.5861 44.4698 33.5579 44.4592 33.5523L44.0764 33.3656L44.1685 33.2305C43.72 33.1338 43.7335 32.9123 43.6646 32.918L43.4795 32.9344C43.1671 32.962 42.8159 33.0962 42.506 33.1852L42.1365 33.1727C42.0994 33.1709 42.0057 33.1382 41.9764 33.1312C41.8607 33.1571 41.694 33.1432 41.5654 33.1242C41.1711 33.3641 41.4298 33.1239 40.6685 33.2922C39.9477 33.4519 40.0917 33.2734 39.4365 33.4219C39.2215 33.4702 39.022 33.4747 38.7717 33.4617C38.7579 33.347 38.7715 33.2279 38.7896 33.0898C38.8147 32.9042 38.7189 32.6941 38.7068 32.5102L38.6318 31.3648C38.6284 31.3165 38.6338 31.2064 38.6709 31.1883C38.8357 31.1101 39.0232 31.3254 39.1889 31.3125L39.6779 31.2727L40.1717 31.2539C40.6828 31.234 41.1384 31.3113 41.5045 31.2086C41.5356 31.1998 41.6276 31.1384 41.6193 31.1125L41.5865 31.0109C41.7626 30.884 41.2847 30.9336 41.2787 30.7609C41.2718 30.5667 41.2303 30.4376 41.024 30.3711C40.9178 30.3374 40.7322 30.2888 40.6053 30.2836L39.2756 30.225C38.926 30.2095 38.5868 30.2283 38.2303 30.2344L37.7029 30.243C37.5001 30.2464 37.28 30.3749 37.1021 30.1992C36.9356 30.0352 36.6815 30.0599 36.4623 30.0289L35.2912 29.8648C35.2567 29.5462 35.2566 29.1324 35.3162 28.8164C35.424 28.2467 35.2223 27.9453 35.3553 27.3867L35.781 27.6625C36.4353 27.8411 37.0871 27.7874 37.756 27.7312C38.4364 27.6734 39.2476 28.1647 40.1162 27.7312C40.0281 27.5974 40.0001 27.4522 39.9639 27.2812L39.8873 26.9242C39.7604 26.869 39.6152 26.811 39.5193 26.7031L39.1404 26.6219C38.9319 26.5771 38.2839 26.6065 38.306 26.6109L37.4287 26.4867C37.2873 26.4669 37.1882 26.4569 37.0623 26.4328L36.3396 26.2953L36.0271 26.2617C35.8382 26.241 35.6817 26.2017 35.4842 26.2094C35.1933 26.2206 34.8684 26.1591 34.5896 26.2375C34.4031 26.2902 34.2999 26.3153 34.167 26.1297C34.0444 25.9596 33.8613 25.7383 33.7975 25.5242C33.7269 25.2877 33.8473 25.0129 33.849 24.7773L33.856 23.5312C34.2661 23.4976 34.3363 23.8301 34.7256 23.8C35.0312 23.7767 35.2799 23.8515 35.5639 23.943C35.897 24.05 36.2658 23.9978 36.6162 24.0297L37.3529 24.0984C37.694 24.1304 38.8087 24.5936 39.5201 24.4805C39.5616 24.3165 39.6357 24.1138 39.6271 23.9352L39.61 23.5742L39.7928 23.5289L39.606 23.3211C39.3652 23.2952 39.0766 23.0581 39.0904 23.0555C38.9255 23.0848 38.9055 23.2328 38.8623 23.1758L38.7771 23.0641C38.6261 23.115 38.4358 23.1526 38.2709 23.1336L37.9357 23.0961C37.6983 23.0693 37.4877 23.0264 37.2451 23.0359C37.0906 23.042 36.4369 22.9623 36.2318 22.9234L35.6467 22.8109C35.4054 22.7652 34.6408 22.7609 34.356 22.7617C34.2128 22.7617 34.0567 22.7084 33.9014 22.7773C33.866 22.7929 33.755 22.8125 33.7443 22.7773L33.6998 22.6328L33.6154 22.3648C33.6957 22.1439 33.6286 21.9045 33.6631 21.6836L33.7935 20.8516C33.8825 20.2872 33.9964 20.332 34.2951 19.8383C34.504 19.9919 34.7198 20.0989 34.9701 20.1516L35.5404 20.2727C35.7959 20.327 36.0752 20.3214 36.3428 20.368L38.1865 20.6914C38.6846 20.7786 39.2817 21.0131 39.6529 20.8414C39.7557 20.8155 39.9761 20.8252 40.0857 20.8148C40.0667 20.593 40.1693 20.2861 40.2928 20.1445C40.2814 19.8416 39.9251 19.7631 39.692 19.7242L39.1248 19.6305C39.029 19.6149 38.7138 19.4199 38.1045 19.3508C37.7169 19.3068 37.299 19.2354 36.9209 19.1672C36.889 19.1612 36.8009 19.1043 36.7662 19.093L36.06 18.8687L35.6029 18.7172C35.5553 18.7017 35.4363 18.7259 35.381 18.7328C35.2802 18.5896 35.3173 18.4068 35.3475 18.2359C35.527 17.2233 35.683 17.3844 35.9342 16.4953C36.0956 16.4392 36.2499 16.5711 36.3389 16.7023C36.4408 16.8525 36.6833 16.8434 36.8404 16.8883C37.1132 16.9667 37.3885 16.9243 37.6639 16.9562L38.8889 17.0977L40.2795 17.5094C40.4538 17.5611 40.6505 17.5277 40.8084 17.6062C40.8446 17.6243 40.9392 17.6324 40.9654 17.6102C41.0621 17.523 41.0623 17.1821 41.0537 17.1078L41.006 16.7328L41.3131 16.6094C41.2363 16.4964 41.1522 16.4556 41.0185 16.4383L40.8568 16.2734C40.6876 16.2346 40.4464 16.2922 40.2764 16.2672L39.2412 16.1133C39.0643 16.0874 38.8983 16.0914 38.7162 16.0672L37.6701 15.9305C37.5648 15.9167 37.3831 16.0024 37.2881 15.9852L36.9131 15.9172C36.8148 15.7705 36.881 15.5465 36.8975 15.3695L36.9482 14.8086C36.9596 14.6879 37.0369 14.5747 37.124 14.5031L37.2037 13.6297C37.8521 13.7998 37.8082 13.8848 38.4998 13.9953C38.9132 14.0618 39.3093 14.0655 39.7279 14.075C40.1242 14.0836 40.4888 14.0846 40.8928 14.0492C41.1043 14.0311 41.3559 14.095 41.5303 13.918C41.2989 13.4949 41.5715 13.3932 41.1303 13.1859C40.9239 13.0893 40.7582 13.0801 40.5381 13.1164C40.4078 13.138 40.313 13.1367 40.1818 13.2281C40.1145 13.2756 39.9656 13.1625 39.8896 13.1539L38.9514 13.0477C38.7856 13.0287 38.5548 13.1501 38.4037 13.1242L38.0201 13.0594L37.9803 12.7344C37.7869 12.4089 37.6796 12.0833 37.7521 11.7086L37.8607 11.143C37.8676 11.105 37.9629 11.0699 37.9896 11.0906C38.3453 11.3666 38.846 11.3032 39.3139 11.2937C39.6151 11.2877 39.8775 11.2601 40.1693 11.2117C40.4153 11.1712 40.9547 11.0966 41.1646 11.1992C41.2285 11.1518 41.1635 11.0024 41.1092 10.9289C40.7284 10.4169 40.29 10.3895 39.6623 10.4344C39.582 10.4403 39.4473 10.4263 39.3826 10.4461C39.2895 10.4745 39.2179 10.4889 39.1334 10.4906L38.5435 10.5047C38.5823 9.77714 38.3921 10.0859 38.4154 9.25625C38.4214 9.05254 38.3957 8.82623 38.3896 8.63203L38.6873 8.65781C38.7494 8.66262 38.8188 8.54025 38.874 8.48594C38.912 8.44882 39.0565 8.48265 39.1092 8.46797L39.5045 8.35625C39.5787 8.40287 39.663 8.4495 39.7131 8.42187C39.9054 8.31381 39.7784 7.8556 39.5678 7.63203L39.1201 7.15937C38.9656 6.99619 38.896 6.75495 38.7959 6.55469C38.745 6.45278 38.6749 6.26548 38.7975 6.15156C39.1316 5.84164 39.5462 5.65119 39.9873 5.45781L40.3318 5.85234L40.3178 5.84531C40.5422 6.10254 40.7453 6.34065 40.9826 6.5625C41.2753 6.83533 40.8571 6.85979 41.2732 7.32344C41.4981 7.57445 41.2568 7.78171 41.5014 7.71641L41.7693 7.64531C42.0922 7.55983 42.36 7.38032 42.6389 7.20937C43.2007 6.86499 42.9058 6.68036 43.274 6.55C43.3041 6.5397 43.3836 6.53002 43.3904 6.55625L43.4162 6.66016C43.4482 6.78965 43.5092 6.89187 43.6154 6.97734C44.0744 7.34509 43.6906 7.70218 44.2146 7.87656C44.2828 8.06213 44.4198 8.35995 44.2232 8.46797C44.111 8.52927 43.9194 8.58068 43.8287 8.66875C43.6837 8.80938 43.5103 8.8922 43.367 9.01641C43.1927 9.16658 43.1215 9.44875 42.9084 9.60937C42.7892 9.69917 42.7167 9.97929 42.7857 10.0984C42.9049 10.3028 43.1336 10.246 43.2881 10.1484C43.4054 10.0743 43.6235 10.1593 43.7435 10.1164C44.1286 9.97567 44.4605 9.77276 44.824 9.59922C45.0735 9.48007 45.3171 9.38128 45.5537 9.24141C45.6297 9.19618 45.7547 8.97282 45.8693 9.13125C46.4046 9.87118 46.2521 9.75583 46.6381 10.4828C46.7166 10.6311 46.8562 10.7863 46.8693 10.9492C46.8797 11.0761 46.7061 11.1447 46.6154 11.1844C46.4057 11.2751 46.2294 11.4737 46.0248 11.5367C45.9015 11.5747 45.7894 11.6007 45.6764 11.643L45.174 11.8328C44.8347 11.9615 44.5085 12.1471 44.2771 12.4242C44.018 12.3536 43.4521 12.4832 43.4771 12.8086C43.4875 12.9449 43.5565 13.0441 43.6928 13.1062L43.749 13.3992L43.8631 13.5062C43.9318 13.572 43.6707 13.8229 43.7482 13.9766C43.9502 13.8229 44.0782 13.7649 44.281 13.6984L44.86 13.5102L45.549 13.2812L47.3592 12.6734C47.7352 12.5474 47.9267 12.3503 47.9881 12.5406C48.0493 12.7313 48.1376 12.9274 48.2256 13.1078C48.3974 13.4575 48.47 13.8299 48.5701 14.2141C48.6374 14.4712 48.9969 14.5283 49.0084 14.7922C49.0144 14.9345 48.8615 14.996 48.7545 15.0125C48.198 15.1005 47.7886 15.3549 47.5959 15.3578C47.3344 15.3613 47.2659 15.4766 47.0787 15.5836C46.8588 15.7086 43.9181 16.249 43.9154 16.2469L43.4678 16.5937C43.4307 16.6222 43.3551 16.6222 43.335 16.6453C43.3151 16.6686 43.3405 16.742 43.356 16.7937C43.3819 16.8792 43.3539 17.0035 43.3607 17.0734C43.3737 17.1986 43.4021 17.3001 43.3373 17.4227C43.314 17.4667 43.2814 17.5163 43.3021 17.5344C43.3703 17.5973 43.6734 17.5268 43.7842 17.5L44.231 17.3898C44.4261 17.3415 44.5609 17.2527 44.7732 17.2492C45.1349 17.2431 45.4863 17.1122 45.842 17.0906L46.5225 17.0492L46.6834 16.8758L47.7607 16.6203L48.7709 16.3359C48.8084 16.3257 48.9174 16.329 48.9295 16.3617L48.9803 16.4961C49.0675 16.7283 49.207 16.9571 49.2709 17.2023C49.3555 17.5269 49.4268 17.8076 49.6029 18.1055C49.6961 18.2627 49.7229 18.6968 49.4795 18.6727C49.1868 18.6433 48.753 18.6066 48.481 18.7422C48.3705 18.7965 48.1971 18.8003 48.0693 18.8383C47.509 19.0066 46.9847 19.1408 46.3959 19.2047L46.1357 19.3297C45.5168 19.3357 44.9493 19.4555 44.3623 19.6117C44.2103 19.6523 44.0622 19.6656 43.9232 19.7398C43.2777 20.085 43.4488 19.8335 43.1209 20.0656C42.728 20.3445 43.0002 20.2867 42.4623 20.6484C42.4399 20.7157 42.4105 20.7929 42.3795 20.8352L42.3162 20.9242C42.2817 20.9717 42.6901 21.2069 43.1865 20.8227C43.4403 20.7907 43.7397 20.7673 44.0029 20.7164L44.6553 20.5914C44.9687 20.531 45.2791 20.4719 45.5865 20.3898L46.0381 20.2695C46.1545 20.2384 46.2925 20.1686 46.4193 20.1453C46.7965 20.0771 47.1334 19.96 47.4951 19.8633L48.3607 19.6328C48.4867 19.599 48.6302 19.4245 48.7795 19.4789C48.9433 19.5387 48.9047 19.8916 48.9529 20.1539C49.1092 21.0035 49.2552 20.6508 49.01 21.25C48.9702 21.3467 48.9397 21.4626 48.9881 21.5516C49.0364 21.6407 49.0656 21.8764 48.9396 21.8945C48.3285 21.9817 47.7632 22.1092 47.1693 22.2594L46.4037 22.4523L46.1568 22.5242L45.8443 22.6062C45.727 22.6365 45.6225 22.6918 45.4982 22.7289L44.9607 22.8898C44.8338 22.9278 44.7358 22.968 44.6123 22.9922L43.9803 23.1172C43.8862 23.1362 43.7636 23.1657 43.6756 23.1977L43.3178 23.3305C43.2021 23.3736 43.1051 23.3703 43.0334 23.2875C42.9617 23.2046 42.8281 23.3496 42.8021 23.4602C42.7866 23.5249 42.5826 23.4983 42.5248 23.5406L42.0068 23.9258C41.9696 23.9533 41.8105 23.9422 41.8217 23.9836C41.8312 24.0191 41.8569 24.1026 41.8725 24.1328L41.9943 24.3742C42.9104 24.6427 42.6693 24.1892 43.0389 24.2703C43.2493 24.3159 43.3951 24.217 43.5771 24.1445C43.6799 24.1031 43.8571 24.0965 43.9607 24.043C44.2923 23.8712 44.6256 23.772 44.9865 23.6883C45.6978 23.5225 45.8032 23.5493 46.524 23.318L47.0115 23.1617L47.4615 23.0141C47.6463 22.9528 47.7944 22.8926 48.0068 22.7977C48.1061 22.9168 48.2826 23.1157 48.3646 23.2547L48.9279 24.7359L48.7467 25.1203C48.6422 25.3413 48.5348 25.3785 48.2982 25.3828C48.1236 25.3863 47.1396 25.5136 47.0248 25.6172C46.9591 25.6482 46.7963 25.6536 46.7264 25.682L46.2646 25.8672C45.7435 26.0768 45.798 25.959 45.6029 26.1359C45.5054 26.224 45.2867 26.2243 45.1451 26.2648C44.8232 26.358 44.521 26.4301 44.1904 26.45L43.2857 26.5039C42.9119 26.5264 42.6131 26.6361 42.3834 26.9383C42.3213 27.0195 42.2839 27.246 42.3295 27.3367C42.3701 27.4179 42.4068 27.5068 42.4318 27.6C42.5458 27.6517 42.7365 27.6318 42.885 27.6094C43.1248 27.5732 43.3931 27.5943 43.6037 27.5211L44.0935 27.3492C44.4009 27.2413 44.7284 27.1726 45.0521 27.1156C45.2454 27.082 45.3654 27.0368 45.5303 26.9289C45.6822 26.8297 45.9146 26.8005 46.0881 26.7211C46.4023 26.5778 46.7296 26.4727 47.0568 26.3734C47.1293 26.351 47.2559 26.2349 47.3232 26.257C47.5043 26.3191 47.4141 26.5222 47.4389 26.6328C47.5839 27.2759 47.9814 27.5646 48.1412 28.2016C48.1732 28.3285 48.1851 28.4359 48.0935 28.5187C48.021 28.5843 47.9069 28.5875 47.799 28.5297C47.7129 28.4845 47.6354 28.5979 47.5725 28.6094L47.1842 28.6797C47.0591 28.7022 46.914 28.7476 46.8459 28.7977L46.867 28.8805C46.305 28.9124 46.5059 29.0091 45.9967 29.1352C45.7386 29.4873 45.6588 29.2336 45.4396 29.3836C45.1452 29.5856 44.8031 29.6679 44.4396 29.6852C44.2084 29.6956 43.9607 29.842 43.7295 29.8766L43.6084 29.8953C43.529 29.9074 43.7607 30.3981 44.0818 30.393C44.1956 30.3913 44.3463 30.4113 44.4412 30.3898L45.1295 30.2367C45.2374 30.2126 45.4628 30.287 45.5475 30.2172L45.8225 29.993C45.8294 29.9351 45.8431 29.8486 45.8803 29.8391C46.1673 29.7641 45.8525 29.9055 46.1873 29.8055L47.0826 29.5367C47.1396 29.5194 47.2313 29.5903 47.2451 29.643C47.3133 29.9054 47.4661 30.0747 47.6318 30.2672C47.8071 30.4718 47.9633 30.6265 48.2154 30.7344C48.2913 30.7663 48.3483 30.9274 48.3303 31C48.3139 31.0673 48.1948 31.1792 48.124 31.1836C47.8901 31.1965 47.7605 31.2894 47.5732 31.393C47.4498 31.462 47.3515 31.5134 47.2514 31.6023C47.0001 31.8268 46.6455 31.9095 46.3623 32.0805C46.2967 32.1202 46.1998 32.1994 46.1248 32.2555C46.0569 32.3066 46.1012 32.5202 46.1529 32.5945C46.3299 32.6645 46.5753 32.6567 46.7428 32.5781L47.8357 32.0656C48.0601 31.9603 48.2404 31.8127 48.2975 31.5461C48.3933 31.515 48.5916 31.5099 48.6693 31.5625C48.8533 31.9475 49.3059 32.3144 49.6693 32.5328C49.7263 32.7159 49.8049 33.0865 49.7185 33.2289C49.6752 33.2996 49.5438 33.3445 49.4412 33.3945L49.1139 33.5523C49.0621 33.5777 49.0077 33.6917 48.9646 33.7719L49.4748 33.8953C49.5991 34.1733 49.8484 34.3604 50.167 34.3656C50.2282 34.4225 50.2831 34.4807 50.3451 34.5195L50.8654 34.8398C50.8846 34.8509 51.0351 34.8453 50.9998 34.743C50.9575 34.6203 51.0024 34.3895 51.0982 34.2695C51.2276 34.1073 51.2419 33.9772 51.2514 33.7719C51.2669 33.4386 51.2753 33.1121 51.2615 32.7719L51.2357 32.1406L51.2154 31.4836L51.2232 30.9187L51.2717 29.3758C51.2872 28.8631 51.2745 28.3712 51.2779 27.8594L51.2818 27.0219L51.3209 25.093L51.3443 23.7633C51.3521 23.3126 51.3307 22.9004 51.2771 22.4523C51.2237 22.0044 51.2907 21.5581 51.3123 21.1102L51.3779 19.7594C51.4107 19.0895 51.4558 18.4325 51.4498 17.7617C51.4463 17.3767 51.4105 17.0045 51.4295 16.6117L51.4982 15.2008C51.5164 14.8192 51.5361 14.4599 51.524 14.0766L51.4834 12.75L51.5701 10.9117C51.6202 9.83593 51.5708 8.78039 51.6295 7.70547C51.6433 7.44411 51.6406 7.19565 51.6389 6.93516L51.6326 6.00078L51.6779 5.64297C51.6934 5.51951 51.6975 5.33571 51.6553 5.23906C51.5293 4.95513 51.6897 4.70398 51.6467 4.42266C51.6087 4.1766 51.4402 3.80844 51.5662 3.55547C51.6715 3.34395 51.2401 3.63798 50.7014 3.45156C50.4432 3.36177 50.1847 3.50534 49.9162 3.48203L49.2928 3.42891C49.2281 3.42349 49.141 3.26134 49.0514 3.36172C49.0195 3.39704 48.9007 3.44557 48.8701 3.41406L48.7607 3.3C48.583 3.42841 48.382 3.44587 48.1896 3.33984L47.8896 3.38359C47.8517 3.38867 47.8 3.37674 47.7381 3.36641C47.537 3.33361 47.3151 3.34729 47.1037 3.33437C46.717 3.31107 46.3524 3.30713 45.9709 3.32266L45.4928 3.34219L45.0092 3.35625C44.7691 3.36316 44.4033 3.3463 44.1279 3.33594L42.4115 3.26875L41.4482 3.31719L41.1279 3.35312C41.0381 3.35571 40.8646 3.20358 40.7834 3.23984C40.6142 3.31488 40.4957 3.22245 40.3826 3.23281L39.8873 3.27734C39.7233 3.29202 39.5839 3.28541 39.431 3.34844C38.9903 3.53122 39.1151 3.28134 38.8185 3.28203H38.3896C38.0946 3.28371 37.8409 3.23271 37.5467 3.26719C37.2523 3.30172 37.214 3.27146 37.056 3.25937C36.1626 3.19377 36.4024 3.31245 36.0521 3.3125C35.4642 3.3125 35.3276 3.20359 34.9123 3.23984L34.5178 3.27422C34.2734 3.2958 33.698 3.24145 33.6592 3.24922C33.5566 3.26989 33.4925 3.27896 33.4037 3.28672L32.7521 3.34141C32.4992 3.36213 32.259 3.34634 32.0225 3.34375C31.8748 3.34203 31.6564 3.40102 31.5381 3.36562C31.3982 3.32332 31.3316 3.3222 31.2029 3.31875L30.1068 3.28984C29.9851 3.28639 29.8792 3.30427 29.7506 3.29219C29.5505 3.27241 29.3323 3.31552 29.1373 3.30781C28.7834 3.294 28.449 3.30333 28.0959 3.30937C27.938 3.31196 27.8117 3.28404 27.6443 3.32109C27.5001 3.35304 27.2822 3.24186 27.1389 3.26172C26.9637 3.28672 26.8074 3.28439 26.6451 3.24297C25.9176 3.33788 26.1685 3.22604 25.9193 3.21562C25.1725 3.18454 25.7784 3.10412 24.5904 3.14297L24.1732 3.15625C23.9203 3.16485 23.6291 3.04336 23.3779 3.14609C22.962 3.31606 23.2976 3.0985 22.6553 3.17187C22.5121 3.18822 22.3413 3.16019 22.1826 3.16016C22.0859 3.16016 21.9 3.3099 21.8162 3.23047C21.7299 3.1485 21.6216 3.05976 21.5068 3.12187C21.2479 3.26248 21.0034 3.22044 20.7264 3.22734C20.4492 3.23423 20.0053 3.21725 19.7576 3.16719C19.7135 3.15867 19.6079 3.17207 19.5639 3.16953L18.6482 3.11562C18.5136 3.10778 18.3339 3.04355 18.2131 3.05391C18.0025 3.07201 17.8462 3.06864 17.6451 3.02031C17.5009 2.98581 17.2969 3.03688 17.1381 3.03516L16.1107 3.025L15.5334 3.00859C15.2701 3.00082 15.005 3.02767 14.7451 3.00781C14.5319 2.99141 14.374 3.02293 14.21 3.16797C14.0934 3.1956 13.8798 3.19613 13.7365 3.1875C13.6875 3.01754 13.9111 2.95952 13.8576 2.925C13.7039 2.82399 13.4413 2.80864 13.2764 2.83281ZM21.8771 5.13828C22.2457 5.15809 22.6056 5.09911 22.9732 5.15L24.2256 5.19609C24.5959 5.20988 24.943 5.17773 25.3107 5.21484C26.0168 5.28561 26.1723 5.20106 26.7178 5.48672C26.8913 5.57737 27.14 5.61153 27.3006 5.73672C27.8453 6.15965 27.6761 5.73678 28.5014 6.30391C28.9511 6.61297 29.5464 6.76017 30.0014 7.05625C30.2413 7.2125 30.4816 7.35059 30.706 7.51719L31.2154 7.89609C31.344 7.99189 31.4867 8.10497 31.5264 8.26719C31.5661 8.42931 31.6837 8.49291 31.7881 8.60937C32.0281 8.87874 32.2436 9.1623 32.4646 9.46016C32.5492 9.57319 32.5202 9.82152 32.5779 9.94766C32.7437 10.3085 32.8881 10.6454 32.9951 11.0234L33.2889 12.0562C33.3657 12.3256 33.4358 12.5891 33.4592 12.8687C33.5429 13.8988 33.7129 15.4757 33.4029 16.4617C33.1776 17.1773 32.9842 17.7327 32.606 18.3586L32.1342 19.1414L31.6451 19.9398C31.5337 20.1212 31.3387 20.276 31.1928 20.4461C30.3959 21.3742 30.4138 21.3575 29.2889 21.8781L28.9451 22.0375L28.3678 22.2781L27.6795 22.5633C27.613 22.5909 27.5061 22.6157 27.4139 22.6398L27.4131 22.6367L26.91 22.7648C26.7658 22.802 26.6097 22.8425 26.4732 22.8883C26.3491 22.9306 26.219 23.0309 26.0725 23.0414C24.7765 23.1312 25.5721 23.304 23.9256 23.1961L22.9889 23.1344L22.5201 23.0547C22.4131 23.0366 22.3122 23.0314 22.2139 23.0547C21.6915 22.7352 21.6292 22.8762 20.9256 22.5672L19.8014 22.0734L19.4631 21.8531C19.1704 21.6632 18.9248 21.47 18.6459 21.268L18.1092 20.8789C17.8622 20.7002 17.6779 20.4536 17.456 20.2437C17.2645 20.0625 17.0866 19.8975 16.9373 19.6766C16.8257 19.5114 16.2441 18.7371 16.2334 18.7125L15.8146 17.6602C15.7084 17.3925 15.4102 16.5424 15.3662 16.2859C15.3179 16.0011 15.2898 15.7336 15.2139 15.4617L15.0014 13.3633C14.9565 12.9179 14.9989 12.4863 15.0412 12.0383C15.1232 11.1749 15.5147 10.4023 15.9334 9.64687C16.2045 9.15906 16.512 8.74198 16.8435 8.30078C17.1095 7.94681 17.3407 7.58564 17.6826 7.29297L18.5959 6.51172C18.709 6.41502 18.8828 6.33918 19.0123 6.24766C19.273 6.06294 19.5337 5.91191 19.8107 5.76172L20.41 5.43594C20.6551 5.30298 21.1964 5.10105 21.4451 5.11484L21.8771 5.13828ZM23.7248 7.66484C23.5608 7.58887 23.4257 7.60973 23.2928 7.67187C23.1598 7.73404 22.9396 7.74565 22.8412 7.82422C22.6911 7.94501 22.6303 7.96104 22.4326 7.90234C21.8508 8.22433 21.9199 8.0884 21.331 8.35C21.079 8.46134 20.8363 8.54621 20.6326 8.76719L20.3373 8.81797C20.3113 8.98358 20.1274 8.96792 20.0428 9.05078C19.4557 9.62838 18.942 10.2743 18.531 10.9961C18.3454 11.3224 18.2041 11.6713 18.0764 12.0227C17.9028 12.4975 17.8537 13.0069 17.8045 13.5094C17.7449 14.1258 17.851 14.6934 17.9779 15.2805C18.0003 15.385 17.9148 15.5923 17.9545 15.7227C18.1107 16.2379 18.3285 16.6797 18.5865 17.1406C18.7557 17.4436 18.8685 17.7792 19.0912 18.0391L19.7146 18.7641C19.7983 18.8616 19.9746 18.9523 20.0834 19.0352L20.5318 19.3805C21.586 20.1929 21.9747 20.2273 23.2318 20.5805C23.4053 20.6288 23.5957 20.7221 23.7467 20.5445L23.6451 20.4008H23.6443C23.7976 20.0099 23.4489 19.7254 23.2193 19.507C23.0026 19.3015 22.8003 19.0643 22.6225 18.8234C21.8855 17.825 22.2536 18.4179 21.8014 17.3555C21.677 17.0619 21.6631 16.7315 21.5889 16.425C21.4533 15.8682 21.4458 15.9925 21.3482 15.4141L21.2264 14.693C21.1729 14.3732 21.1852 13.4265 21.2568 13.1141L21.5115 12.0023C21.6825 11.2546 22.0268 10.0816 22.3834 9.40469C22.5794 9.0326 22.9978 8.71649 23.0842 8.52656C23.3517 7.93482 23.5634 8.37872 23.7248 7.66484ZM27.9037 8.6C27.5696 8.49294 27.3802 8.65495 27.1678 8.84922C27.0977 8.91301 26.9243 8.9285 26.8803 9.04844C26.8336 9.17614 26.7102 9.2125 26.5756 9.22891L26.5654 9.46719C26.057 9.37137 25.4474 10.0212 25.1451 10.3727C24.5528 11.0608 24.3479 11.4429 24.1295 12.3141L23.992 12.8617C23.9152 13.1682 23.9541 13.4947 23.9576 13.8055C23.9645 14.3753 24.0037 14.9195 24.1514 15.4867C24.3629 16.2991 24.7292 17.0634 25.2006 17.7602C25.3784 18.0226 25.6094 18.2394 25.8123 18.482C26.382 19.1656 26.5814 18.9838 26.7748 19.2367L26.9662 19.4875L27.5357 19.382V19.3844C27.6773 19.3584 27.8213 19.1638 27.9326 19.0758C28.1597 18.8979 28.331 18.7008 28.5287 18.4953L29.0982 17.9031L29.3459 17.6195C29.5479 17.3882 29.6787 17.1318 29.8185 16.8547L30.2232 16.0531C30.4011 15.7009 30.5434 15.3036 30.5943 14.9047C30.6452 14.5085 30.5947 14.1158 30.599 13.7187C30.6033 13.3891 30.5457 13.0815 30.4982 12.7578C30.4482 12.4159 30.4087 12.0867 30.2826 11.7664L29.9404 10.8961C29.8627 10.6984 29.734 10.5161 29.6037 10.3461C29.3991 10.0802 29.2218 9.83329 29.031 9.54844C28.9836 9.4785 28.8639 9.37121 28.7975 9.3125C28.3396 9.25361 28.5939 8.82186 27.9037 8.6ZM53.0857 14.3836L53.2154 14.3852C53.2369 14.385 53.2338 14.3359 53.2295 14.2773L53.0857 14.3836ZM41.4131 2.74219C41.4348 2.76128 41.5037 2.68767 41.5154 2.67422H41.5162L41.2943 2.63359L41.4131 2.74219ZM27.8623 1.72266C27.8449 1.72925 27.8685 1.78036 27.8771 1.79844C27.8858 1.81657 27.9311 1.79071 27.9389 1.77344C27.9466 1.7561 27.9601 1.69901 27.9412 1.70234C27.9248 1.7058 27.8744 1.71834 27.8623 1.72266ZM34.1162 0.889062H34.317V0.809375H34.1162V0.889062ZM38.2568 0.828906L38.3568 0.889062L38.4209 0.782812L38.3209 0.722656L38.2568 0.828906Z" fill="white"/> 4 + </g> 5 + <defs> 6 + <clipPath id="clip0_1_128"> 7 + <rect width="64" height="64" fill="black"/> 8 + </clipPath> 9 + </defs> 10 + </svg>
+3
public/atmosphere-icons/logo-blacksky.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M33.4007 30.251V37.2108C33.4007 40.3527 35.9477 42.8997 39.0896 42.8997H46.05V45.8872H39.0896C35.9478 45.8872 33.4008 48.4342 33.4007 51.576V58.5365H30.4132V51.576C30.4131 48.4344 27.866 45.8873 24.7243 45.8872H17.7639V42.8997H24.7243C27.866 42.8995 30.4132 40.3525 30.4132 37.2108V30.2504L33.4007 30.251ZM19.65 15.2004L17.9292 21.9448C17.1524 24.9891 18.9905 28.0867 22.0347 28.8635L28.7792 30.5844L28.0403 33.4795L21.2965 31.7587C18.2522 30.9819 15.1539 32.8199 14.3771 35.8642L12.6563 42.6087L9.76181 41.8698L11.4826 35.1254C12.2593 32.0811 10.4213 28.9835 7.37709 28.2066L0.632645 26.4858L1.37153 23.5913L8.11528 25.3122C11.1596 26.089 14.2572 24.2503 15.034 21.2059L16.7549 14.4629L19.65 15.2004ZM48.9653 21.2059C49.7421 24.2502 52.8397 26.0889 55.884 25.3122L62.6285 23.5913L63.3674 26.4858L56.6229 28.2066C53.5787 28.9834 51.74 32.0811 52.5167 35.1254L54.2382 41.8698L51.3431 42.6087L49.6222 35.8642C48.8454 32.8199 45.7478 30.9819 42.7035 31.7587L35.959 33.4795L35.2208 30.5844L41.9646 28.8635C45.0089 28.0867 46.8476 24.9891 46.0708 21.9448L44.3493 15.2004L47.2445 14.4629L48.9653 21.2059ZM42.9639 7.57605L38.0417 12.4976C35.8202 14.7192 35.8202 18.3211 38.0417 20.5427L42.9639 25.4642L40.8514 27.5767L35.9292 22.6552C33.7075 20.4337 30.1056 20.4336 27.884 22.6552L22.9625 27.5767L20.85 25.4642L25.7715 20.5427C27.9931 18.3211 27.9931 14.7192 25.7715 12.4976L20.85 7.57605L22.9625 5.46355L27.884 10.3851C30.1056 12.6067 33.7075 12.6066 35.9292 10.3851L40.8514 5.46355L42.9639 7.57605Z" fill="white"/> 3 + </svg>
+6
public/atmosphere-icons/logo-blento.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M24.2728 7.25019C24.2728 3.79832 27.0711 1.00003 30.5229 1.00003H57.2186C60.6705 1.00003 63.4688 3.79833 63.4688 7.2502V33.4355C63.4688 36.8874 60.6705 39.6857 57.2186 39.6857H30.5229C27.0711 39.6857 24.2728 36.8874 24.2728 33.4355V7.25019Z" fill="#A755F6"/> 3 + <path d="M1 7.25019C1 3.79832 3.7983 1.00003 7.25017 1.00003H10.0608C13.5127 1.00003 16.311 3.79833 16.311 7.2502V33.4355C16.311 36.8874 13.5127 39.6857 10.0608 39.6857H7.25017C3.7983 39.6857 1 36.8874 1 33.4355V7.25019Z" fill="#3D82F4"/> 4 + <path d="M1 53.8975C1 50.4457 3.7983 47.6474 7.25017 47.6474H33.6396C37.0915 47.6474 39.8898 50.4457 39.8898 53.8975V57.0143C39.8898 60.4662 37.0915 63.2645 33.6396 63.2645H7.25018C3.79831 63.2645 1 60.4662 1 57.0143V53.8975Z" fill="#EC479B"/> 5 + <path d="M47.7495 53.8975C47.7495 50.4457 50.5478 47.6474 53.9997 47.6474H57.2186C60.6705 47.6474 63.4687 50.4457 63.4687 53.8975V57.0143C63.4687 60.4662 60.6705 63.2645 57.2186 63.2645H53.9997C50.5478 63.2645 47.7495 60.4662 47.7495 57.0143V53.8975Z" fill="#EE4345"/> 6 + </svg>
+3
public/atmosphere-icons/logo-bluesky.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M14.6366 7.81116C21.8491 13.3459 29.607 24.5681 32.4553 30.5905C35.3038 24.5685 43.0612 13.3458 50.2739 7.81116C55.4781 3.81752 63.9102 0.727462 63.9102 10.5602C63.9102 12.5239 62.8087 27.0565 62.1627 29.4158C59.9171 37.6184 51.7344 39.7106 44.4557 38.4443C57.1787 40.6577 60.4153 47.9893 53.4255 55.3209C40.1504 69.2451 34.3454 51.8273 32.8572 47.3642C32.4543 46.1554 32.4558 46.1554 32.0529 47.3642C30.5654 51.8273 24.7605 69.2455 11.4847 55.3209C4.49475 47.9893 7.73124 40.6573 20.4544 38.4443C13.1755 39.7106 4.99271 37.6184 2.74748 29.4158C2.10144 27.0563 1 12.5237 1 10.5602C1 0.727462 9.43267 3.81752 14.6366 7.81116Z" fill="#0A7AFF"/> 3 + </svg>
+9
public/atmosphere-icons/logo-bookhive.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M14.2442 0.963867L14.7499 0.962065C15.2121 0.960623 51.1072 0.930164 51.5588 0.932507C51.722 0.932957 51.8852 0.932507 52.0483 0.930975C53.1501 0.921422 53.8535 1.06038 54.7446 1.75896C55.2249 2.24685 55.5629 2.70762 55.8195 3.34303L55.9137 3.53723C56.0228 3.86111 56.0247 4.16263 56.0225 4.50012L56.0232 4.71505C56.0237 4.95359 56.023 5.19203 56.0223 5.43057C56.0235 6.07734 56.013 43.1982 56.0123 43.6605V44.1643C56.0124 44.3911 56.0121 44.618 56.0116 44.8449L56.0122 45.0459C56.0104 47.5696 54.4662 47.3198 54.4662 47.3198C54.4662 47.3198 54.5382 55.7658 54.5379 56.0668L54.5447 56.3337C54.5377 57.5481 54.2466 58.505 52.4863 58.5065L25.7791 58.5727C25.5946 58.5639 25.5946 58.5639 25.5038 58.6744C25.4938 58.9355 25.5561 61.6808 25.5561 61.6808C25.5465 62.144 25.5531 62.9894 24.5113 63C22.8066 63.0174 21.1565 60.7507 20.2707 60.7471C19.5918 60.7443 17.8008 63.0001 15.9265 62.9913C15.4985 62.9893 15.1922 62.6836 15.0376 62.3692C14.9528 62.0605 14.9636 61.7672 14.9759 61.4491L14.9786 61.1846C14.9822 60.9072 14.99 60.6301 14.9981 60.3528C15.0013 60.1643 15.0042 59.9757 15.0067 59.7872C15.0137 59.326 15.0246 58.8651 15.0376 58.4041L14.8658 58.4065C13.4329 58.4097 7.98683 58.5339 7.98737 52.2753L7.98656 52.0325C7.98584 51.7637 7.98565 51.495 7.98547 51.2261C7.98547 51.2261 7.93224 7.67537 7.93188 7.48693C7.91844 0.890603 13.5318 0.961794 14.2441 0.963957L14.2442 0.963867Z" fill="#210E03"/> 3 + <path d="M15.4946 47.828C16.0832 47.8266 47.2276 47.8544 51.9398 47.8605L51.8272 48.1511L51.6794 48.5374L51.6054 48.7279C51.3654 49.3582 51.2306 49.987 51.1278 50.6541L51.0887 50.8924C50.8646 52.6469 51.1609 54.4764 51.9398 56.061V56.2413C48.1805 56.2461 26.4939 56.2634 26.4939 56.2634L26.256 56.2636C26.0248 56.2391 25.8799 56.1849 25.6842 56.061C25.5701 55.8331 25.5833 55.6761 25.5841 55.4208L25.5721 51.5095L25.5717 51.2523C25.4919 50.9727 25.3693 50.8244 25.1362 50.6507C24.7922 50.479 24.4337 50.5016 24.0565 50.5057C24.0565 50.5057 16.8604 50.5031 16.5751 50.5057L16.3202 50.5029C15.9258 50.5093 15.661 50.5291 15.3475 50.7816C15.0445 51.1028 15.0259 51.2477 15.0191 51.6785L15.0137 51.9846C15.0137 51.9846 14.9562 55.6462 14.9474 56.2413C14.7883 56.2429 14.6292 56.244 14.4702 56.2451L14.2018 56.2471C12.7709 56.2239 10.5582 55.4391 10.5147 52.0667C10.561 50.9055 11.0209 49.8962 11.7895 49.032C12.0162 48.8245 12.2506 48.6536 12.5113 48.4913L12.6685 48.3885C13.5842 47.8236 14.4598 47.8222 15.4946 47.828Z" fill="#F6E8C5"/> 4 + <path d="M23.3384 60.0262C23.0462 59.846 21.6125 58.9015 21.3545 58.7478C20.8561 58.4526 20.4465 58.2263 19.8728 58.3675C19.3643 58.5542 18.828 58.9176 18.3788 59.2173C17.9939 59.4679 17.597 59.7 17.203 59.9361V52.8169H23.3384V60.0262ZM13.3219 3.73063C13.3203 4.09861 13.3333 45.4553 13.2331 45.7877C11.6431 46.0767 11.1579 46.5988 10.2556 47.4098V47.3197C10.2369 41.5325 10.1696 8.14692 10.1654 7.98158C10.0573 3.73966 12.4325 3.36832 13.3396 3.28929L13.3219 3.73063ZM50.3364 3.15103C53.4422 3.15004 53.6894 3.60517 53.678 6.36741C53.6649 9.58573 53.7161 34.341 53.7449 43.0277C53.7518 45.0956 53.3652 45.6221 51.4887 45.6977C50.6824 45.7302 21.1473 45.8109 15.5516 45.7416L15.5331 3.25857C17.5145 3.18594 48.4413 3.15157 50.3364 3.15103Z" fill="#CC7935"/> 5 + <path d="M29.9248 4.69476C30.8218 4.69477 31.5489 5.40083 31.5489 6.2718C31.5489 6.33629 31.5447 6.39986 31.537 6.46233C32.4027 7.41819 33.037 8.63188 33.5401 9.78792C33.6894 10.1309 33.8146 10.4575 33.9901 10.7738C34.5923 10.398 37.7988 10.5099 38.1153 10.8595L38.1807 10.4479C38.4829 9.04123 39.2362 7.92085 40.3015 7.08592C40.301 7.06994 40.3008 7.05389 40.3008 7.03779C40.3008 6.14193 41.0683 5.41569 42.0151 5.41569C42.9618 5.41569 43.7293 6.14193 43.7293 7.03779C43.7293 7.93364 42.9618 8.65988 42.0151 8.65988C41.8174 8.65988 41.6275 8.62812 41.4508 8.56985C40.8877 8.99862 40.7577 9.09365 40.1033 10.6915C40.048 10.8267 39.9062 11.0117 40.0431 11.094C45.1301 14.151 45.7124 16.9707 45.7682 20.076L45.9645 20.0541C49.3504 19.1903 51.9898 19.8251 52.4777 22.7094C52.5578 23.7237 52.3695 24.602 51.9237 25.506C50.8379 27.5413 46.4797 30.5203 44.1957 29.951L44.2067 30.3423C43.9505 46.0612 29.3271 40.2719 29.3091 40.2648C29.3091 40.2648 27.319 41.542 26.9917 41.4083C26.6049 41.3361 27.4322 39.6021 27.5269 39.2773L27.3115 39.0357C24.4702 37.2377 23.9693 34.9197 23.8576 32.8038L23.6005 32.9106C17.0555 35.3729 18.0353 26.8788 21.5513 26.001L21.3219 25.7609C11.2829 15.4735 20.5037 10.6606 27.422 16.7844C27.422 16.7844 28.1477 12.7947 32.0348 11.2983C31.8975 10.9776 31.396 9.66696 31.2878 9.50842C30.8484 8.86467 30.4992 8.30458 30.2278 7.82129C30.1297 7.83928 30.0284 7.84883 29.9248 7.84883C29.0279 7.84883 28.3008 7.14277 28.3008 6.2718C28.3008 5.40083 29.0279 4.69476 29.9248 4.69476Z" fill="#210E03"/> 6 + <path d="M27.0351 30.2549C31.953 36.0684 39.6793 34.3829 41.8893 33.6815C40.4533 43.2877 23.5883 38.2578 26.8979 30.0607L27.0351 30.2549ZM30.2526 25.3427C31.9491 27.1244 35.5947 28.8958 41.1546 27.118C41.7578 27.5657 42.0919 29.6971 41.8893 30.7191C31.6111 33.7855 28.2906 27.8037 28.2906 27.8037C28.2912 27.802 28.9551 25.9331 30.2526 25.3427ZM29.3624 17.939C29.9837 12.9105 37.3692 10.7942 41.2457 14.5194C41.6098 14.8329 44.1959 16.7169 43.579 20.8295C43.0442 22.8138 42.1238 23.8195 40.7078 24.6468C38.5669 25.7495 36.2257 25.8783 33.962 25.1032C32.8151 24.6313 31.7128 23.8895 30.8816 22.9288L30.6719 22.7094C29.6713 21.3038 29.1447 19.7002 29.3624 17.939Z" fill="#FEC402"/> 7 + <path d="M22.0473 27.765C22.1689 27.7022 23.3242 26.9989 24.7737 27.2341C25.0383 27.277 25.1065 27.2496 25.4302 27.3177C25.036 27.8224 24.3875 29.1715 24.2467 29.4559C23.9631 30.0229 23.8598 31.217 23.2802 31.4185C19.4806 33.3184 20.2551 28.6908 22.0473 27.765ZM45.2874 22.7107C45.4885 22.4437 48.742 19.9077 50.8069 22.1813C52.0264 23.524 48.7628 26.434 48.7524 26.4433C46.1929 28.6319 43.9291 28.7153 43.9291 28.7153C43.7376 28.4639 42.6232 26.3302 42.6232 26.1107C42.7533 26.0056 42.8865 25.905 43.0229 25.8091C43.9692 25.058 44.95 24.1274 45.2874 22.7107ZM25.4117 24.9413C16.1166 20.3807 18.1211 13.69 23.8765 16.9841C24.9092 17.5788 26.4769 18.4447 27.1076 19.7469C27.1609 20.0146 27.1995 20.2719 27.2321 20.5424C27.4277 21.8552 28.0922 22.8984 28.8897 23.9163C28.6565 24.5529 28.0799 24.9605 27.5192 25.2655C26.4836 25.7203 25.4117 24.9413 25.4117 24.9413Z" fill="#BBDDCE"/> 8 + <path d="M36.6935 22.4214C36.1914 21.7363 37.1875 21.1485 37.4735 21.7041C37.7164 22.176 38.2534 22.4599 38.7606 22.4398C39.307 22.4181 39.7609 22.152 40.0795 21.7228C40.3222 21.3958 41.1377 21.8847 40.8264 22.341C39.8869 23.718 37.5936 23.6498 36.6935 22.4214ZM36.4843 17.9797C37.0215 17.9797 37.457 18.5762 37.457 19.312C37.457 20.0478 37.0215 20.6443 36.4843 20.6443C35.9471 20.6443 35.5116 20.0478 35.5116 19.312C35.5116 18.5762 35.9471 17.9797 36.4843 17.9797ZM40.77 17.9797C41.2325 17.9797 41.6074 18.5358 41.6074 19.2219C41.6074 19.9079 41.2325 20.464 40.77 20.464C40.3075 20.464 39.9326 19.9079 39.9326 19.2219C39.9326 18.5358 40.3075 17.9797 40.77 17.9797Z" fill="#210E03"/> 9 + </svg>
+3
public/atmosphere-icons/logo-eurosky.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M63.324 33.3255V30.4794H53.7954C34.9377 30.2338 34.3544 25.118 33.4231 10.1376V0.689178H30.577V10.1376C29.6457 25.118 29.1554 30.2338 10.2977 30.4794H0.675964V33.3255H10.2977C25.606 34.3555 30.1863 34.0808 30.577 52.295V63.3108H33.4231V52.27C33.8137 34.0559 38.4871 34.3555 53.7954 33.3255L63.324 33.3255Z" fill="black"/> 3 + </svg>
+3
public/atmosphere-icons/logo-grain.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M28.9823 37.4693C22.5838 37.4693 17.3117 36.9511 13.1662 35.9147C9.02069 34.8333 5.95661 33.2336 3.97396 31.1158C1.99132 28.9529 1 26.2493 1 23.005C1 19.986 1.96879 17.3725 3.90637 15.1645C5.84396 12.9115 8.86298 11.1542 12.9634 9.89252C17.109 8.63084 22.4486 8 28.9823 8C30.289 8 31.6183 8 32.9701 8C34.3219 8 35.6512 8 36.9579 8H62.7773V16.5163C59.8484 16.6515 56.8745 16.5164 53.8554 16.1108C50.8815 15.6602 48.1328 15.0744 45.6095 14.3535L44.866 13.3396C46.8937 13.9705 48.8087 14.7815 50.6111 15.7729C52.4586 16.7642 53.9456 17.9583 55.0721 19.3551C56.1986 20.752 56.7618 22.4192 56.7618 24.3568C56.7618 27.1505 55.793 29.5387 53.8554 31.5214C51.9629 33.4589 48.9664 34.9459 44.866 35.9823C40.8106 36.9736 35.516 37.4693 28.9823 37.4693ZM43.379 56.6649V54.8399C43.379 53.4881 42.7707 52.677 41.5541 52.4067C40.3825 52.1814 38.5125 52.0687 35.9441 52.0687H17.0864C13.8872 52.0687 11.2962 51.8434 9.31358 51.3928C7.376 50.9422 5.88902 50.3339 4.85264 49.5679C3.86131 48.8019 3.18541 47.9457 2.82493 46.9995C2.50951 46.0983 2.3518 45.1971 2.3518 44.2959C2.3518 42.3583 3.07276 40.8488 4.51468 39.7673C5.95661 38.6408 8.16455 37.8523 11.1385 37.4017C14.1125 36.9511 17.8975 36.7258 22.4936 36.7258L28.9823 37.4693C25.1973 37.4693 22.5612 37.672 21.0743 38.0776C19.5873 38.4381 18.8438 39.1816 18.8438 40.3081C18.8438 40.9389 19.1367 41.412 19.7225 41.7275C20.3082 41.9978 21.0968 42.133 22.0881 42.133H42.0272C46.4881 42.133 50.0028 42.4484 52.5712 43.0793C55.1397 43.7552 56.9421 44.8591 57.9784 46.3912C59.0599 47.9683 59.6006 50.1086 59.6006 52.8122V56.6649H43.379ZM28.9823 28.615C31.9563 28.615 34.3444 28.3897 36.1468 27.9391C37.9943 27.4434 39.3236 26.79 40.1347 25.979C40.9457 25.1679 41.3513 24.2667 41.3513 23.2754C41.3513 22.1489 40.9457 21.1801 40.1347 20.369C39.3236 19.5579 38.0168 18.9271 36.2144 18.4765C34.412 18.0259 32.0013 17.8006 28.9823 17.8006C26.0083 17.8006 23.5976 18.0259 21.7502 18.4765C19.9027 18.9271 18.5509 19.5579 17.6948 20.369C16.8386 21.1801 16.4105 22.1489 16.4105 23.2754C16.4105 24.2667 16.8161 25.1679 17.6272 25.979C18.4833 26.79 19.8351 27.4434 21.6826 27.9391C23.53 28.3897 25.9633 28.615 28.9823 28.615Z" fill="black"/> 3 + </svg>
+3
public/atmosphere-icons/logo-graze.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M45.7619 7.87587C60.1702 10.6391 63.4775 22.3307 63.4775 27.9181H36.1258C36.1258 27.5617 35.364 26.8039 32.9584 26.9237C29.966 27.0728 28.9088 29.7137 28.9088 32.4192C28.9088 35.1247 29.1685 37.4479 30.3502 38.2959C31.6616 39.237 32.8425 39.2668 34.2072 39.129C36.0651 38.9415 36.654 37.7064 36.7601 37.0344H30.7655V29.7137H63.4775V56.026H38.5107L37.6353 41.2621C37.6805 42.5161 36.6411 47.4777 35.5375 49.4641C33.5007 53.1304 31.2195 57.7008 18.1616 57.3492C2.86694 56.9373 0.522465 43.9029 0.522461 36.2991C0.522456 26.9237 1.96649 21.2534 7.07669 15.5318C14.7563 6.93337 30.7655 4.99983 45.7619 7.87587Z" fill="#00B5B5"/> 3 + </svg>
+4
public/atmosphere-icons/logo-leaflet.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path fill-rule="evenodd" clip-rule="evenodd" d="M6.55069 43.9803C4.40599 48.2312 2.799 50.9958 1.24638 54.9631C0.0342212 58.0604 1.49808 61.5798 4.51595 62.8238C7.53384 64.0679 10.963 62.5655 12.1751 59.4682C12.482 58.684 12.7778 57.9117 13.0635 57.1655L13.0661 57.1586C14.1541 54.3171 15.0925 51.8858 16.2276 49.696C17.5061 49.6248 18.9679 49.6138 20.6162 49.6044L20.8234 49.6032C23.8295 49.5862 27.4511 49.5658 30.5742 48.917C33.6991 48.2679 37.5663 46.7333 39.2758 42.623C39.7385 41.5105 40.2079 39.868 39.7969 38.1997C39.9202 38.1995 40.0466 38.1995 40.1762 38.1995C40.2456 38.1995 40.3164 38.1995 40.3884 38.1996C42.0376 38.2007 44.3583 38.2023 46.4328 37.6231C48.8535 36.9473 51.3989 35.3469 52.5156 31.9759C52.9191 30.7578 52.9939 29.4786 52.6455 28.2697C52.7523 28.2503 52.8617 28.2306 52.9741 28.2104C53.0281 28.2007 53.0829 28.1909 53.1384 28.1809C54.5559 27.9267 56.4532 27.5864 58.0742 26.964C59.6509 26.3586 62.2418 25.0061 63.0182 21.9064C63.4607 20.1397 63.4142 18.2693 62.4202 16.5802C62.0069 15.8778 61.481 15.3248 61.0145 14.917C61.449 14.3589 62.0016 13.5826 62.3822 12.7261C63.0425 11.24 63.383 9.05666 62.0323 6.9204C60.4993 4.49585 57.8707 4.0723 56.5704 3.96257C55.2183 3.84846 53.7647 3.97035 52.7202 4.06723C52.5784 3.71062 52.3831 3.33561 52.1131 2.9655C50.663 0.978048 48.4138 0.811008 47.1478 0.84595C44.59 0.916547 42.5894 2.08135 41.1433 3.28946C40.3844 3.9235 38.5783 6.51583 37.9874 7.1901C37.9874 4.77231 35.7179 3.54183 34.1223 3.28946C31.0243 2.79946 29.1055 4.84683 27.3216 7.1901C25.0979 10.1111 23.3765 13.8707 21.3424 16.6956C20.6414 16.2275 19.8115 15.1322 18.4842 15.1955C16.2973 15.2997 14.8446 16.8212 13.9045 17.8623C12.2687 19.674 11.2278 22.9654 10.5193 25.416C9.74905 28.9617 9.2237 30.4567 8.5996 34.3441C8.22845 36.6559 8.04028 38.4801 8.04028 41.0617C7.61448 41.918 7.12715 42.8377 6.55069 43.9803Z" fill="#639431"/> 3 + <path fill-rule="evenodd" clip-rule="evenodd" d="M19.2006 18.3464C19.8407 18.9236 20.5909 19.6 22.2092 19.0221C23.2673 18.6443 24.6348 16.1828 26.1606 13.4363C28.3908 9.42172 30.9594 4.79819 33.3946 5.18336C36.3321 5.64797 36.1512 7.31693 36.0122 8.60059C35.9146 9.50098 35.8376 10.2118 36.8716 10.1845C37.9249 10.1567 38.9499 8.8863 40.1395 7.41202C41.7826 5.37558 43.7396 2.95016 46.5183 2.87347C48.4775 2.8194 48.4466 3.68586 48.4152 4.56456C48.3952 5.1262 48.375 5.69284 48.8741 6.02727C49.3659 6.35673 50.6025 6.24161 52.024 6.10926C54.303 5.89708 57.0574 5.64065 57.9807 7.10084C58.7923 8.38455 57.7583 9.66043 56.7671 10.8833C55.9276 11.9192 55.1189 12.917 55.4886 13.8494C55.7903 14.6101 56.4095 15.0387 57.0166 15.4588C58.0094 16.146 58.9695 16.8105 58.454 18.8686C57.909 21.0447 54.63 21.634 51.5565 22.1865C48.9817 22.6492 46.551 23.0861 45.9927 24.4083C45.6425 25.2375 46.2234 25.6237 46.8742 26.0563C47.6519 26.5733 48.5295 27.1568 48.0374 28.6421C46.8871 32.1146 43.0457 32.1146 39.4405 32.1147C36.346 32.1147 33.4254 32.1148 32.53 34.3107C32.013 35.5785 32.7955 35.8023 33.654 36.0479C34.7049 36.3485 35.8698 36.6817 34.9046 39.0025C33.0575 43.4436 26.1665 43.4833 19.8583 43.5196C17.5453 43.533 15.3107 43.5458 13.4317 43.7751C13.2173 43.8012 13.027 43.9276 12.9146 44.1168C11.1857 47.0285 9.95944 50.2309 8.65145 53.6468C8.36411 54.3973 8.07282 55.158 7.77139 55.9282C7.37291 56.9464 6.24563 57.4403 5.25353 57.0314C4.26144 56.6224 3.78022 55.4654 4.1787 54.4472C5.66286 50.6549 7.37505 47.1676 9.24726 43.9665C12.3027 38.1918 18.3257 31.1069 24.6949 25.7843C30.3621 20.9419 35.774 17.3174 42.0727 14.567C42.8611 14.2228 42.6271 13.2765 41.804 13.5206C36.2176 15.1775 31.2793 18.4639 26.1606 21.7758C20.5932 25.378 15.9277 30.2493 13.0567 33.791C12.5505 34.4155 11.4434 33.902 11.6028 33.1063C12.8497 26.8815 14.1366 21.169 16.0231 19.0797C17.8141 17.0961 18.4269 17.6487 19.2006 18.3464Z" fill="#D9EA72"/> 4 + </svg>
+3
public/atmosphere-icons/logo-margin.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M47.518 20.5424H36.0103V32.0502H43.6821L47.518 35.8861V58.7352H1.25452V5.2648H47.518V20.5424ZM62.7455 5.2648V58.7352H51.2377V55.0675H59.0258V9.0367H51.2377V5.2648H62.7455Z" fill="#027BFF"/> 3 + </svg>
+3
public/atmosphere-icons/logo-offprint.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M15.3556 31.5106C15.7241 34.5814 17.0753 40.8461 20.1462 46.1283C20.5147 46.8653 21.4975 46.7424 21.743 46.1283L39.4316 13.6992C39.8002 13.085 39.6773 12.2252 39.0631 11.7338C36.4836 9.52275 33.1669 8.17154 29.2362 8.29436C15.1099 8.66289 14.9871 26.4743 15.3556 31.5106ZM34.7638 55.5868C48.5216 55.2181 49.013 37.5296 48.5216 32.6161C48.276 29.4223 46.9247 23.0348 43.7309 17.5072C43.4852 17.0158 42.6254 17.0158 42.3797 17.5072L24.5684 50.1819C24.3227 50.9188 24.4455 51.6559 24.9368 52.1473C27.5165 54.3583 30.8331 55.7095 34.7638 55.5868ZM49.7499 3.99506L49.013 5.34628C48.5216 6.20615 48.7673 7.18884 49.5042 7.55734C59.3314 13.822 62.525 24.6317 62.525 31.7563C62.525 40.6006 55.1548 61.2371 32.6757 61.2371C28.2534 61.2371 24.4455 60.623 21.0061 59.5175C20.3919 59.2718 19.532 59.5175 19.1635 60.1316L18.1808 62.0972C17.8123 62.834 16.9525 63.0797 16.2154 62.7113L14.8642 61.9742C14.1272 61.6058 13.8815 60.7459 14.25 60.0089L15.1099 58.4119C15.4784 57.6749 15.2327 56.815 14.6186 56.4466C4.79158 50.059 1.47498 39.1265 1.47498 32.2477C1.47498 23.4033 8.23102 2.7667 30.8331 2.7667C35.5009 2.7667 39.4316 3.38089 42.8711 4.48641C43.6082 4.73208 44.468 4.36358 44.8364 3.74939L45.942 1.784C46.3106 1.16981 47.1704 0.924138 47.7846 1.29265L49.2587 2.02967C49.8729 2.39819 50.1186 3.25804 49.7499 3.99506Z" fill="black"/> 3 + </svg>
+5
public/atmosphere-icons/logo-pckt.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M35.0415 0.551819C41.0486 0.551819 46.1485 2.56577 49.6504 6.89075C49.9931 7.31408 50.3154 7.75501 50.6196 8.2117C52.0145 9.12372 53.2731 10.2547 54.3737 11.6141C57.7727 15.8121 59.2539 21.6859 59.2539 28.6181C59.2539 34.128 58.3163 38.9765 56.2292 42.8505C56.4404 42.9955 56.6437 43.1574 56.8374 43.336C57.7636 44.1894 58.3016 45.2584 58.6399 46.2062L58.6595 46.2615L58.6779 46.318C59.1153 47.6859 59.4069 49.675 58.2639 51.5165C58.0283 51.8961 57.7584 52.2242 57.4671 52.5088C57.5288 52.8967 57.5505 53.3056 57.5184 53.7347C57.3555 55.9066 55.9376 57.3616 54.7139 58.2331L54.7116 58.2349C53.8013 58.8821 52.5029 59.5938 50.8721 59.5939C49.9274 59.5938 49.118 59.3623 48.4291 58.9977C47.7318 59.364 46.9175 59.5939 45.9763 59.5939C44.4172 59.5938 43.0829 58.882 42.1726 58.2349L42.1311 58.2049C41.1223 57.4652 39.9082 56.2835 39.4881 54.5718C38.6861 54.3046 37.992 53.8974 37.4493 53.5115L37.4078 53.4816C36.7846 53.0246 36.0834 52.3989 35.5391 51.584C35.046 51.4755 34.5619 51.3493 34.0878 51.204V57.6387C34.0878 58.9405 33.7588 60.5905 32.4428 61.8741C31.1436 63.1417 29.4987 63.4482 28.202 63.4482H15.2791C13.9774 63.4482 12.3506 63.1199 11.0741 61.844C10.1135 60.8834 9.69005 59.7244 9.53922 58.6546C8.46987 58.5037 7.31112 58.0807 6.35072 57.1203C5.07428 55.8439 4.74614 54.2171 4.74609 52.9153V7.11736C4.74609 5.81557 5.07419 4.18831 6.35072 2.91177C7.6272 1.63544 9.25403 1.30773 10.5557 1.30772H23.4787C24.5333 1.30772 25.8009 1.5103 26.9313 2.24467C29.3471 1.12842 32.077 0.551855 35.0415 0.551819Z" fill="black"/> 3 + <path d="M50.5802 42.6738C51.1877 44.5736 50.5445 45.6642 48.4718 46.016L47.7571 46.1215L48.2574 46.6844C49.6868 48.1268 49.6153 49.4285 47.9358 50.6247C47.2926 51.082 46.7208 51.3283 46.149 51.3283C45.3271 51.3283 44.6482 50.7654 44.0764 49.6747L43.719 49.0063L43.3617 49.6747C42.79 50.7654 42.0753 51.3283 41.2533 51.3283C40.7531 51.3283 40.1455 51.082 39.5023 50.6247C37.8227 49.3933 37.7155 48.1268 39.1807 46.7196L39.7167 46.1215L38.9663 46.016C36.9294 45.6642 36.2147 44.5736 36.8579 42.709C37.2867 41.337 37.9657 40.7037 39.002 40.7037C39.4308 40.7037 39.9669 40.8445 40.5386 41.1259L41.2176 41.4777L41.0747 40.7389C40.8245 38.7337 41.6464 37.7486 43.719 37.7486C45.7559 37.7486 46.6136 38.7337 46.292 40.7389L46.1848 41.4777L46.8995 41.1611C47.507 40.8797 48.0073 40.7389 48.4718 40.7389C49.4367 40.7389 50.1157 41.3722 50.5802 42.6738Z" fill="#58A7FF"/> 4 + <path fill-rule="evenodd" clip-rule="evenodd" d="M35.0419 4.09436C45.3955 4.09436 50.9885 10.8961 50.9885 23.8948C50.9885 29.8304 49.8208 34.4888 47.5676 37.7996C47.4703 37.6397 47.36 37.4833 47.2314 37.3343C46.3152 36.2727 44.9651 35.9771 43.7195 35.9771C42.4584 35.9771 41.1123 36.2715 40.1914 37.3274C39.765 37.8164 39.5143 38.3736 39.3824 38.9517C39.2554 38.9395 39.1286 38.9321 39.0025 38.9321C38.0819 38.9321 37.2067 39.2311 36.4932 39.8978C35.8431 40.5055 35.4464 41.3086 35.1838 42.131C35.0048 42.6498 34.8792 43.2062 34.8603 43.7684C31.311 43.7312 28.2745 42.6054 25.8224 40.7477V52.9154C25.8223 54.4267 25.0661 55.1825 23.4791 55.1825H10.5562C9.04487 55.1825 8.28916 54.4266 8.28906 52.9154V7.11737C8.28906 5.60594 9.04477 4.85029 10.5562 4.85026H23.4791C25.0662 4.85026 25.8224 5.60595 25.8224 7.04186C28.2407 5.15258 31.339 4.09441 35.0419 4.09436ZM30.1346 17.3384C26.5814 17.3384 25.4113 19.989 25.4113 24.4235C25.4113 28.8582 26.5813 31.5085 30.1346 31.5085C33.688 31.5085 34.858 28.8582 34.858 24.4235C34.8579 19.989 33.6879 17.3384 30.1346 17.3384Z" fill="#FF5D5B"/> 5 + </svg>
+3
public/atmosphere-icons/logo-pdsls.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M38.8392 1.51855C43.2582 1.51855 46.8405 5.18242 46.8405 9.70204C46.8405 11.5587 46.2345 13.2699 45.2157 14.6431L50.758 24.0001C51.3028 23.8802 51.8682 23.8165 52.4481 23.8165C56.8671 23.8165 60.4494 27.4804 60.4494 32C60.4494 36.5196 56.8671 40.1835 52.4481 40.1835C48.0291 40.1835 44.4468 36.5196 44.4468 32C44.4468 30.1472 45.0491 28.4385 46.064 27.0668L40.5174 17.7031C39.9761 17.8213 39.415 17.8855 38.8392 17.8855C38.2651 17.8855 37.7053 17.8228 37.1655 17.7053L31.5557 26.7987C32.5637 28.1677 33.1621 29.8706 33.1621 31.7164C33.162 33.6214 32.5231 35.3724 31.4557 36.763L37.11 46.3069C37.6669 46.1814 38.2454 46.1145 38.8392 46.1145C43.2582 46.1145 46.8405 49.7783 46.8405 54.298C46.8405 58.8176 43.2582 62.4814 38.8392 62.4814C34.4202 62.4814 30.8379 58.8176 30.8379 54.298C30.8379 52.4603 31.4302 50.7641 32.4301 49.3981L26.7106 39.7441C26.2091 39.8448 25.6911 39.8998 25.1608 39.8998C24.6178 39.8998 24.0877 39.8429 23.5751 39.7374L17.7696 49.1489C18.8844 50.5553 19.5532 52.3464 19.5532 54.298C19.5532 58.8176 15.9709 62.4814 11.552 62.4814C7.13296 62.4814 3.55066 58.8176 3.55066 54.298C3.55066 49.7783 7.13296 46.1145 11.552 46.1145C12.0383 46.1145 12.5142 46.1607 12.9767 46.2457L18.8442 36.7352C17.7897 35.3491 17.1596 33.6086 17.1595 31.7164C17.1595 27.1967 20.7418 23.5329 25.1608 23.5329C25.748 23.5329 26.3203 23.598 26.8715 23.7209L32.4671 14.6497C31.4455 13.2755 30.8379 11.5616 30.8379 9.70204C30.8379 5.18242 34.4202 1.51855 38.8392 1.51855Z" fill="#75C4E4"/> 3 + </svg>
+4
public/atmosphere-icons/logo-plyr.fm.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <circle cx="32.1428" cy="32.1428" r="31.1428" fill="#D9E4FF"/> 3 + <path d="M32.4944 4.94086C47.3571 5.12915 59.3479 17.2356 59.3479 32.143L59.3449 32.4946C59.1567 47.3573 47.0502 59.348 32.1428 59.3481L31.7912 59.3461C17.0455 59.1594 5.12647 47.2403 4.93968 32.4946L4.93772 32.143C4.93774 17.1182 17.118 4.93793 32.1428 4.93793L32.4944 4.94086ZM32.1428 6.10492C17.7622 6.10492 6.10474 17.7624 6.10472 32.143C6.10474 46.5236 17.7622 58.1811 32.1428 58.1811C46.5234 58.181 58.1809 46.5236 58.1809 32.143C58.1809 17.7624 46.5234 6.10498 32.1428 6.10492ZM32.3948 12.7143C43.0098 12.8489 51.5735 21.496 51.5735 32.143L51.5715 32.394C51.437 43.009 42.7907 51.5724 32.1438 51.5727L31.8918 51.5717C21.3603 51.4382 12.8485 42.9255 12.7151 32.394L12.7131 32.143C12.7131 21.412 21.4128 12.7123 32.1438 12.7123L32.3948 12.7143ZM32.1438 13.2963C21.7349 13.2963 13.2961 21.7341 13.2961 32.143C13.2962 42.5518 21.735 50.9897 32.1438 50.9897C42.5523 50.9894 50.9903 42.5516 50.9905 32.143C50.9905 21.7343 42.5524 13.2966 32.1438 13.2963ZM32.1428 20.5805C38.5284 20.5805 43.7053 25.7575 43.7053 32.143L43.7043 32.2924C43.6242 38.6091 38.4784 43.7045 32.1428 43.7045H31.9934C25.6769 43.6244 20.5814 38.4785 20.5813 32.143C20.5813 25.7576 25.7574 20.5807 32.1428 20.5805ZM32.1428 21.1635C26.0795 21.1637 21.1643 26.0797 21.1643 32.143C21.1644 38.2063 26.0796 43.1213 32.1428 43.1215C38.2062 43.1215 43.1222 38.2064 43.1223 32.143C43.1223 26.0796 38.2063 21.1635 32.1428 21.1635ZM32.1428 26.0864C35.4879 26.0864 38.1994 28.7979 38.1994 32.143C38.1993 35.488 35.4878 38.1996 32.1428 38.1996C28.7978 38.1996 26.0863 35.488 26.0862 32.143C26.0862 28.798 28.7978 26.0864 32.1428 26.0864Z" fill="#3B7EFF"/> 4 + </svg>
+3
public/atmosphere-icons/logo-popfeed.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M32.0001 1.09973C45.9147 1.09978 57.2008 12.0113 57.2008 25.4784C57.2008 38.9454 45.9147 49.8567 32.0001 49.8568C29.4003 49.8568 27.047 49.5296 24.7268 48.8357C24.1191 48.6539 23.4581 48.819 23.0353 49.2846L11.8188 61.6346C11.3417 62.1589 10.8682 62.5566 10.3222 62.7565C9.77269 62.9578 9.16182 62.9547 8.41926 62.703C7.66113 62.4459 7.25363 61.9416 7.03822 61.4125C6.82456 60.8876 6.79974 60.3386 6.79915 59.9836V25.4784C6.79917 12.0113 18.0854 1.09973 32.0001 1.09973ZM32.7157 13.178C32.3467 12.3503 31.1719 12.3503 30.8029 13.178L27.6925 20.1556C27.5403 20.4969 27.2177 20.7313 26.8461 20.7706L19.249 21.5722C18.3478 21.6674 17.9848 22.7849 18.658 23.3916L24.3329 28.5057C24.6105 28.7559 24.7338 29.1352 24.6562 29.5008L23.0711 36.9738C22.883 37.8602 23.8336 38.5509 24.6186 38.0982L31.2361 34.2812C31.5598 34.0945 31.9586 34.0945 32.2823 34.2812L38.8998 38.0982C39.6848 38.5509 40.6353 37.8603 40.4473 36.9738L38.8624 29.5008C38.7848 29.1352 38.9079 28.7559 39.1855 28.5057L44.8604 23.3916C45.5336 22.7849 45.1706 21.6674 44.2694 21.5722L36.6723 20.7706C36.3006 20.7313 35.978 20.497 35.8258 20.1556L32.7157 13.178Z" fill="#533EE5"/> 3 + </svg>
+4
public/atmosphere-icons/logo-roomy.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M12.6923 8.56014C21.1606 3.48784 32.9802 2.65962 43.8724 3.10408C50.1339 3.35961 54.6592 5.81101 57.7679 9.53078C60.8691 13.242 62.5431 18.1945 63.1556 23.4351C63.7681 28.6777 63.3212 34.2299 62.1608 39.1634C61.0015 44.0926 59.1242 48.4301 56.8559 51.2292C47.8253 62.3724 35.953 61.5267 26.7211 60.517C22.0927 60.0106 16.4826 58.9573 11.7005 55.9161C6.90433 52.8662 2.96388 47.8317 1.65953 39.4193C0.388546 31.2219 1.01319 24.7813 3.02911 19.7473C5.04667 14.7092 8.44913 11.1017 12.6923 8.56014Z" fill="#250041"/> 3 + <path d="M39.5823 13.9393C53.9896 14.4039 51.8655 45.1873 51.1184 56.5848C48.9087 58.0964 46.6136 59.1343 44.2922 59.827C44.6109 49.8605 46.726 21.6069 34.9084 19.077C9.06719 14.5786 19.335 44.1952 20.0686 59.3739C19.6026 59.2573 19.1356 59.1301 18.6682 58.993C17.8334 49.598 15.3232 38.6798 16.384 29.0701C17.7857 16.3759 30.7655 13.655 39.5823 13.9393ZM37.304 37.3592C39.3431 36.0439 41.8725 38.2807 40.9934 40.9891C39.7581 44.792 33.7607 39.645 37.304 37.3592Z" fill="#FCF4C3"/> 4 + </svg>
+3
public/atmosphere-icons/logo-semble.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M32.4963 34.4842C46.491 34.4842 53.8619 40.7132 53.8619 48.3966C53.8617 56.0798 46.4908 62.3076 32.4963 62.3076C18.5018 62.3074 10.1381 54.5889 10.1381 46.9057C10.1381 39.2224 18.5018 34.4843 32.4963 34.4842ZM31.7859 19.5806C39.737 19.5808 46.4081 24.63 46.4087 29.0202C46.4087 33.4106 39.455 32.996 31.5037 32.996C23.5521 32.996 17.0943 32.9137 17.0943 28.5233C17.095 24.133 23.8348 19.5806 31.7859 19.5806ZM31.5037 9.64115C39.4553 9.64118 45.4161 12.7038 45.4161 17.0943C45.4159 21.4844 39.4551 18.5839 31.5037 18.5839C23.5523 18.5839 19.0823 20.9876 19.0822 16.5974C19.0822 12.2068 23.5522 9.64115 31.5037 9.64115ZM31.6056 1.69238C35.8061 1.69245 38.9552 3.55125 38.9555 6.7323C38.9555 9.91362 35.8063 7.65474 31.6056 7.65465C27.4049 7.65465 25.0431 9.91368 25.0431 6.7323C25.0433 3.55119 27.405 1.69238 31.6056 1.69238Z" fill="#FF6400"/> 3 + </svg>
+5
public/atmosphere-icons/logo-sifa id.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M15.2088 1.84613C22.4429 1.84614 28.3956 7.79885 28.3956 15.0329C28.3956 18.8469 26.6327 21.6555 23.1796 21.6555C21.6008 21.6555 20.3755 21.0682 19.5103 20.0663C18.3527 21.0567 16.8502 21.6555 15.2088 21.6555C11.5537 21.6555 8.58621 18.6881 8.5862 15.0329C8.5862 11.3778 11.5536 8.41035 15.2088 8.41035C16.3413 8.41035 17.4076 8.69547 18.3403 9.19744C18.6926 8.72009 19.2591 8.41038 19.8973 8.41035C20.9648 8.41035 21.8314 9.27693 21.8314 10.3444V15.0329C21.8314 15.7841 21.9179 16.4822 22.1573 17.045C22.3416 17.4779 22.6564 17.7874 23.1796 17.7874C23.7027 17.7874 24.0173 17.4778 24.2016 17.045C24.4409 16.4822 24.5275 15.7841 24.5275 15.0329C24.5275 9.92092 20.3208 5.71427 15.2088 5.71426C10.0968 5.71426 5.89011 9.92092 5.89011 15.0329C5.89012 20.145 10.0968 24.3516 15.2088 24.3516C17.1329 24.3516 19.2115 23.7904 20.7023 22.7994C21.5912 22.2086 22.7927 22.4507 23.3836 23.3396C23.9744 24.2286 23.7324 25.4301 22.8434 26.0209C20.7685 27.4 17.8867 28.2198 15.2088 28.2198C7.97469 28.2198 2.02199 22.267 2.02198 15.0329C2.02198 7.79884 7.97469 1.84613 15.2088 1.84613ZM15.2088 12.2785C13.6885 12.2785 12.4543 13.5127 12.4543 15.0329C12.4543 16.5532 13.6885 17.7874 15.2088 17.7874C16.7291 17.7874 17.9632 16.5532 17.9633 15.0329C17.9633 13.5127 16.7291 12.2785 15.2088 12.2785Z" fill="#DA702C"/> 3 + <path d="M21.4505 36.9231C24.5579 36.9231 27.0769 39.4421 27.0769 42.5494V55.2088C27.0769 58.3161 24.5579 60.8351 21.4505 60.8351H8.79121C5.68385 60.8351 3.16483 58.3161 3.16483 55.2088V42.5494C3.16483 39.4421 5.68385 36.9231 8.79121 36.9231H21.4505ZM8.79121 41.1428C8.01437 41.1428 7.38462 41.7726 7.38462 42.5494V55.2088C7.38462 55.9856 8.01437 56.6154 8.79121 56.6154H21.4505C22.2274 56.6154 22.8571 55.9856 22.8571 55.2088V42.5494C22.8571 41.7726 22.2274 41.1428 21.4505 41.1428H8.79121ZM55.2088 3.0769C58.3162 3.0769 60.8352 5.59592 60.8352 8.70328V21.3626C60.8352 24.47 58.3162 26.989 55.2088 26.989H42.5495C39.4421 26.989 36.9231 24.47 36.9231 21.3626V8.70328C36.9231 5.59592 39.4421 3.0769 42.5495 3.0769H55.2088ZM42.5495 7.29668C41.7726 7.29668 41.1429 7.92644 41.1429 8.70328V21.3626C41.1429 22.1395 41.7726 22.7692 42.5495 22.7692H55.2088C55.9856 22.7692 56.6154 22.1395 56.6154 21.3626V8.70328C56.6154 7.92644 55.9856 7.29668 55.2088 7.29668H42.5495Z" fill="#1C1B1A"/> 4 + <path d="M42.5495 50.989C44.4916 50.989 46.0659 52.5634 46.0659 54.5055C46.0659 56.4476 44.4916 58.022 42.5495 58.022C40.6073 58.022 39.033 56.4476 39.033 54.5055C39.033 52.5634 40.6073 50.989 42.5495 50.989ZM55.2088 50.989C57.1509 50.989 58.7253 52.5634 58.7253 54.5055C58.7253 56.4476 57.1509 58.022 55.2088 58.022C53.2667 58.022 51.6923 56.4476 51.6923 54.5055C51.6923 52.5634 53.2667 50.989 55.2088 50.989ZM48.8791 38.3297C50.8212 38.3297 52.3956 39.904 52.3956 41.8461C52.3956 43.7882 50.8212 45.3626 48.8791 45.3626C46.937 45.3626 45.3626 43.7882 45.3626 41.8461C45.3626 39.904 46.937 38.3297 48.8791 38.3297Z" fill="#8B7EC8"/> 5 + </svg>
+3
public/atmosphere-icons/logo-sill.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M29.9516 19.0014C29.9516 21.5145 32.2989 22.3872 34.4481 22.8395C37.4272 23.4664 41.9968 24.0448 47.9303 26.0939C53.9885 28.1861 57.0388 31.8749 58.3149 35.9691C59.5785 40.0233 59.0816 44.4042 58.2076 47.8948C57.2939 51.5441 54.161 55.3739 49.2097 58.2794C44.2439 61.1933 37.4028 63.2094 28.9652 63.2094C20.5711 63.2094 15.0339 62.0758 11.2004 60.5422C7.35309 59.0031 5.25812 57.0742 3.74235 55.5627C2.41112 54.2352 1.70963 51.9972 1.34754 49.8262C0.984891 47.6517 0.938245 45.4522 1.06101 43.2561H23.9101C23.9396 45.114 24.3276 46.4883 26.011 47.426C26.6674 47.7917 28.5096 48.0569 29.8728 48.1465C31.7343 48.2688 34.1484 48.0908 35.5093 46.6025C35.9119 46.162 36.1564 45.5931 36.1048 44.8043C36.0343 43.7289 35.4854 42.9525 34.4929 42.3246C33.4708 41.678 32.0162 41.2177 30.2386 40.82C28.4627 40.4228 26.4591 40.1064 24.3276 39.7069C22.2131 39.3106 20.0032 38.8369 17.8943 38.134C13.6464 36.718 10.7402 34.4591 8.96473 31.5084C7.19494 28.5671 6.58817 25.0034 6.80927 21.0436C7.27546 12.6962 14.7855 2.1961 31.3529 1.19179C47.6976 0.201205 55.5271 3.16215 59.5436 7.43765C61.184 9.18389 62.0737 11.5996 62.5032 13.884C62.9334 16.1724 62.9163 18.4061 62.6777 19.8598L62.594 20.3656H40.174L40.1292 19.8103C39.9025 16.9692 39.1416 15.6338 35.0955 15.6338C33.0407 15.6338 29.9516 16.4884 29.9516 19.0014Z" fill="#A06E00"/> 3 + </svg>
+3
public/atmosphere-icons/logo-spark.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M38.1678 54.9961C39.0793 58.3988 37.0597 61.8959 33.6571 62.8076C33.1188 62.9518 32.564 63.0254 32.0067 63.0254C28.4839 63.0254 25.6278 60.1693 25.6278 56.6465C25.6278 56.0893 25.7004 55.5343 25.8446 54.9961L32.0067 32L38.1678 54.9961ZM15.1483 48.9316C12.6662 51.4245 8.63331 51.4332 6.14047 48.9512C5.74109 48.5535 5.39635 48.1046 5.11508 47.6162C3.34725 44.5464 4.40271 40.6253 7.47251 38.8574C7.95166 38.5815 8.46417 38.368 8.9979 38.2236L32.0067 32L15.1483 48.9316ZM55.0223 38.0879C58.3886 38.9782 60.3961 42.4286 59.5057 45.7949C59.3605 46.3439 59.1416 46.8709 58.8553 47.3613C57.0702 50.4192 53.1438 51.451 50.0858 49.666C49.6172 49.3925 49.1856 49.0601 48.8006 48.6777L32.0067 32L55.0223 38.0879ZM32.1141 0.974609C35.6045 0.974754 38.4343 3.80455 38.4344 7.29492C38.4344 7.84987 38.3609 8.40262 38.2166 8.93848L32.0067 32L25.9598 8.95215C25.0681 5.55339 27.1002 2.07551 30.4989 1.18359C31.026 1.0453 31.5692 0.974609 32.1141 0.974609ZM48.8817 15.1914C51.3736 12.7096 55.4055 12.7181 57.8875 15.21C58.2757 15.5996 58.612 16.0377 58.8875 16.5137C60.6426 19.5463 59.6067 23.4276 56.5741 25.1826C56.093 25.461 55.5776 25.6753 55.0409 25.8193L32.0067 32L48.8817 15.1914ZM5.15024 16.4248C6.91532 13.3754 10.8186 12.3337 13.868 14.0986C14.3521 14.3789 14.7975 14.7219 15.1922 15.1182L32.0067 32L9.01645 25.7949C5.60923 24.8754 3.59217 21.3682 4.51157 17.9609C4.65665 17.4234 4.87134 16.9067 5.15024 16.4248Z" fill="#FF0090"/> 3 + </svg>
+3
public/atmosphere-icons/logo-surf.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M1.1106 63.1671H62.6904V56.7437C40.2089 56.7437 36.3543 49.0834 35.1047 41.8962C33.666 33.6213 37.5348 27.0374 40.0017 25.129C39.5828 27.5028 40.105 32.4311 42.5909 34.5793C45.5322 37.1212 57.6484 40.035 61.4916 29.3363C66.6581 14.9538 56.686 4.9386 44.9565 2.00623C33.227 -0.926139 23.0588 1.54355 12.8653 10.4803C4.71056 17.6297 1.1106 29.3363 1.1106 35.6587V63.1671Z" fill="#007E7E"/> 3 + </svg>
+3
public/atmosphere-icons/logo-tangled.svg
··· 1 + <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M42.1942 62.2061C40.1132 62.1895 38.5255 61.5978 36.8033 60.5694C34.3336 59.2985 32.4473 57.1634 31.0995 54.8093C28.9577 57.4086 26.0952 58.9857 22.8906 59.8767C21.5261 60.2643 19.1362 60.6575 15.1747 59.2536C9.46554 57.3775 5.30684 51.5664 5.77946 45.6454C5.693 43.191 6.60783 40.782 7.90455 38.7112C4.44529 36.8949 1.6245 33.8461 0.544296 30.1071C-0.112146 28.0602 -0.084542 25.8552 0.157525 23.751C1.02443 18.7831 4.83393 14.4631 9.73824 12.9093C11.6958 8.54547 15.9676 5.29133 20.8073 4.62882C24.0207 4.1911 27.3471 4.84916 30.1583 6.44676C34.2544 2.00297 41.3903 0.689689 46.8391 3.41949C50.9955 5.36113 53.9677 9.41209 54.6894 13.8295C58.6443 15.3794 61.9754 18.5401 63.2827 22.5526C64.1568 25.0368 64.1857 27.7732 63.6196 30.324C62.6082 34.3042 59.7359 37.6927 56.0181 39.5447C56.0271 40.2531 58.4075 45.3603 58.0093 49.2145C57.9223 54.0331 54.798 58.5998 50.465 60.818C47.9366 62.2616 44.9403 62.2344 42.1942 62.2061ZM30.3466 48.3357C33.8511 47.9539 36.1485 44.9649 37.9329 42.273C38.7765 41.0468 39.4209 39.6743 40.0612 38.3689C40.8915 39.1134 41.5951 40.5159 42.9082 40.8499C44.2914 41.2713 45.9131 40.929 46.7599 39.6999C48.3805 36.7431 47.5817 33.1753 46.638 30.1112C46.0569 28.3514 45.2944 26.546 43.8436 25.2985C44.153 23.1635 42.8597 20.9952 41.0211 19.8776C39.4543 21.0998 37.0703 21.0924 35.5588 19.7851C32.6618 22.6753 30.0069 22.5794 27.4425 20.2888C26.8661 19.774 25.7664 23.431 21.907 21.3594C19.6898 23.1767 17.9705 24.9249 16.4471 27.4421C14.9668 30.1558 13.4166 32.5658 13.283 35.5127C13.2188 37.2351 14.5946 39.0397 16.4588 38.8996C18.3221 39.0624 19.5904 37.2686 21.0012 36.5235C21.2116 38.9272 21.4486 41.5098 22.279 43.8565C23.2322 46.8932 26.5893 48.8233 29.767 48.3813C29.9918 48.3642 30.3466 48.3354 30.3466 48.3357ZM32.1657 39.2678C30.4611 38.2458 31.2814 36.0279 31.2131 34.417C31.3827 32.4731 31.5188 30.4293 32.4122 28.6583C33.3577 27.3957 35.6635 27.8828 35.7653 29.5027C35.6975 31.1323 34.9328 32.7544 35.0242 34.4436C34.8258 35.8542 35.1678 37.4385 34.5299 38.7277C34.0066 39.4411 32.9406 39.6484 32.1657 39.2678ZM24.7212 38.3393C23.1157 37.4871 23.6258 35.343 23.3739 33.8523C23.5827 32.1264 23.4089 29.9371 24.8861 28.7268C26.3307 27.7413 28.297 29.4289 27.6138 30.9783C26.8852 32.9363 27.3627 35.0756 27.3781 37.061C27.1025 38.2321 25.822 38.8538 24.7212 38.3393Z" fill="#ffffff"/> 3 + </svg>
-1
public/checkout-one-time-payments.svg
··· 1 - <svg height="156" viewBox="0 0 240 156" width="240" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd" transform="translate(0 1)"><rect fill="#fff" height="154" opacity=".8" rx="4" width="240"/><path d="m99 0v154" opacity=".068034" stroke="#000" stroke-linecap="square"/><text style="opacity:.836844;font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;font-size:18;font-weight:500;letter-spacing:-.45;fill:#8f6ed5"><tspan x="14" y="48">$29.90</tspan></text><path d="m18 17h23c1.1045695 0 2 .8954305 2 2s-.8954305 2-2 2h-23c-1.1045695 0-2-.8954305-2-2s.8954305-2 2-2z" fill="#8f6ed5"/><g transform="translate(112 109)"><path d="m3.58943928 0h109.02112172c1.248126 0 1.700727.12995586 2.157023.37398579s.8144.60213393 1.05843 1.05843023c.24403.45629629.373986.90889702.373986 2.15702326v12.42112142c0 1.2481263-.129956 1.700727-.373986 2.1570233s-.602134.8144003-1.05843 1.0584302-.908897.3739858-2.157023.3739858h-109.02112172c-1.24812624 0-1.70072697-.1299559-2.15702326-.3739858-.4562963-.2440299-.8144003-.6021339-1.05843023-1.0584302s-.37398579-.908897-.37398579-2.1570233v-12.42112142c0-1.24812624.12995586-1.70072697.37398579-2.15702326.24402993-.4562963.60213393-.8144003 1.05843023-1.05843023.45629629-.24402993.90889702-.37398579 2.15702326-.37398579z" fill="#8f6ed5"/><text style="opacity:.7;font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;font-size:10;font-weight:500;letter-spacing:.12;fill:#f7fafc"><tspan x="29" y="14">Pay $29.90</tspan></text></g><g transform="translate(112 83)"><path d="m3.58943928.35c-1.08510563 0-1.53103464.08611287-1.99196366.33262041-.39530234.21141-.70344521.51955287-.91485521.91485521-.24650754.46092902-.33262041.90685803-.33262041 1.99196366v12.42112142c0 1.0851056.08611287 1.5310347.33262041 1.9919637.21141.3953023.51955287.7034452.91485521.9148552.46092902.2465075.90685803.3326204 1.99196366.3326204h109.02112172c1.085105 0 1.531034-.0861129 1.991963-.3326204.395303-.21141.703446-.5195529.914856-.9148552.246507-.460929.33262-.9068581.33262-1.9919637v-12.42112142c0-1.08510563-.086113-1.53103464-.33262-1.99196366-.21141-.39530234-.519553-.70344521-.914856-.91485521-.460929-.24650754-.906858-.33262041-1.991963-.33262041z" fill="#fff" opacity=".8" stroke="#8f6ed5" stroke-opacity=".266253" stroke-width=".7"/><g fill-rule="nonzero" opacity=".5" transform="translate(95.2 4.2)"><rect fill="#ebf1f8" height="10.7" rx="1.4" stroke="#a450b5" stroke-width=".5" width="16.3" x=".25" y=".25"/><path d="m2.30141283 4.14010612c-.36619921-.20085195-.7841356-.36238968-1.25141283-.47449094l.01960035-.08729771h1.91588511c.25968832.00910242.47040833.08723662.53897699.36318047l.41637443 1.98511543.12755149.59789495 1.1661881-2.94619085h1.2591758l-1.87173549 4.31595242h-1.25924092zm5.11856981 3.75874553h-1.1908025l.7448132-4.32053418h1.19073738zm4.31676486-4.21490945-.1619471.93296757-.1077042-.04587865c-.2154736-.0873588-.4999065-.17465651-.8870297-.16543191-.4701478 0-.68099808.18834069-.68588189.3722218 0 .20226923.25506499.33556776.67155609.53325523.6860773.30795505 1.0043062.6848197.9995526 1.17665586-.0096374.89631352-.8230844 1.47550848-2.07255766 1.47550848-.53422342-.00464284-1.04878137-.11057303-1.32807004-.22994303l.16663551-.96986596.15680278.06903178c.38712314.16103343.64186253.22982085 1.11728491.22982085.34284328 0 .7104312-.13342072.7151196-.42286548 0-.18846286-.1566074-.32646533-.61731322-.53789807-.45074287-.20691207-1.05340471-.55158225-1.04363709-1.17213519.00507916-.8410881.83317755-1.42938548 2.00913331-1.42938548.4606407 0 .8331775.09652231 1.0680561.1839422zm1.5826792 2.68429772h.989785c-.0489683-.21601449-.27447-1.2502083-.27447-1.2502083l-.0832201-.37228289c-.058801.16085015-.1616214.42286547-.1566725.41364087 0 0-.3773555.96064136-.4754224 1.20885032zm1.4698958-2.78992245.9606775 4.32047309h-1.1025684s-.1078996-.49641792-.1420862-.64810457h-1.5288922c-.0442148.11484934-.2499207.64810457-.2499207.64810457h-1.2494733l1.7687848-3.96199655c.122551-.28040343.3383502-.35847654.6223924-.35847654z" fill="#8f6ed5"/></g><g fill="#1a1f36" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" font-size="8.4" font-weight="500"><text opacity=".67"><tspan x="5.6" y="12.9">4242</tspan></text><text opacity=".67"><tspan x="33.6" y="12.9">11/26</tspan></text><text opacity=".67"><tspan x="61.6" y="12.9">934</tspan></text></g></g><g transform="translate(112 57)"><path d="m3.58943928.35c-1.08510563 0-1.53103464.08611287-1.99196366.33262041-.39530234.21141-.70344521.51955287-.91485521.91485521-.24650754.46092902-.33262041.90685803-.33262041 1.99196366v12.42112142c0 1.0851056.08611287 1.5310347.33262041 1.9919637.21141.3953023.51955287.7034452.91485521.9148552.46092902.2465075.90685803.3326204 1.99196366.3326204h109.02112172c1.085105 0 1.531034-.0861129 1.991963-.3326204.395303-.21141.703446-.5195529.914856-.9148552.246507-.460929.33262-.9068581.33262-1.9919637v-12.42112142c0-1.08510563-.086113-1.53103464-.33262-1.99196366-.21141-.39530234-.519553-.70344521-.914856-.91485521-.460929-.24650754-.906858-.33262041-1.991963-.33262041z" fill="#fff" opacity=".8" stroke="#8f6ed5" stroke-opacity=".266253" stroke-width=".7"/><text fill="#1a1f36" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" font-size="8.4" font-weight="500" opacity=".67"><tspan x="5.6" y="13.6">Jenny Rosen</tspan></text></g><g transform="translate(112 31)"><path d="m3.58943928.35c-1.08510563 0-1.53103464.08611287-1.99196366.33262041-.39530234.21141-.70344521.51955287-.91485521.91485521-.24650754.46092902-.33262041.90685803-.33262041 1.99196366v12.42112142c0 1.0851056.08611287 1.5310347.33262041 1.9919637.21141.3953023.51955287.7034452.91485521.9148552.46092902.2465075.90685803.3326204 1.99196366.3326204h109.02112172c1.085105 0 1.531034-.0861129 1.991963-.3326204.395303-.21141.703446-.5195529.914856-.9148552.246507-.460929.33262-.9068581.33262-1.9919637v-12.42112142c0-1.08510563-.086113-1.53103464-.33262-1.99196366-.21141-.39530234-.519553-.70344521-.914856-.91485521-.460929-.24650754-.906858-.33262041-1.991963-.33262041z" fill="#fff" opacity=".8" stroke="#8f6ed5" stroke-opacity=".266253" stroke-width=".7"/><text fill="#1a1f36" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" font-size="8.4" font-weight="500" opacity=".67"><tspan x="5.6" y="13.6">jenny@rosen.com</tspan></text></g></g></svg>
public/checkout_demo.gif

This is a binary file and will not be displayed.

public/earth.png

This is a binary file and will not be displayed.

public/earth2.jpg

This is a binary file and will not be displayed.

-1
public/elements-card-payment.svg
··· 1 - <svg height="64" viewBox="0 0 202 64" width="202" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><rect fill="#fff" height="28" opacity=".8" rx="4" width="202"/><g transform="translate(0 36)"><rect fill="#4e5663" height="28" rx="4" width="202"/><text style="opacity:.7;font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;font-size:14;font-weight:500;letter-spacing:-.154;fill:#fff"><tspan x="63" y="19">Pay $29.90</tspan></text></g><text fill="#1a1f36" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" font-size="12" font-weight="500" opacity=".797503"><tspan x="9" y="19">4242 4242 4242 4242</tspan></text><g fill-rule="nonzero" opacity=".5" transform="translate(171 6)"><rect height="15.5" rx="2" stroke="#4f566b" stroke-width=".5" width="23.5" x=".25" y=".25"/><path d="m3.28773262 5.91443732c-.52314173-.28693137-1.12019372-.51769955-1.78773262-.6778442l.0280005-.12471102h2.73697872c.37098332.01300346.67201191.12462375.76996714.51882925l.59482061 2.83587917.18221641.85413565 1.66598301-4.20884407h1.79882257l-2.67390785 6.1656463h-1.79891559zm7.31224258 5.36963648h-1.70114643l1.06401886-6.1721917h1.70105337zm6.1668069-6.02129922-.2313529 1.3328108-.1538632-.06554092c-.3078194-.12479829-.7141522-.2495093-1.2671852-.2363313-.6716398 0-.9728545.26905813-.9798314.53174543 0 .28895604.3643786.47938251.9593659.76179318.9801104.43993579 1.4347231.97831385 1.4279323 1.68093694-.0137677 1.28044789-1.1758348 2.10786929-2.9607967 2.10786929-.7631763-.0066327-1.4982591-.1579615-1.8972429-.3284901l.2380507-1.38552277.224004.09861682c.5530331.23004776.9169465.32831555 1.5961213.32831555.4897761 0 1.0149017-.19060107 1.0215995-.60409358 0-.26923267-.2237249-.46637906-.8818761-.76842582-.6439184-.29558867-1.5048639-.78797464-1.4909101-1.67447884.0072559-1.20155443 1.1902536-2.04197926 2.8701904-2.04197926.6580581 0 1.1902536.13788902 1.5257944.26277458zm2.2609703 3.83471102h1.4139786c-.0699548-.30859213-.3921-1.78601186-.3921-1.78601186l-.1188858-.5318327c-.0840015.22978594-.2308878.60409353-.2238179.59091553 0 0-.5390794 1.3723448-.6791749 1.72692903zm2.0998512-3.9856035 1.3723964 6.1721044h-1.5750977s-.1541422-.7091684-.2029803-.9258637h-2.1841317c-.0631639.1640705-.3570296.9258637-.3570296.9258637h-1.7849619l2.5268355-5.65999506c.1750729-.40057632.4833574-.51210934.889132-.51210934z" fill="#3c4257"/></g></g></svg>
public/elements_demo.gif

This is a binary file and will not be displayed.

public/favicon-96x96.png

This is a binary file and will not be displayed.

public/favicon.ico

This is a binary file and will not be displayed.

+12
public/favicon.svg
··· 1 + <svg 2 + width="150" 3 + height="150" 4 + viewBox="0 0 150 150" 5 + fill="none" 6 + xmlns="http://www.w3.org/2000/svg" 7 + > 8 + <path 9 + d="M143.619 35.5547C139.137 27.8262 127.307 26.0859 109.342 30.4805C101.025 24.0495 91.0706 20.08 80.6105 19.0229C70.1504 17.9658 59.6035 19.8635 50.1679 24.5004C40.7323 29.1373 32.7863 36.3276 27.2325 45.2544C21.6788 54.1812 18.74 64.4866 18.7499 75C18.7506 77.4115 18.9033 79.8206 19.2069 82.2129C2.9823 99.0234 3.21668 108.984 6.3866 114.445C9.37488 119.625 15.6093 121.875 23.8124 121.875C29.5078 121.757 35.1697 120.971 40.6815 119.531C48.9996 125.956 58.9523 129.92 69.4098 130.973C79.8672 132.026 90.4104 130.126 99.8423 125.488C109.274 120.851 117.217 113.661 122.769 104.737C128.32 95.8126 131.259 85.5103 131.25 75C131.251 72.6003 131.1 70.2029 130.799 67.8223C138.123 60.2051 142.998 52.9688 144.656 46.7754C145.799 42.4863 145.453 38.7129 143.619 35.5547ZM74.9999 28.125C85.6167 28.1359 95.9163 31.7457 104.217 38.365C112.518 44.9844 118.329 54.2222 120.703 64.5703C110.707 73.9805 97.1776 83.6309 84.3339 91.0137C68.1913 100.277 54.1874 106.055 43.0194 109.219C36.1409 102.803 31.3532 94.4659 29.2795 85.2915C27.2059 76.1171 27.9423 66.5309 31.393 57.7809C34.8437 49.0309 40.8488 41.5224 48.6264 36.233C56.4041 30.9437 65.5941 28.1184 74.9999 28.125ZM14.496 109.74C13.6405 108.27 14.1151 105.498 15.7968 102.123C17.4597 98.9609 19.4829 96.0018 21.8261 93.3047C24.1487 100.034 27.7277 106.262 32.3729 111.656C22.2655 113.355 15.9608 112.271 14.496 109.74ZM74.9999 121.875C67.0963 121.883 59.3209 119.879 52.4061 116.051C65.0981 111.562 77.3443 105.901 88.9862 99.1406C101.631 91.8809 112.822 84.0117 121.84 76.2422C121.506 88.4482 116.426 100.043 107.68 108.564C98.934 117.085 87.2104 121.86 74.9999 121.875ZM135.598 44.3496C134.601 48.0469 131.971 52.2774 128.197 56.7305C125.881 49.9929 122.301 43.7587 117.65 38.3613C125.976 36.9844 133.687 37.0899 135.521 40.2598C136.049 41.1797 136.078 42.5567 135.598 44.3496Z" 10 + fill="black" 11 + /> 12 + </svg>
public/jupiter.jpg

This is a binary file and will not be displayed.

public/jupiter2.png

This is a binary file and will not be displayed.

public/logo.png

This is a binary file and will not be displayed.

+3
public/logo.svg
··· 1 + <svg width="150" height="150" viewBox="0 0 150 150" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M143.619 35.5547C139.137 27.8262 127.307 26.0859 109.342 30.4805C101.025 24.0495 91.0706 20.08 80.6105 19.0229C70.1504 17.9658 59.6035 19.8635 50.1679 24.5004C40.7323 29.1373 32.7863 36.3276 27.2325 45.2544C21.6788 54.1812 18.74 64.4866 18.7499 75C18.7506 77.4115 18.9033 79.8206 19.2069 82.2129C2.9823 99.0234 3.21668 108.984 6.3866 114.445C9.37488 119.625 15.6093 121.875 23.8124 121.875C29.5078 121.757 35.1697 120.971 40.6815 119.531C48.9996 125.956 58.9523 129.92 69.4098 130.973C79.8672 132.026 90.4104 130.126 99.8423 125.488C109.274 120.851 117.217 113.661 122.769 104.737C128.32 95.8126 131.259 85.5103 131.25 75C131.251 72.6003 131.1 70.2029 130.799 67.8223C138.123 60.2051 142.998 52.9688 144.656 46.7754C145.799 42.4863 145.453 38.7129 143.619 35.5547ZM74.9999 28.125C85.6167 28.1359 95.9163 31.7457 104.217 38.365C112.518 44.9844 118.329 54.2222 120.703 64.5703C110.707 73.9805 97.1776 83.6309 84.3339 91.0137C68.1913 100.277 54.1874 106.055 43.0194 109.219C36.1409 102.803 31.3532 94.4659 29.2795 85.2915C27.2059 76.1171 27.9423 66.5309 31.393 57.7809C34.8437 49.0309 40.8488 41.5224 48.6264 36.233C56.4041 30.9437 65.5941 28.1184 74.9999 28.125ZM14.496 109.74C13.6405 108.27 14.1151 105.498 15.7968 102.123C17.4597 98.9609 19.4829 96.0018 21.8261 93.3047C24.1487 100.034 27.7277 106.262 32.3729 111.656C22.2655 113.355 15.9608 112.271 14.496 109.74ZM74.9999 121.875C67.0963 121.883 59.3209 119.879 52.4061 116.051C65.0981 111.562 77.3443 105.901 88.9862 99.1406C101.631 91.8809 112.822 84.0117 121.84 76.2422C121.506 88.4482 116.426 100.043 107.68 108.564C98.934 117.085 87.2104 121.86 74.9999 121.875ZM135.598 44.3496C134.601 48.0469 131.971 52.2774 128.197 56.7305C125.881 49.9929 122.301 43.7587 117.65 38.3613C125.976 36.9844 133.687 37.0899 135.521 40.2598C136.049 41.1797 136.078 42.5567 135.598 44.3496Z" fill="white"/> 3 + </svg>
+5
public/logo2.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="1280" height="1280"> 3 + <path d="M0 0 C0.81952148 0.37697021 1.63904297 0.75394043 2.48339844 1.14233398 C11.60285155 5.34423447 20.53345418 9.57571453 29 15 C30.18360833 15.72476307 31.36863018 16.44722038 32.5546875 17.16796875 C46.72974953 25.82640202 60.36518708 35.19579918 73 46 C74.16665776 46.99219797 75.33332501 47.98438479 76.5 48.9765625 C79.49524674 51.52960075 82.4772543 54.09757669 85.45507812 56.67089844 C86.77004037 57.80216495 88.09493747 58.92186671 89.421875 60.0390625 C93.40501694 63.42010158 96.85096472 66.9899968 100.2265625 70.9765625 C102.02461917 73.02808972 103.9157426 74.91519541 105.875 76.8125 C117.27976871 88.08567523 126.98680285 101.77032865 136 115 C136.72445312 116.02609375 137.44890625 117.0521875 138.1953125 118.109375 C149.2185272 133.93422347 158.34831911 151.30931379 166 169 C166.47308594 170.08667969 166.94617188 171.17335938 167.43359375 172.29296875 C173.60118867 187.08516795 178.77580507 202.5412441 183 218 C191.44559799 218.17788528 199.80780198 217.69099294 208.22385406 217.07402039 C210.57253644 216.90208377 212.92154201 216.73537984 215.27069092 216.56994629 C221.9422003 216.09910602 228.612987 215.61832316 235.28369141 215.13623047 C239.38744579 214.84000895 243.49154851 214.54903854 247.5958786 214.26091003 C249.88180192 214.09880775 252.16722718 213.93067445 254.45269775 213.7623291 C261.35894704 213.26645294 268.26668378 212.8695614 275.19042969 212.74414062 C276.94356476 212.70673767 276.94356476 212.70673767 278.7321167 212.6685791 C283.6286285 213.1651716 286.87960948 214.81736556 290.25 218.375 C292.86510786 222.2976618 294.04899829 224.65254715 293.875 229.4375 C292.5211383 234.9496512 290.58481365 237.89055902 285.91914368 241.15673828 C279.09492723 244.37226141 271.22051996 243.4377612 263.85620117 243.3046875 C261.98679061 243.28616696 260.11736129 243.26947191 258.24792004 243.25436401 C253.95263776 243.21536571 249.65777666 243.1624677 245.36275864 243.10095215 C238.03405749 242.99698969 230.70519033 242.92239103 223.37612181 242.85097337 C205.08949117 242.67173396 186.80341632 242.45106706 168.51730435 242.22583044 C159.25423381 242.11181257 149.99112738 242.00084257 140.72801854 241.88998723 C124.2191264 241.69234224 107.71026259 241.49242862 91.20141602 241.29101562 C75.19850098 241.09578017 59.19557304 240.90165839 43.19262695 240.70898438 C42.20029355 240.69703639 41.20796015 240.68508841 40.18555603 240.67277837 C35.20554558 240.6128243 30.22553488 240.5528916 25.24552405 240.49296951 C-15.83635763 239.99862339 -56.91819366 239.50056505 -98 239 C-98 238.34 -98 237.68 -98 237 C-94.0772445 236.11799576 -90.25605616 235.73677137 -86.24584961 235.47509766 C-85.58342034 235.43094601 -84.92099108 235.38679436 -84.2384882 235.34130478 C-82.04330016 235.19576448 -79.84783634 235.05492764 -77.65234375 234.9140625 C-76.09722926 234.81179793 -74.54213522 234.70922196 -72.98706055 234.60635376 C-68.83005453 234.33214466 -64.67280103 234.06187973 -60.51548386 233.79243469 C-56.21599178 233.51319162 -51.91671364 233.23069836 -47.61743164 232.94824219 C-46.76663497 232.89235176 -45.9158383 232.83646133 -45.03925991 232.77887726 C-43.32703585 232.66639738 -41.61481248 232.55390708 -39.9025898 232.44140625 C-37.34604683 232.27358827 -34.78947358 232.10623782 -32.2328949 231.93896484 C-22.87255654 231.32580498 -13.51349711 230.69804944 -4.15625 230.0390625 C-3.17010208 229.96968979 -2.18395416 229.90031708 -1.16792297 229.82884216 C0.69423473 229.69778159 2.55639194 229.56671403 4.41854858 229.43563843 C20.27341435 228.32242873 36.1087474 227.41589311 52 227 C28.48303999 174.33120936 -8.88782019 132.94486147 -63.59375 111.59765625 C-67.04662044 110.3410253 -70.50394586 109.12915527 -74 108 C-74.94004883 107.69078613 -75.88009766 107.38157227 -76.84863281 107.06298828 C-118.45317339 93.75330041 -164.24458983 95.77523221 -205 111 C-205.8161377 111.30276855 -206.63227539 111.60553711 -207.47314453 111.91748047 C-230.53456122 120.64579466 -252.10337515 134.03226571 -270 151 C-271.68585984 152.48103575 -273.37338885 153.96017343 -275.0625 155.4375 C-300.22364275 178.21166031 -318.80195062 210.61137709 -328.39599609 242.97558594 C-328.95177564 244.83836846 -329.54636871 246.68945411 -330.14453125 248.5390625 C-333.58184819 259.94529026 -334.52692461 271.69369358 -335.67456055 283.51074219 C-336 286 -336 286 -337 289 C-336.24820213 288.98955375 -335.49640427 288.97910749 -334.72182465 288.96834469 C-293.24246821 288.39439767 -251.76291629 287.90813975 -210.28125 287.53515625 C-209.23160655 287.52569292 -208.1819631 287.5162296 -207.10051227 287.5064795 C-197.31794611 287.41828419 -187.53537512 287.3306339 -177.75279903 287.24354649 C-106.47918426 286.60890316 -35.20721591 285.9227042 36.0625 284.9375 C37.62000779 284.91601508 39.17751562 284.89453324 40.7350235 284.8730545 C55.2741428 284.67240874 69.8132208 284.468893 84.3522644 284.26283836 C136.85791209 283.51880763 189.36409672 282.94243828 241.87305307 282.48904628 C246.38426787 282.45004984 250.8954738 282.41012889 255.40667725 282.36984253 C268.67279676 282.25224972 281.93888756 282.1470754 295.20529938 282.068326 C301.35536669 282.03155845 307.50527833 281.98835802 313.6552124 281.93341064 C319.95170712 281.87751368 326.2481379 281.8366901 332.54480553 281.80629158 C334.91375068 281.79235237 337.28267174 281.77321585 339.65152931 281.74853325 C342.91841738 281.71539305 346.18487402 281.70125976 349.4519043 281.69165039 C350.40687742 281.67755945 351.36185055 281.66346851 352.34576225 281.64895058 C360.63382175 281.65973849 367.26181189 283.53746305 373.4609375 289.26953125 C377.91126877 294.27333011 380.10440405 300.31814082 380 307 C379.2633535 313.73505373 376.30879778 319.88072763 371.36328125 324.54296875 C364.94911712 329.45809228 358.17568314 330.31464934 350.3125 330.1875 C349.60544922 330.18685547 348.89839844 330.18621094 348.16992188 330.18554688 C342.52031747 330.14249316 336.8900743 329.84474055 331.25 329.54296875 C319.50622724 328.92311547 307.75605631 328.61867614 296.00097179 328.29819489 C271.19987653 327.62177489 246.41454064 326.76666647 221.62908173 325.65774918 C188.37191297 324.16991624 155.10709618 323.11636312 121.83016777 322.17552948 C116.83594671 322.03412419 111.84178383 321.89076116 106.84765625 321.74609375 C105.86691006 321.71772808 104.88616386 321.68936241 103.87569809 321.66013718 C87.60406101 321.18452577 71.34266729 320.53954986 55.07943153 319.83660507 C38.37624292 319.1161931 21.67655252 318.57284445 4.96310425 318.16629028 C-22.95005425 317.4841153 -50.84562012 316.51288028 -78.74337769 315.37091064 C-83.50076148 315.17617174 -88.25817341 314.98213834 -93.015625 314.7890625 C-94.21104007 314.74052061 -94.21104007 314.74052061 -95.43060493 314.69099808 C-116.38782218 313.84312763 -137.35012931 313.14386423 -158.3125 312.4375 C-181.3783415 311.65978759 -204.44001782 310.86464293 -227.49557495 309.81860352 C-248.019523 308.89296795 -268.55379362 308.29634458 -289.08935547 307.69702148 C-305.06426974 307.2287885 -321.03269911 306.68195513 -337 306 C-332.83721069 350.28271298 -321.03864146 390.35389674 -292 425 C-291.54044922 425.54978516 -291.08089844 426.09957031 -290.60742188 426.66601562 C-270.49209967 450.66278202 -245.21131168 471.03688217 -216 483 C-214.86433594 483.47953125 -213.72867187 483.9590625 -212.55859375 484.453125 C-166.45230384 503.6473276 -113.04922114 506.33421506 -66.0625 488.125 C-63.69932313 487.10393917 -61.34516891 486.06176878 -59 485 C-57.64873805 484.42117287 -56.29716258 483.84307723 -54.9453125 483.265625 C-36.87201051 475.35334032 -15.51439117 463.69376054 -7.625 444.6875 C-6.23861212 436.50781149 -7.30923154 428.90899331 -12 422 C-15.78006204 416.99967521 -19.59482757 413.24310346 -25 410 C-25.84498047 409.37931641 -25.84498047 409.37931641 -26.70703125 408.74609375 C-39.74845449 399.30585247 -55.43098238 393.79178019 -70.59179688 388.79980469 C-72.8874013 388.03739592 -75.17098743 387.24700731 -77.453125 386.4453125 C-94.46665541 380.5215192 -111.97492709 376.24400154 -129.58813477 372.51586914 C-131.42643526 372.12267864 -133.26247165 371.71888686 -135.09741211 371.31030273 C-143.83687428 369.38482551 -152.59916928 367.83348946 -161.4375 366.4375 C-163.37206055 366.12522461 -163.37206055 366.12522461 -165.34570312 365.80664062 C-174.21378779 364.39005625 -183.09361855 363.14600372 -192 362 C-192 361.01 -192 360.02 -192 359 C-174.93963303 359.24208307 -157.87928634 359.48554849 -140.81896019 359.73049068 C-132.89054582 359.84429281 -124.96212626 359.95770164 -117.03369141 360.07006836 C-107.84275483 360.20037598 -98.65183887 360.33207676 -89.4609375 360.46484375 C-88.70015616 360.47580755 -87.93937483 360.48677135 -87.15553951 360.49806738 C-67.8765974 360.77615397 -48.59910296 361.09006679 -29.32185745 361.47047615 C-3.01784746 361.98873757 23.28473973 362.25424325 49.59298706 362.44555664 C62.43835546 362.5390792 75.28362534 362.64526654 88.12890625 362.75 C89.4088553 362.76035782 90.68880436 362.77071564 92.00753975 362.78138733 C124.73477588 363.04668073 157.46095613 363.38671159 190.18638611 363.82156372 C198.45325137 363.93116943 206.72007292 364.0313398 214.98725033 364.11433029 C220.94016887 364.17467005 226.89280754 364.24914014 232.8454895 364.32983398 C235.19819474 364.35941695 237.55096674 364.38417571 239.90377808 364.40356445 C243.03906095 364.43013636 246.17359396 364.47440242 249.30859375 364.5234375 C250.20195435 364.52665009 251.09531494 364.52986267 252.01574707 364.53317261 C257.39856495 364.64128791 261.2242674 365.45955875 266 368 C267.70091875 370.21858967 267.95238868 371.69052639 268.375 374.4375 C267.86233872 377.94068541 266.47871818 379.52128182 264 382 C261.14387256 382.97054331 258.50107568 383.12186828 255.5 383.140625 C237.48314124 383.46327056 220.98389724 386.36246221 205 395 C203.73542969 395.65742187 203.73542969 395.65742187 202.4453125 396.328125 C179.13021457 409.28923376 166.78509512 430.60877584 154.37109375 453.22924805 C148.12930001 464.59791958 141.71783758 475.56523937 134 486 C133.51966309 486.66 133.03932617 487.32 132.54443359 488 C126.16026194 496.76967189 119.50449706 505.24579868 112.37329102 513.421875 C111.40855875 514.53050244 110.45135077 515.64570077 109.49975586 516.765625 C104.77542249 522.27443144 99.74056099 527.44563145 94.60961914 532.57568359 C93.16718144 534.02034996 91.73298435 535.47289854 90.29882812 536.92578125 C88.93467773 538.29283203 88.93467773 538.29283203 87.54296875 539.6875 C86.71821045 540.51636719 85.89345215 541.34523438 85.04370117 542.19921875 C83 544 83 544 81 544 C81 544.66 81 545.32 81 546 C68.9840536 557.56601008 53.95203579 566.95219487 40 576 C39.09121094 576.60328125 38.18242188 577.2065625 37.24609375 577.828125 C31.76658773 581.41357702 26.21191334 584.50545563 20.31640625 587.3515625 C17.94737407 588.52910264 15.64571165 589.73445795 13.33984375 591.0234375 C1.87345416 597.39507428 -10.03038028 602.27948577 -22.27587891 606.95751953 C-24.44496308 607.78759566 -26.60489965 608.63496421 -28.76171875 609.49609375 C-50.30974428 617.74220139 -73.86861575 622.64622575 -96.75 625.1875 C-97.52223907 625.27371613 -98.29447815 625.35993225 -99.09011841 625.44876099 C-125.94408589 628.37463847 -152.22105241 627.52049032 -179 624 C-179.94004883 623.88253418 -180.88009766 623.76506836 -181.84863281 623.64404297 C-231.68341913 617.35750272 -278.44029652 597.7658453 -320 570 C-320.92425781 569.38382813 -321.84851563 568.76765625 -322.80078125 568.1328125 C-333.85919468 560.5674822 -344.14703878 552.06335109 -354 543 C-355.41207844 541.74481917 -356.8284912 540.49449073 -358.25 539.25 C-358.89324219 538.68667969 -359.53648437 538.12335937 -360.19921875 537.54296875 C-361.78999235 536.17994148 -363.42343723 534.86706017 -365.0625 533.5625 C-368.10505563 530.90835573 -370.62166258 528.08480873 -373.23046875 525.015625 C-374.83077503 523.19275957 -376.48869775 521.53961978 -378.25 519.875 C-383.20730242 514.99515543 -387.30767706 509.37557702 -391.54296875 503.87597656 C-392.98029226 502.02537438 -394.43861788 500.19381589 -395.90625 498.3671875 C-401.41672544 491.49483608 -406.44046932 484.55337566 -411 477 C-412.37430079 474.77040219 -413.74932368 472.54124935 -415.125 470.3125 C-415.79789063 469.21164062 -416.47078125 468.11078125 -417.1640625 466.9765625 C-418.57625843 464.68700229 -420.0243424 462.4356495 -421.5 460.1875 C-436.90389769 435.53092552 -447.26413521 406.07933033 -454 378 C-454.22139648 377.08911621 -454.44279297 376.17823242 -454.67089844 375.23974609 C-460.44738189 351.00141796 -463.8098876 325.9249354 -463 301 C-464.21362213 301.0104686 -465.42724426 301.02093719 -466.67764282 301.03172302 C-477.87407841 301.09810038 -489.00490254 300.81780458 -500.18492508 300.23461723 C-518.06717644 299.31075482 -535.95266072 298.67532138 -553.8515625 298.18359375 C-554.9869622 298.15226978 -556.12236191 298.12094582 -557.29216766 298.08867264 C-564.2312066 297.89827166 -571.17038034 297.7132298 -578.10961914 297.53027344 C-587.49793899 297.2825089 -596.88612916 297.0301319 -606.27421188 296.77354622 C-609.49204809 296.68655439 -612.70995627 296.60280548 -615.92788696 296.51939392 C-627.63337202 296.20732084 -639.31294993 295.7305766 -651 295 C-651 294.34 -651 293.68 -651 293 C-647.26788977 291.75596326 -643.78316281 291.83133129 -639.89428711 291.81054688 C-638.64620569 291.79807718 -638.64620569 291.79807718 -637.3729105 291.78535557 C-634.59107611 291.75864525 -631.8092337 291.73876882 -629.02734375 291.71875 C-627.05822324 291.70094416 -625.08910701 291.68265953 -623.11999512 291.66392517 C-618.91618657 291.62471772 -614.71236708 291.58831685 -610.5085144 291.5541687 C-600.62843159 291.47370501 -590.74847797 291.37938452 -580.86851692 291.28530693 C-578.65935492 291.26432422 -576.45019123 291.24351841 -574.24102592 291.22288704 C-551.699903 291.01204131 -529.16157638 290.68837798 -506.62280273 290.3046875 C-492.08021035 290.06158667 -477.54466498 289.93917051 -463 290 C-463.02392822 289.19892822 -463.04785645 288.39785645 -463.07250977 287.57250977 C-463.23685879 277.53725862 -462.27784296 267.86796153 -460.9375 257.9375 C-460.82740601 257.11051605 -460.71731201 256.2835321 -460.60388184 255.43148804 C-451.80786134 190.21780463 -423.21981592 128.7489231 -379 80 C-378.46036621 79.40396973 -377.92073242 78.80793945 -377.36474609 78.19384766 C-373.94530852 74.4290949 -370.50856591 70.68197919 -367 67 C-366.46874512 66.43812988 -365.93749023 65.87625977 -365.39013672 65.29736328 C-363.96690655 63.82501163 -362.48719596 62.40771151 -361 61 C-360.34 61 -359.68 61 -359 61 C-359 60.34 -359 59.68 -359 59 C-357.3203125 57.2734375 -357.3203125 57.2734375 -355.125 55.375 C-354.40570313 54.74335938 -353.68640625 54.11171875 -352.9453125 53.4609375 C-351 52 -351 52 -349 52 C-349 51.34 -349 50.68 -349 50 C-346.86956389 48.16878244 -344.73240909 46.44881162 -342.5 44.75 C-341.85361572 44.25129395 -341.20723145 43.75258789 -340.54125977 43.23876953 C-338.69861779 41.81992826 -336.84988012 40.40938175 -335 39 C-333.88431641 38.13761719 -333.88431641 38.13761719 -332.74609375 37.2578125 C-330.85079942 35.80871057 -328.93326669 34.39806857 -327 33 C-326.11957031 32.360625 -325.23914063 31.72125 -324.33203125 31.0625 C-294.20508548 9.67962341 -260.54434815 -6.88838167 -225 -17 C-224.28102539 -17.21317871 -223.56205078 -17.42635742 -222.82128906 -17.64599609 C-207.81351426 -22.08269882 -192.45887415 -24.67633728 -177 -27 C-176.10684082 -27.13567383 -175.21368164 -27.27134766 -174.29345703 -27.41113281 C-115.79417589 -35.81042293 -53.22637909 -24.81181726 0 0 Z " fill="#FDFDFD" transform="translate(739,332)"/> 4 + <path d="" fill="#FFFFFF" transform="translate(0,0)"/> 5 + </svg>
public/mars.png

This is a binary file and will not be displayed.

public/neptune.png

This is a binary file and will not be displayed.

public/social_card.png

This is a binary file and will not be displayed.

public/venus.png

This is a binary file and will not be displayed.

+1
supabase/.temp/cli-latest
··· 1 + v2.67.1
+1
supabase/.temp/gotrue-version
··· 1 + v2.185.0
+1
supabase/.temp/pooler-url
··· 1 + postgresql://postgres.espdzfmvhthcskxzrnyq@aws-1-eu-west-1.pooler.supabase.com:5432/postgres
+1
supabase/.temp/postgres-version
··· 1 + 17.6.1.063
+1
supabase/.temp/project-ref
··· 1 + espdzfmvhthcskxzrnyq
+1
supabase/.temp/rest-version
··· 1 + v14.1
+1
supabase/.temp/storage-migration
··· 1 + buckets-objects-grants-postgres
+1
supabase/.temp/storage-version
··· 1 + v1.33.0
+65
supabase/migrations/001_subscriptions.sql
··· 1 + -- Create subscriptions table to track user subscriptions 2 + CREATE TABLE IF NOT EXISTS subscriptions ( 3 + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), 4 + user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE, 5 + stripe_customer_id TEXT, 6 + stripe_subscription_id TEXT UNIQUE, 7 + stripe_price_id TEXT, 8 + status TEXT NOT NULL, 9 + current_period_start TIMESTAMPTZ, 10 + current_period_end TIMESTAMPTZ, 11 + cancel_at_period_end BOOLEAN DEFAULT false, 12 + created_at TIMESTAMPTZ DEFAULT NOW(), 13 + updated_at TIMESTAMPTZ DEFAULT NOW() 14 + ); 15 + 16 + -- Create index for faster lookups 17 + CREATE INDEX IF NOT EXISTS subscriptions_user_id_idx ON subscriptions(user_id); 18 + CREATE INDEX IF NOT EXISTS subscriptions_stripe_customer_id_idx ON subscriptions(stripe_customer_id); 19 + CREATE INDEX IF NOT EXISTS subscriptions_stripe_subscription_id_idx ON subscriptions(stripe_subscription_id); 20 + 21 + -- Enable Row Level Security 22 + ALTER TABLE subscriptions ENABLE ROW LEVEL SECURITY; 23 + 24 + -- Policy: Users can only see their own subscriptions 25 + DROP POLICY IF EXISTS "Users can view own subscriptions" ON subscriptions; 26 + CREATE POLICY "Users can view own subscriptions" 27 + ON subscriptions 28 + FOR SELECT 29 + USING (auth.uid() = user_id); 30 + 31 + -- Policy: Users can insert their own subscription records (for initial customer creation) 32 + -- But they can ONLY insert records with status='incomplete' to prevent fraud 33 + DROP POLICY IF EXISTS "Users can insert own subscriptions" ON subscriptions; 34 + CREATE POLICY "Users can insert own subscriptions" 35 + ON subscriptions 36 + FOR INSERT 37 + WITH CHECK ( 38 + auth.uid() = user_id 39 + AND status = 'incomplete' 40 + ); 41 + 42 + -- Users CANNOT update their own subscriptions directly 43 + -- All updates must come from webhooks (using service role) or validated server actions 44 + -- This prevents users from setting status='active' without paying 45 + DROP POLICY IF EXISTS "Users can update own subscriptions" ON subscriptions; 46 + 47 + -- Note: Service role (used by webhooks via admin client) bypasses RLS entirely 48 + -- The admin client uses SUPABASE_SERVICE_ROLE_KEY which automatically bypasses all RLS policies. 49 + -- No policy needed for service role since it bypasses RLS. 50 + 51 + -- Function to update updated_at timestamp 52 + CREATE OR REPLACE FUNCTION update_updated_at_column() 53 + RETURNS TRIGGER AS $$ 54 + BEGIN 55 + NEW.updated_at = NOW(); 56 + RETURN NEW; 57 + END; 58 + $$ language 'plpgsql'; 59 + 60 + -- Trigger to automatically update updated_at 61 + DROP TRIGGER IF EXISTS update_subscriptions_updated_at ON subscriptions; 62 + CREATE TRIGGER update_subscriptions_updated_at 63 + BEFORE UPDATE ON subscriptions 64 + FOR EACH ROW 65 + EXECUTE FUNCTION update_updated_at_column();
+20
supabase/migrations/002_add_user_insert_update_policies.sql
··· 1 + -- Add policies to allow users to insert and update their own subscriptions 2 + -- This is needed for the checkout flow to work without requiring service role key 3 + -- NOTE: This migration is now obsolete - we removed UPDATE policy for security 4 + -- Keeping it for migration history, but it will be skipped if policies already exist 5 + 6 + -- Policy: Users can insert their own subscription records (for initial customer creation) 7 + DO $$ 8 + BEGIN 9 + IF NOT EXISTS ( 10 + SELECT 1 FROM pg_policies 11 + WHERE schemaname = 'public' 12 + AND tablename = 'subscriptions' 13 + AND policyname = 'Users can insert own subscriptions' 14 + ) THEN 15 + CREATE POLICY "Users can insert own subscriptions" 16 + ON subscriptions 17 + FOR INSERT 18 + WITH CHECK (auth.uid() = user_id); 19 + END IF; 20 + END $$;
+16
supabase/migrations/003_remove_user_update_policy.sql
··· 1 + -- Remove the UPDATE policy that allows users to update their own subscriptions 2 + -- This is a security fix: users should NOT be able to modify subscription status 3 + -- All updates must come from webhooks (service role) or validated server actions 4 + 5 + -- This migration is safe to run multiple times 6 + DO $$ 7 + BEGIN 8 + IF EXISTS ( 9 + SELECT 1 FROM pg_policies 10 + WHERE schemaname = 'public' 11 + AND tablename = 'subscriptions' 12 + AND policyname = 'Users can update own subscriptions' 13 + ) THEN 14 + DROP POLICY "Users can update own subscriptions" ON subscriptions; 15 + END IF; 16 + END $$;
+19
supabase/migrations/004_add_subscription_validation.sql
··· 1 + -- Additional security: Add a check constraint to ensure data integrity 2 + -- Note: RLS policies already prevent users from updating, but this adds an extra layer 3 + 4 + -- Ensure status is one of the valid Stripe subscription statuses 5 + ALTER TABLE subscriptions 6 + DROP CONSTRAINT IF EXISTS valid_subscription_status; 7 + 8 + ALTER TABLE subscriptions 9 + ADD CONSTRAINT valid_subscription_status 10 + CHECK (status IN ( 11 + 'incomplete', 12 + 'incomplete_expired', 13 + 'trialing', 14 + 'active', 15 + 'past_due', 16 + 'canceled', 17 + 'unpaid', 18 + 'paused' 19 + ));
+24
supabase/migrations/005_simplify_subscriptions.sql
··· 1 + -- Simplify subscriptions table to only store minimal data 2 + -- Stripe API is the source of truth for all subscription details 3 + 4 + -- First, drop policies that depend on columns we're removing 5 + DROP POLICY IF EXISTS "Users can insert own subscriptions" ON subscriptions; 6 + 7 + -- Drop unnecessary columns (keep only user_id and stripe_customer_id) 8 + ALTER TABLE subscriptions 9 + DROP COLUMN IF EXISTS stripe_subscription_id, 10 + DROP COLUMN IF EXISTS stripe_price_id, 11 + DROP COLUMN IF EXISTS status, 12 + DROP COLUMN IF EXISTS current_period_start, 13 + DROP COLUMN IF EXISTS current_period_end, 14 + DROP COLUMN IF EXISTS cancel_at_period_end; 15 + 16 + -- Recreate a simpler insert policy (no status check needed since we don't store it) 17 + CREATE POLICY "Users can insert own subscriptions" 18 + ON subscriptions 19 + FOR INSERT 20 + WITH CHECK (auth.uid() = user_id); 21 + 22 + -- Keep only essential columns 23 + -- user_id: links to Supabase auth user 24 + -- stripe_customer_id: used to query Stripe API for subscription details
+35
supabase/migrations/006_add_pds_services.sql
··· 1 + -- Track which PDS service has been provisioned for each user 2 + -- This lets the dashboard fetch the correct service via GET /service/{id} 3 + CREATE TABLE IF NOT EXISTS pds_services ( 4 + user_id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE, 5 + pds_service_id BIGINT, 6 + hostname TEXT, 7 + status TEXT NOT NULL DEFAULT 'provisioning', 8 + created_at TIMESTAMPTZ DEFAULT NOW(), 9 + updated_at TIMESTAMPTZ DEFAULT NOW() 10 + ); 11 + 12 + ALTER TABLE pds_services ENABLE ROW LEVEL SECURITY; 13 + 14 + -- Users can see only their own provisioned PDS 15 + DROP POLICY IF EXISTS "Users can view own pds services" ON pds_services; 16 + CREATE POLICY "Users can view own pds services" 17 + ON pds_services 18 + FOR SELECT 19 + USING (auth.uid() = user_id); 20 + 21 + -- Keep updated_at current 22 + CREATE OR REPLACE FUNCTION update_pds_services_updated_at_column() 23 + RETURNS TRIGGER AS $$ 24 + BEGIN 25 + NEW.updated_at = NOW(); 26 + RETURN NEW; 27 + END; 28 + $$ language 'plpgsql'; 29 + 30 + DROP TRIGGER IF EXISTS update_pds_services_updated_at ON pds_services; 31 + CREATE TRIGGER update_pds_services_updated_at 32 + BEFORE UPDATE ON pds_services 33 + FOR EACH ROW 34 + EXECUTE FUNCTION update_pds_services_updated_at_column(); 35 +
-3
tsconfig.json
··· 27 27 "@/components/*": [ 28 28 "app/components/*" 29 29 ], 30 - "@/config": [ 31 - "config/" 32 - ], 33 30 "@/lib/*": [ 34 31 "lib/*" 35 32 ],
-15
utils/get-stripejs.ts
··· 1 - /** 2 - * This is a singleton to ensure we only instantiate Stripe once. 3 - */ 4 - import { Stripe, loadStripe } from "@stripe/stripe-js"; 5 - 6 - let stripePromise: Promise<Stripe | null>; 7 - 8 - export default function getStripe(): Promise<Stripe | null> { 9 - if (!stripePromise) 10 - stripePromise = loadStripe( 11 - process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY as string, 12 - ); 13 - 14 - return stripePromise; 15 - }
-30
utils/stripe-helpers.ts
··· 1 - export function formatAmountForDisplay( 2 - amount: number, 3 - currency: string, 4 - ): string { 5 - let numberFormat = new Intl.NumberFormat(["en-US"], { 6 - style: "currency", 7 - currency: currency, 8 - currencyDisplay: "symbol", 9 - }); 10 - return numberFormat.format(amount); 11 - } 12 - 13 - export function formatAmountForStripe( 14 - amount: number, 15 - currency: string, 16 - ): number { 17 - let numberFormat = new Intl.NumberFormat(["en-US"], { 18 - style: "currency", 19 - currency: currency, 20 - currencyDisplay: "symbol", 21 - }); 22 - const parts = numberFormat.formatToParts(amount); 23 - let zeroDecimalCurrency: boolean = true; 24 - for (let part of parts) { 25 - if (part.type === "decimal") { 26 - zeroDecimalCurrency = false; 27 - } 28 - } 29 - return zeroDecimalCurrency ? amount : Math.round(amount * 100); 30 - }