diff --git a/TESTING.md b/TESTING.md new file mode 100644 index 0000000..c4ec680 --- /dev/null +++ b/TESTING.md @@ -0,0 +1,94 @@ +# Testing Floodwall + +Three parts, each tested on its own, then together on the preview site. + +| Part | Where | What it is | +|---|---|---| +| Crate | `src/`, `tests/` | The Rust library: admission, scheduler, gate, hold queue, ledger | +| Sign-in and billing service | `api/` | Cloudflare Worker at `api.floodwall.ai`, D1 `floodwall-auth`, Paygate for payments | +| Site | `site/` → `docs/` | React + Vite: floodwall.ai (from `main`), preview.floodwall.ai (from `preview`) | + +Run one test command at a time. + +## 1. Crate + +```sh +cargo test +cargo clippy --all-targets -- -D warnings +cargo run --example production # the OPA/Rego-style guardrails at the gate +node --test tools/verify-ledger.test.mjs # the independent ledger verifier +``` + +## 2. Service, locally + +```sh +cd api +npm ci +npm run check # typecheck, bundle, Miniflare tests (Resend and Paygate stood in) +cp .dev.vars.example .dev.vars # Resend key, AUTH_SECRET, your address in ADMIN_EMAILS, Paygate test key +npm run migrate:local +npm run dev # http://127.0.0.1:8787 +``` + +And the site against it, in another terminal: + +```sh +echo VITE_AUTH_API_URL=http://127.0.0.1:8787 > site/.env.development.local +npm --prefix site run dev # open http://127.0.0.1:5173 (not localhost: the cookie is SameSite=Strict) +``` + +Without `VITE_AUTH_API_URL` the site runs an in-browser demo: the code is shown on the page and +billing says it needs the service. + +### Billing end to end, locally + +Paygate has to reach the local Worker for webhooks: + +```sh +cloudflared tunnel --url http://127.0.0.1:8787 +``` + +In Paygate (test mode), set the floodwall app's webhook URL to `/billing/webhook` and +send a test webhook. Then: + +1. Sign in, open `/account`, choose **Move to Team**. +2. Pay with `4242 4242 4242 4242`, any future date, any CVC. +3. Back on `/account?billing=success`: it says the plan is active and shows **Team** with its + renewal date. In D1: `npx wrangler d1 execute floodwall-auth --local --command "SELECT email, plan, plan_status FROM users"`. +4. **Invoices, card and cancelling** opens Paygate's billing page. Cancel: the account shows + **Ends ** and returns to Free when the period ends (advance a test clock on Paygate's + **Testing** page to see it). +5. A declined card (`4000 0000 0000 0002`) sends `payment.failed`: the owner gets an email. +6. Paygate's **Webhooks to apps** shows every delivery and lets you resend one; a resend is + answered `duplicate: true` and changes nothing. + +## 3. Site + +```sh +npm --prefix site test +npm --prefix site run build # writes docs/; add `-- --outDir ` to build elsewhere +``` + +## 4. Live, on preview.floodwall.ai + +Pushing to `preview` deploys the site (`.github/workflows/preview.yml`). The Worker deploys by hand: + +```sh +cd api && npm run migrate:remote && npm run deploy +npx wrangler tail floodwall-api # live logs while you test +curl -i https://api.floodwall.ai/auth/session # 200 { "user": null } +``` + +Smoke test, in a private window: + +1. `/signup` with an address you can read → six-digit code by email → `/waitlist`. +2. As an admin (`ADMIN_EMAILS`), `/app/admin` → **Approve** → the "You're in" email → `/app`. +3. `/account` → **Plan and billing** shows **Free**. +4. `/pricing` signed in: Free is marked **Your plan**; **Move to Team** opens Stripe Checkout. +5. Pay with the 4242 test card (the service holds a `pg_sk_test_…` key, so nothing is charged), + come back to `/account`, see **Team**. +6. Open the billing page, cancel, check the account shows the end date. +7. Sign out; `/account` sends you to `/login`. + +Going live is swapping the Worker's Paygate key and webhook secret for live ones +(`npx wrangler secret put …`), after the Terms, Privacy and Refund pages are up (FW-605). diff --git a/api/.dev.vars.example b/api/.dev.vars.example index 5a0f198..7516758 100644 --- a/api/.dev.vars.example +++ b/api/.dev.vars.example @@ -17,3 +17,10 @@ ADMIN_EMAILS=you@example.com # Uncomment to let anyone in, as after the beta. # SIGNUP_MODE=open + +# Billing, through Paygate's test mode (pay.erpai.studio → Apps → floodwall → Test). +# Without the key, /billing answers 503 and the account page says billing is unavailable. +PAYGATE_SECRET_KEY=pg_sk_test_... +# "Show signing secret" on the app page. Point its test webhook URL at a tunnel to +# this service, e.g. `cloudflared tunnel --url http://127.0.0.1:8787` + /billing/webhook. +PAYGATE_WEBHOOK_SECRET= diff --git a/api/README.md b/api/README.md index fcb8a37..f45036c 100644 --- a/api/README.md +++ b/api/README.md @@ -102,6 +102,13 @@ which the site shows as it is. | `POST /admin/approve` | `{ "email": "..." }` | `200 { "approved": true, "emailed": true \| false }`; `404` no such account; `401`, `403` as above | | `POST /admin/remove` | `{ "email": "..." }` | `200 { "removed": true }`; `400` an admin; `404` no such account; `401`, `403` as above | +| `GET /billing` | | `200 `; `?refresh=1` asks Paygate first; `401` signed out; `403` waiting | +| `POST /billing/checkout` | `{ "plan": "team" \| "business", "interval": "month" \| "year" }` | `200 { "url": "" }`; `400` unknown plan; `409` already on a plan; `502` Paygate failed; `503` no key | +| `POST /billing/manage` | `{}` | `200 { "url": "" }`; `404` never checked out | +| `POST /billing/webhook` | Paygate's event, signed | `200 { "received": true }`; `400` bad or stale signature. Called by Paygate, not the site: no origin check, no session | + +`` is `{ "plan": "free" | "team" | "business", "status", "features", "periodEnd", "cancelAtPeriodEnd" }`. + `` is `{ "email": "...", "waiting": false, "admin": false }`. `waiting` is true while the account is on the waitlist; the site then shows `/waitlist` instead of the console. Anything added to the service later that only @@ -110,6 +117,45 @@ approved accounts may use should check `waiting` the same way. Without `RESEND_API_KEY`, or an `AUTH_SECRET` of at least 32 characters, `/auth/code` and `/auth/verify` answer `503`. +## Billing + +Plans are sold through [Paygate](https://pay.erpai.studio), our Stripe hub +(`~/code/v2/payment-gateway`). The Worker never sees a card or a Stripe key: + +1. **Upgrade.** `POST /billing/checkout` asks Paygate for a Stripe Checkout + page for the account (`external_id` = the account's id) and the site goes + there. Stripe returns to `/account?billing=success`, or `/pricing` if + cancelled. +2. **Paid.** Paygate sends a signed `entitlement.changed` webhook to + `POST /billing/webhook`. The Worker checks the signature + (HMAC-SHA256 with `PAYGATE_WEBHOOK_SECRET`, 5-minute tolerance), skips an + event id it has seen, and copies the plan, status, limits (`features`) and + period end onto the account. An older event never overwrites a newer one. + `payment.failed` emails the owner. Coming back from checkout, the account + page also asks for `?refresh=1`, in case the webhook is still on its way. +3. **Manage.** `POST /billing/manage` opens Paygate's hosted billing page: + invoices, card, cancel and resume. + +Every account starts on `free`. Plan changes between Team and Business, and +usage-based overage (metered `decisions`, FW-704), come later. + +**Paygate setup** (dashboard → Apps → `floodwall`, test mode first): plans +`team` ($49/mo, $490/yr) and `business` ($399/mo, $3,990/yr) with these +features JSON, success and cancel URLs as above, webhook URL +`https://api.floodwall.ai/billing/webhook`, and allowed origins +`https://floodwall.ai`, `https://preview.floodwall.ai`. + +```json +{ "planes": 5, "decisions_included": 250000, "retention_days": 90, "approvers": null, "slack": true, "sso": false } +{ "planes": null, "decisions_included": 2500000, "retention_days": 365, "approvers": null, "slack": true, "sso": true, "sla": "99.9" } +``` + +**Secrets:** `npx wrangler secret put PAYGATE_SECRET_KEY` and +`npx wrangler secret put PAYGATE_WEBHOOK_SECRET`. A `pg_sk_test_…` key keeps +everything in Stripe test mode; going live is swapping in the live key and +live webhook secret, no code change. Run `npm run migrate:remote` for +`0003_billing.sql` before deploying. + ## Local development ```sh @@ -142,10 +188,12 @@ npm run check # typecheck, bundle, then the tests The tests run the bundle that `wrangler deploy` would upload in the Workers runtime (Miniflare), with an empty D1 database and a stand-in for Resend that -keeps every email. They cover the whole flow and each rule above, including +keeps every email. A stand-in for Paygate answers the billing calls. They cover the whole flow +and each rule above, including requests that race each other, a Resend that refuses, a missing secret, the cookie's attributes, origin checks, the daily sweep, the waitlist, the admin -calls and both settings of `SIGNUP_MODE`. CI runs them on every pull request. +calls, both settings of `SIGNUP_MODE`, and billing: checkout, the billing +page, signed and replayed webhooks, and webhooks out of order. CI runs them on every pull request. ## Deploying diff --git a/api/migrations/0003_billing.sql b/api/migrations/0003_billing.sql new file mode 100644 index 0000000..a47909b --- /dev/null +++ b/api/migrations/0003_billing.sql @@ -0,0 +1,23 @@ +-- Billing through Paygate (pay.erpai.studio), which runs Stripe for us. An +-- account's plan is copied here from Paygate's entitlement.changed webhook, +-- so pages can read it without calling Paygate. Every account starts on Free. + +ALTER TABLE users ADD COLUMN plan TEXT NOT NULL DEFAULT 'free'; +-- Paygate's subscription status: active, trialing, past_due, canceled, or null on Free. +ALTER TABLE users ADD COLUMN plan_status TEXT; +-- The plan's limits as JSON (planes, decisions_included, retention_days, ...). +ALTER TABLE users ADD COLUMN plan_features TEXT; +ALTER TABLE users ADD COLUMN plan_period_end INTEGER; +ALTER TABLE users ADD COLUMN plan_cancel_at_period_end INTEGER NOT NULL DEFAULT 0; +-- When the state copied here was true. Webhooks can arrive out of order, so +-- an older one never overwrites a newer one. +ALTER TABLE users ADD COLUMN plan_updated_at INTEGER NOT NULL DEFAULT 0; + +-- Webhooks already handled, by Paygate's event id: delivery is at least once. +CREATE TABLE billing_events ( + id TEXT PRIMARY KEY, + type TEXT NOT NULL, + received_at INTEGER NOT NULL +); + +CREATE INDEX billing_events_received ON billing_events (received_at); diff --git a/api/src/auth.ts b/api/src/auth.ts index 63e28ce..927c9df 100644 --- a/api/src/auth.ts +++ b/api/src/auth.ts @@ -197,6 +197,12 @@ export async function verifyCode(request: Request, env: Env, now: number) { /** The account the session cookie belongs to, or null. */ export async function sessionUser(request: Request, env: Env, now: number) { + const account = await sessionAccount(request, env, now); + return account && account.user; +} + +/** The session's account with its id, for calls that need to name it to another service. */ +export async function sessionAccount(request: Request, env: Env, now: number) { const token = readSessionCookie(request); if (!token || !isToken(token)) return null; const row = await env.DB.prepare( @@ -205,7 +211,7 @@ export async function sessionUser(request: Request, env: Env, now: number) { ) .bind(await tokenHash(token), now) .first(); - return row ? publicUser(row, env) : null; + return row ? { id: row.id, user: publicUser(row, env) } : null; } export async function currentSession(request: Request, env: Env, now: number) { @@ -227,5 +233,7 @@ export async function sweep(db: D1Database, now: number) { db.prepare("DELETE FROM sessions WHERE expires_at <= ?").bind(now), // The longest window is a day, so one that started a day ago has ended. db.prepare("DELETE FROM rate_limits WHERE window_start <= ?").bind(now - DAY), + // Paygate stops retrying a webhook after 3 days, so a week covers any repeat. + db.prepare("DELETE FROM billing_events WHERE received_at <= ?").bind(now - 7 * DAY), ]); } diff --git a/api/src/billing.ts b/api/src/billing.ts new file mode 100644 index 0000000..b4fb68c --- /dev/null +++ b/api/src/billing.ts @@ -0,0 +1,264 @@ +// Plans and payments, through Paygate (pay.erpai.studio), which runs Stripe +// for us. The Worker never sees a card or a Stripe key: it asks Paygate for a +// checkout page or a billing page, and Paygate's signed webhooks tell it what +// each account has paid for, which it keeps on the account's row. +// +// GET /billing the signed-in account's plan (?refresh=1 asks Paygate first) +// POST /billing/checkout { plan, interval } a Stripe Checkout page for Team or Business +// POST /billing/manage Paygate's hosted billing page: invoices, card, cancel +// POST /billing/webhook Paygate's webhooks (signed; no session, no site origin) + +import { sessionAccount } from "./auth"; +import type { Env } from "./env"; +import { HttpError, json, readBody, readJson } from "./http"; +import { paymentFailedEmail, sendEmail } from "./mail"; +import { MESSAGES } from "./rules"; + +/** The plans that can be bought; Free is what an account has without one. */ +export const PAID_PLANS = ["team", "business"] as const; +export const INTERVALS = ["month", "year"] as const; + +/** How far a webhook's signed time may be from ours. */ +const SIGNATURE_TOLERANCE_MS = 5 * 60_000; +/** Paygate's events are small; this leaves room for an invoice with many lines. */ +const MAX_WEBHOOK_LENGTH = 256 * 1024; + +/** What Paygate says an account is entitled to (GET /v1/entitlements, entitlement.changed). */ +type Entitlement = { + active: boolean; + plan: string | null; + status: string | null; + current_period_end?: string | null; + cancel_at_period_end?: boolean; + features?: Record | null; +}; + +type PlanRow = { + plan: string; + plan_status: string | null; + plan_features: string | null; + plan_period_end: number | null; + plan_cancel_at_period_end: number; +}; + +/** What the site is told about the account's plan. */ +function publicPlan(row: PlanRow) { + return { + plan: row.plan, + status: row.plan_status, + features: row.plan_features ? (JSON.parse(row.plan_features) as Record) : null, + periodEnd: row.plan_period_end, + cancelAtPeriodEnd: row.plan_cancel_at_period_end === 1, + }; +} + +function secretKey(env: Env) { + if (!env.PAYGATE_SECRET_KEY || !env.PAYGATE_URL) { + console.error("billing is not configured: set PAYGATE_URL and PAYGATE_SECRET_KEY"); + throw new HttpError(503, MESSAGES.billingUnavailable); + } + return env.PAYGATE_SECRET_KEY; +} + +/** One call to Paygate's app API. Returns the status and parsed body; a network failure is a 502. */ +async function paygate(env: Env, method: string, path: string, body?: unknown) { + const key = secretKey(env); + const headers: Record = { Authorization: `Bearer ${key}` }; + if (body !== undefined) { + headers["Content-Type"] = "application/json"; + // Paygate replays the first answer to a repeated key; each call here is a new intent. + headers["Idempotency-Key"] = crypto.randomUUID(); + } + let response: Response; + try { + response = await fetch(`${env.PAYGATE_URL.replace(/\/$/, "")}/v1${path}`, { + method, + headers, + body: body === undefined ? undefined : JSON.stringify(body), + }); + } catch (error) { + console.error("paygate: unreachable", error); + throw new HttpError(502, MESSAGES.billingUnavailable); + } + const text = await response.text(); + let parsed: any = null; + try { + parsed = text ? JSON.parse(text) : null; + } catch { + // Not JSON: treated as a failure below. + } + return { status: response.status, body: parsed }; +} + +function paygateFailed(what: string, answer: { status: number; body: any }): never { + console.error(`paygate: ${what} refused`, answer.status, JSON.stringify(answer.body?.error ?? null).slice(0, 300)); + throw new HttpError(502, MESSAGES.billingUnavailable); +} + +/** The signed-in account, which must be past the waitlist to buy anything. */ +async function requireMember(request: Request, env: Env, now: number) { + const account = await sessionAccount(request, env, now); + if (!account) throw new HttpError(401, MESSAGES.signedOut); + if (account.user.waiting) throw new HttpError(403, MESSAGES.waiting); + return account; +} + +/** + * Copies an entitlement onto the account, unless what is there is newer. Without an active + * subscription the account is on Free. + */ +async function storeEntitlement(env: Env, userId: string, ent: Entitlement, asOf: number) { + const active = ent.active && !!ent.plan; + const periodEnd = ent.current_period_end ? Date.parse(ent.current_period_end) : NaN; + const result = await env.DB.prepare( + `UPDATE users SET plan = ?1, plan_status = ?2, plan_features = ?3, plan_period_end = ?4, + plan_cancel_at_period_end = ?5, plan_updated_at = ?6 + WHERE id = ?7 AND plan_updated_at <= ?6`, + ) + .bind( + active ? ent.plan : "free", + ent.status ?? null, + active && ent.features ? JSON.stringify(ent.features) : null, + Number.isFinite(periodEnd) ? periodEnd : null, + ent.cancel_at_period_end ? 1 : 0, + asOf, + userId, + ) + .run(); + return result.meta.changes > 0; +} + +async function planRow(env: Env, userId: string) { + return env.DB.prepare( + "SELECT plan, plan_status, plan_features, plan_period_end, plan_cancel_at_period_end FROM users WHERE id = ?", + ) + .bind(userId) + .first(); +} + +export async function currentPlan(request: Request, env: Env, now: number) { + const { id } = await requireMember(request, env, now); + // Straight after checkout the webhook may not have landed yet, so the site asks for a refresh. + if (new URL(request.url).searchParams.get("refresh") === "1") { + const answer = await paygate(env, "GET", `/entitlements/${encodeURIComponent(id)}`); + if (answer.status !== 200) paygateFailed("entitlements", answer); + await storeEntitlement(env, id, answer.body as Entitlement, now); + } + const row = await planRow(env, id); + if (!row) throw new HttpError(401, MESSAGES.signedOut); + return json(publicPlan(row)); +} + +export async function startCheckout(request: Request, env: Env, now: number, origin: string) { + const { id, user } = await requireMember(request, env, now); + const body = await readJson(request); + const plan = PAID_PLANS.find((p) => p === body.plan); + const interval = INTERVALS.find((i) => i === (body.interval ?? "month")); + if (!plan || !interval) throw new HttpError(400, MESSAGES.badPlan); + + const answer = await paygate(env, "POST", "/checkout", { + customer: { external_id: id, email: user.email }, + plan, + interval, + allow_promotion_codes: true, + // Back to the site the reader came from: one of ALLOWED_ORIGINS. + success_url: `${origin}/account?billing=success`, + cancel_url: `${origin}/pricing`, + metadata: { floodwall_user: id }, + }); + if (answer.status === 409 && answer.body?.error?.code === "already_subscribed") { + throw new HttpError(409, MESSAGES.alreadySubscribed); + } + if (answer.status !== 200 && answer.status !== 201) paygateFailed("checkout", answer); + return json({ url: answer.body.url }); +} + +export async function manageBilling(request: Request, env: Env, now: number) { + const { id } = await requireMember(request, env, now); + const answer = await paygate(env, "POST", "/billing-link", { external_id: id }); + if (answer.status === 404) throw new HttpError(404, MESSAGES.noBilling); + if (answer.status !== 200 && answer.status !== 201) paygateFailed("billing link", answer); + return json({ url: answer.body.url }); +} + +/** Checks `Paygate-Signature: t=,v1=.")>`. */ +export async function verifySignature(secret: string, header: string | null, body: string, now: number) { + if (!header) return false; + const parts = new Map(header.split(",").map((p) => p.trim().split("=", 2) as [string, string])); + const t = Number(parts.get("t")); + const given = parts.get("v1"); + if (!Number.isInteger(t) || !given || !/^[0-9a-f]{64}$/.test(given)) return false; + if (Math.abs(now - t * 1000) > SIGNATURE_TOLERANCE_MS) return false; + const key = await crypto.subtle.importKey( + "raw", + new TextEncoder().encode(secret), + { name: "HMAC", hash: "SHA-256" }, + false, + ["verify"], + ); + const signature = new Uint8Array(given.match(/../g)!.map((h) => parseInt(h, 16))); + // verify() compares in constant time. + return crypto.subtle.verify("HMAC", key, signature, new TextEncoder().encode(`${t}.${body}`)); +} + +type PaygateEvent = { + id: string; + type: string; + created: string; + customer?: { external_id?: string } | null; + data?: any; +}; + +export async function receiveWebhook(request: Request, env: Env, now: number) { + if (!env.PAYGATE_WEBHOOK_SECRET) { + console.error("billing is not configured: set PAYGATE_WEBHOOK_SECRET"); + throw new HttpError(503, MESSAGES.billingUnavailable); + } + const raw = await readBody(request, MAX_WEBHOOK_LENGTH); + if (!(await verifySignature(env.PAYGATE_WEBHOOK_SECRET, request.headers.get("Paygate-Signature"), raw, now))) { + throw new HttpError(400, MESSAGES.badRequest); + } + let event: PaygateEvent; + try { + event = JSON.parse(raw); + } catch { + throw new HttpError(400, MESSAGES.badRequest); + } + if (!event || typeof event.id !== "string" || typeof event.type !== "string") { + throw new HttpError(400, MESSAGES.badRequest); + } + + const seen = await env.DB.prepare("SELECT 1 FROM billing_events WHERE id = ?").bind(event.id).first(); + if (seen) return json({ received: true, duplicate: true }); + + const userId = event.customer?.external_id; + const created = Date.parse(event.created); + const asOf = Number.isFinite(created) ? created : now; + if (userId) { + switch (event.type) { + case "entitlement.changed": + if (event.data?.entitlement) await storeEntitlement(env, userId, event.data.entitlement, asOf); + break; + case "payment.failed": + await notifyPaymentFailed(env, userId); + break; + } + } + // Recorded once handled: a failure above answers 500 and Paygate sends the event again. + await env.DB.prepare("INSERT OR IGNORE INTO billing_events (id, type, received_at) VALUES (?, ?, ?)") + .bind(event.id, event.type, now) + .run(); + return json({ received: true }); +} + +async function notifyPaymentFailed(env: Env, userId: string) { + const row = await env.DB.prepare("SELECT email FROM users WHERE id = ?").bind(userId).first<{ email: string }>(); + if (!row) return; + const origin = env.ALLOWED_ORIGINS.split(",")[0].trim(); + try { + await sendEmail(env, row.email, paymentFailedEmail(`${origin}/account`)); + } catch (error) { + // The plan itself follows from entitlement.changed; a lost reminder isn't worth a retry storm. + console.error("billing: payment-failed email not sent", error); + } +} diff --git a/api/src/env.ts b/api/src/env.ts index dd45d80..a6e1e3f 100644 --- a/api/src/env.ts +++ b/api/src/env.ts @@ -1,4 +1,4 @@ -/** What the Worker is given: its database, three secrets and three settings. */ +/** What the Worker is given: its database, its secrets and its settings. */ export interface Env { DB: D1Database; /** Secret. A Resend API key that can send from MAIL_FROM's domain. */ @@ -23,4 +23,13 @@ export interface Env { * else): a new account waits until an admin approves it. */ SIGNUP_MODE: string; + /** Where Paygate's app API is, e.g. "https://pay.erpai.studio". */ + PAYGATE_URL: string; + /** + * Secret. The floodwall app's Paygate secret key. Its prefix picks the + * mode: pg_sk_test_… on preview, pg_sk_live_… once billing is live. + */ + PAYGATE_SECRET_KEY?: string; + /** Secret. Signs the webhooks Paygate sends to POST /billing/webhook. */ + PAYGATE_WEBHOOK_SECRET?: string; } diff --git a/api/src/http.ts b/api/src/http.ts index ef4e2e0..d167b96 100644 --- a/api/src/http.ts +++ b/api/src/http.ts @@ -31,19 +31,19 @@ export function json(body: unknown, status = 200, headers: Record MAX_BODY_LENGTH) throw new HttpError(413, MESSAGES.badRequest); +export async function readBody(request: Request, maxLength = MAX_BODY_LENGTH) { + if (Number(request.headers.get("Content-Length")) > maxLength) throw new HttpError(413, MESSAGES.badRequest); if (!request.body) return ""; const reader = request.body.getReader(); - const bytes = new Uint8Array(MAX_BODY_LENGTH); + const bytes = new Uint8Array(maxLength); let length = 0; for (;;) { const { done, value } = await reader.read(); if (done) break; - if (length + value.byteLength > MAX_BODY_LENGTH) { + if (length + value.byteLength > maxLength) { await reader.cancel(); throw new HttpError(413, MESSAGES.badRequest); } diff --git a/api/src/index.ts b/api/src/index.ts index 43f9276..0da3f63 100644 --- a/api/src/index.ts +++ b/api/src/index.ts @@ -2,6 +2,7 @@ // and sweeps expired rows on its daily schedule. import { approveUser, listUsers, removeUser } from "./admin"; +import { currentPlan, manageBilling, receiveWebhook, startCheckout } from "./billing"; import { currentSession, sendCode, signOut, sweep, verifyCode } from "./auth"; import type { Env } from "./env"; import { allowedOrigin, HttpError, json, preflight, withCors } from "./http"; @@ -10,6 +11,8 @@ import { MESSAGES } from "./rules"; async function route(request: Request, env: Env, origin: string | null) { const now = Date.now(); const { pathname } = new URL(request.url); + // Paygate's webhooks come from its server, not a site: their signature is the check. + if (request.method === "POST" && pathname === "/billing/webhook") return receiveWebhook(request, env, now); // Only the site's own pages may change anything: a POST from any other // origin, or with none, is refused before it is read. if (request.method === "POST" && !origin) throw new HttpError(403, MESSAGES.foreignOrigin); @@ -29,6 +32,12 @@ async function route(request: Request, env: Env, origin: string | null) { return approveUser(request, env, now, origin!); case "POST /admin/remove": return removeUser(request, env, now); + case "GET /billing": + return currentPlan(request, env, now); + case "POST /billing/checkout": + return startCheckout(request, env, now, origin!); + case "POST /billing/manage": + return manageBilling(request, env, now); } throw new HttpError(404, MESSAGES.notFound); } @@ -44,7 +53,7 @@ export default { if (error instanceof HttpError) { response = json({ error: error.message }, error.status, error.headers); } else { - console.error("sign-in failed", error); + console.error("request failed", error); response = json({ error: MESSAGES.broken }, 500); } } diff --git a/api/src/mail.ts b/api/src/mail.ts index dfee202..d6edf46 100644 --- a/api/src/mail.ts +++ b/api/src/mail.ts @@ -64,6 +64,22 @@ export function approvedEmail(consoleUrl: string): Email { }; } +/** The email when a renewal or upgrade can't be charged. `accountUrl` is /account on the site. */ +export function paymentFailedEmail(accountUrl: string): Email { + const lines = { + lead: "We couldn't take the payment for your Floodwall plan. Your card will be tried again over the next few days, and your plan stays on meanwhile.", + open: "Update your card", + help: "Open Billing on your account page to update the card or change your plan.", + }; + return { + subject: "Your Floodwall payment didn't go through", + text: `${lines.lead}\n\n${lines.open}: ${accountUrl}\n\n${lines.help}\n`, + html: page(`

${lines.lead}

+${lines.open} +

${lines.help}

`), + }; +} + /** Sends `email` to `to`, or throws a 502 the reader can retry after. */ export async function sendEmail(env: Env, to: string, email: Email) { let response: Response; diff --git a/api/src/rules.ts b/api/src/rules.ts index 568d300..8099d0c 100644 --- a/api/src/rules.ts +++ b/api/src/rules.ts @@ -46,5 +46,10 @@ export const MESSAGES = { noSuchUser: "There is no account for that address.", adminStays: "Admins can't be removed here. Take the address out of ADMIN_EMAILS first.", notFound: "Not found.", + waiting: "Your account is still on the waitlist.", + badPlan: "Choose the Team or Business plan, billed monthly or yearly.", + billingUnavailable: "Billing is not available right now. Please try again later.", + alreadySubscribed: "You already have a plan. Manage it from Billing on your account page.", + noBilling: "You have no billing history yet. Choose a plan first.", broken: "Something went wrong. Please try again.", }; diff --git a/api/test/billing.test.mjs b/api/test/billing.test.mjs new file mode 100644 index 0000000..9819c89 --- /dev/null +++ b/api/test/billing.test.mjs @@ -0,0 +1,210 @@ +import assert from "node:assert/strict"; +import { createHmac } from "node:crypto"; +import { after, before, beforeEach, describe, test } from "node:test"; +import { PAYGATE_KEY, PAYGATE_WEBHOOK_SECRET, SITE, start } from "./harness.mjs"; + +const ADMIN = "grace@example.com"; + +/** Signs a webhook body the way Paygate does. */ +function signed(event, { secret = PAYGATE_WEBHOOK_SECRET, at = Math.floor(Date.now() / 1000) } = {}) { + const body = JSON.stringify(event); + const v1 = createHmac("sha256", secret).update(`${at}.${body}`).digest("hex"); + return { body, headers: { "Paygate-Signature": `t=${at},v1=${v1}` } }; +} + +let eventCount = 0; +function entitlementEvent(userId, entitlement, created = new Date().toISOString()) { + eventCount += 1; + return { + id: `evt_${eventCount}`, + type: "entitlement.changed", + created, + mode: "test", + app: "floodwall", + customer: { id: "cus_1", external_id: userId }, + data: { entitlement, previous: null }, + }; +} + +const TEAM = { + active: true, + plan: "team", + status: "active", + current_period_end: "2026-12-14T00:00:00Z", + cancel_at_period_end: false, + features: { planes: 5, decisions_included: 250000, retention_days: 90 }, +}; + +describe("billing through Paygate", () => { + let w; + let answer; // what the fake Paygate says next + before(async () => { + w = await start({ bindings: { ADMIN_EMAILS: ADMIN }, paygate: (call) => answer?.(call) }); + }); + after(() => w.stop()); + beforeEach(async () => { + answer = null; + await w.reset(); + }); + + const userId = async (email) => (await w.db.prepare("SELECT id FROM users WHERE email = ?").bind(email).first()).id; + const webhook = (event, options) => { + const { body, headers } = signed(event, options); + return w.call("/billing/webhook", { body, headers, origin: null }); + }; + + test("a new account is on Free", async () => { + const cookie = await w.signIn(ADMIN); + const plan = await w.call("/billing", { method: "GET", cookie }); + assert.equal(plan.status, 200); + assert.deepEqual(plan.body, { plan: "free", status: null, features: null, periodEnd: null, cancelAtPeriodEnd: false }); + }); + + test("checkout asks Paygate for a page and returns its url", async () => { + const cookie = await w.signIn(ADMIN); + answer = () => Response.json({ id: "cs_1", url: "https://checkout.stripe.com/c/pay/cs_1" }); + const r = await w.call("/billing/checkout", { body: { plan: "team", interval: "year" }, cookie }); + assert.equal(r.status, 200); + assert.equal(r.body.url, "https://checkout.stripe.com/c/pay/cs_1"); + + const [call] = w.paygateCalls; + assert.equal(call.method, "POST"); + assert.equal(call.path, "/v1/checkout"); + assert.equal(call.headers.authorization, `Bearer ${PAYGATE_KEY}`); + assert.ok(call.headers["idempotency-key"]); + assert.deepEqual(call.body.customer, { external_id: await userId(ADMIN), email: ADMIN }); + assert.equal(call.body.plan, "team"); + assert.equal(call.body.interval, "year"); + assert.equal(call.body.success_url, `${SITE}/account?billing=success`); + assert.equal(call.body.cancel_url, `${SITE}/pricing`); + }); + + test("checkout refuses an unknown plan or interval without calling Paygate", async () => { + const cookie = await w.signIn(ADMIN); + for (const body of [{ plan: "free" }, { plan: "enterprise" }, { plan: "team", interval: "week" }, {}]) { + const r = await w.call("/billing/checkout", { body, cookie }); + assert.equal(r.status, 400, JSON.stringify(body)); + } + assert.equal(w.paygateCalls.length, 0); + }); + + test("an account already on a plan is told to manage it", async () => { + const cookie = await w.signIn(ADMIN); + answer = () => Response.json({ error: { code: "already_subscribed", message: "x" } }, { status: 409 }); + const r = await w.call("/billing/checkout", { body: { plan: "business" }, cookie }); + assert.equal(r.status, 409); + assert.match(r.body.error, /already have a plan/); + }); + + test("Paygate failing is a 502, not a crash", async () => { + const cookie = await w.signIn(ADMIN); + answer = () => Response.json({ error: { code: "boom" } }, { status: 500 }); + assert.equal((await w.call("/billing/checkout", { body: { plan: "team" }, cookie })).status, 502); + }); + + test("signed-out and waiting accounts can't buy", async () => { + assert.equal((await w.call("/billing/checkout", { body: { plan: "team" } })).status, 401); + assert.equal((await w.call("/billing", { method: "GET" })).status, 401); + const waiting = await w.signIn("ada@example.com"); + assert.equal((await w.call("/billing/checkout", { body: { plan: "team" }, cookie: waiting })).status, 403); + assert.equal((await w.call("/billing/manage", { body: {}, cookie: waiting })).status, 403); + assert.equal(w.paygateCalls.length, 0); + }); + + test("checkout without a Paygate key is unavailable", async () => { + const bare = await start({ bindings: { ADMIN_EMAILS: ADMIN, PAYGATE_SECRET_KEY: "" } }); + try { + const cookie = await bare.signIn(ADMIN); + assert.equal((await bare.call("/billing/checkout", { body: { plan: "team" }, cookie })).status, 503); + } finally { + await bare.stop(); + } + }); + + test("manage opens Paygate's hosted billing page", async () => { + const cookie = await w.signIn(ADMIN); + answer = () => Response.json({ url: "https://pay.erpai.studio/b/floodwall?t=abc", expires_at: "x" }); + const r = await w.call("/billing/manage", { body: {}, cookie }); + assert.equal(r.status, 200); + assert.equal(r.body.url, "https://pay.erpai.studio/b/floodwall?t=abc"); + assert.deepEqual(w.paygateCalls[0].body, { external_id: await userId(ADMIN) }); + + answer = () => Response.json({ error: { code: "not_found" } }, { status: 404 }); + assert.equal((await w.call("/billing/manage", { body: {}, cookie })).status, 404); + }); + + test("entitlement.changed puts the account on its plan, once", async () => { + const cookie = await w.signIn(ADMIN); + const event = entitlementEvent(await userId(ADMIN), TEAM); + const first = await webhook(event); + assert.equal(first.status, 200); + assert.deepEqual(first.body, { received: true }); + + const plan = (await w.call("/billing", { method: "GET", cookie })).body; + assert.equal(plan.plan, "team"); + assert.equal(plan.status, "active"); + assert.equal(plan.periodEnd, Date.parse(TEAM.current_period_end)); + assert.deepEqual(plan.features, TEAM.features); + + const again = await webhook(event); + assert.equal(again.status, 200); + assert.equal(again.body.duplicate, true); + }); + + test("an older event never overwrites a newer one", async () => { + const cookie = await w.signIn(ADMIN); + const id = await userId(ADMIN); + await webhook(entitlementEvent(id, TEAM, "2026-11-14T10:00:00Z")); + const canceled = { active: false, plan: null, status: "canceled", cancel_at_period_end: false, features: null }; + await webhook(entitlementEvent(id, canceled, "2026-11-14T09:00:00Z")); + assert.equal((await w.call("/billing", { method: "GET", cookie })).body.plan, "team"); + + await webhook(entitlementEvent(id, canceled, "2026-11-14T11:00:00Z")); + const plan = (await w.call("/billing", { method: "GET", cookie })).body; + assert.equal(plan.plan, "free"); + assert.equal(plan.status, "canceled"); + assert.equal(plan.features, null); + }); + + test("a webhook with a bad or stale signature is refused and changes nothing", async () => { + const cookie = await w.signIn(ADMIN); + const event = entitlementEvent(await userId(ADMIN), TEAM); + assert.equal((await webhook(event, { secret: "whsec_wrong" })).status, 400); + assert.equal((await webhook(event, { at: Math.floor(Date.now() / 1000) - 600 })).status, 400); + const unsigned = await w.call("/billing/webhook", { body: JSON.stringify(event), origin: null }); + assert.equal(unsigned.status, 400); + assert.equal((await w.call("/billing", { method: "GET", cookie })).body.plan, "free"); + }); + + test("payment.failed emails the account's owner", async () => { + await w.signIn(ADMIN); + const before = w.outbox.length; + const r = await webhook({ + id: "evt_failed_1", + type: "payment.failed", + created: new Date().toISOString(), + customer: { external_id: await userId(ADMIN) }, + data: { payment: {} }, + }); + assert.equal(r.status, 200); + assert.equal(w.outbox.length, before + 1); + assert.equal(w.outbox.at(-1).body.to[0], ADMIN); + assert.match(w.outbox.at(-1).body.subject, /payment didn't go through/); + }); + + test("refresh copies Paygate's current entitlement", async () => { + const cookie = await w.signIn(ADMIN); + answer = (call) => (call.path.startsWith("/v1/entitlements/") ? Response.json({ ...TEAM, plan: "business" }) : null); + const plan = await w.call("/billing?refresh=1", { method: "GET", cookie }); + assert.equal(plan.status, 200); + assert.equal(plan.body.plan, "business"); + assert.equal(w.paygateCalls[0].path, `/v1/entitlements/${await userId(ADMIN)}`); + }); + + test("the daily sweep forgets old webhook ids", async () => { + await w.db.prepare("INSERT INTO billing_events (id, type, received_at) VALUES ('old', 'ping', 1), ('new', 'ping', ?)").bind(Date.now()).run(); + await w.mf.getWorker().then((worker) => worker.scheduled({ cron: "17 3 * * *" })); + const left = await w.db.prepare("SELECT id FROM billing_events").all(); + assert.deepEqual(left.results.map((r) => r.id), ["new"]); + }); +}); diff --git a/api/test/harness.mjs b/api/test/harness.mjs index 010b8d4..09ec43d 100644 --- a/api/test/harness.mjs +++ b/api/test/harness.mjs @@ -1,6 +1,6 @@ // Runs the built Worker (dist/index.js, from `npm run build`) in Miniflare, -// with an empty D1 database and a stand-in for Resend that keeps every email -// it is sent. +// with an empty D1 database, a stand-in for Resend that keeps every email +// it is sent, and a stand-in for Paygate that a test can answer for. import fs from "node:fs"; import path from "node:path"; @@ -15,6 +15,9 @@ export const API = "https://api.floodwall.ai"; export const SITE = "https://preview.floodwall.ai"; export const SECRET = "test-secret-that-is-at-least-32-characters"; export const KEY = "re_test_key"; +export const PAYGATE = "https://pay.erpai.studio"; +export const PAYGATE_KEY = "pg_sk_test_floodwall"; +export const PAYGATE_WEBHOOK_SECRET = "whsec_test_floodwall"; /** * The service counts requests in fixed windows on the real clock (limits.ts). A test that makes @@ -26,9 +29,13 @@ export async function clearOfWindowEnd(windowMs, marginMs = 30_000) { if (left < marginMs) await new Promise((resolve) => setTimeout(resolve, left + 1_000)); } -/** Starts the Worker. `resend(request)` can stand in for Resend's answer. */ -export async function start({ bindings = {}, resend } = {}) { +/** + * Starts the Worker. `resend(request)` can stand in for Resend's answer, and `paygate(call)` answers + * every call to Paygate (`{ method, path, headers, body }`); each call is also kept in `paygateCalls`. + */ +export async function start({ bindings = {}, resend, paygate } = {}) { const outbox = []; + const paygateCalls = []; // Wrangler's Miniflare 5 still reads the familiar version 4 options. const mf = new Miniflare( convertV4MiniflareOptions({ @@ -39,8 +46,26 @@ export async function start({ bindings = {}, resend } = {}) { scriptPath: path.join(root, "dist/index.js"), compatibilityDate: config.compatibility_date, d1Databases: { DB: "floodwall-auth-test" }, - bindings: { ...config.vars, RESEND_API_KEY: KEY, AUTH_SECRET: SECRET, ...bindings }, + bindings: { + ...config.vars, + RESEND_API_KEY: KEY, + AUTH_SECRET: SECRET, + PAYGATE_SECRET_KEY: PAYGATE_KEY, + PAYGATE_WEBHOOK_SECRET, + ...bindings, + }, async outboundService(request) { + if (request.url.startsWith(`${PAYGATE}/`)) { + const text = await request.text(); + const call = { + method: request.method, + path: new URL(request.url).pathname, + headers: Object.fromEntries(request.headers), + body: text ? JSON.parse(text) : undefined, + }; + paygateCalls.push(call); + return (paygate && (await paygate(call))) || Response.json({ error: { code: "unexpected" } }, { status: 500 }); + } if (request.url !== "https://api.resend.com/emails") return new Response("unexpected fetch", { status: 599 }); const email = { headers: Object.fromEntries(request.headers), body: await request.json() }; const answer = resend ? await resend(email) : null; @@ -59,8 +84,11 @@ export async function start({ bindings = {}, resend } = {}) { } /** A request as the site would send it: JSON, from SITE, from one network. */ - async function call(pathname, { method = "POST", body, cookie, origin = SITE, ip = "203.0.113.7", base = API } = {}) { - const headers = { "CF-Connecting-IP": ip }; + async function call( + pathname, + { method = "POST", body, cookie, origin = SITE, ip = "203.0.113.7", base = API, headers: extra = {} } = {}, + ) { + const headers = { "CF-Connecting-IP": ip, ...extra }; if (origin) headers.Origin = origin; if (cookie) headers.Cookie = cookie; if (body !== undefined) headers["Content-Type"] = "application/json"; @@ -104,10 +132,11 @@ export async function start({ bindings = {}, resend } = {}) { async function reset() { outbox.length = 0; - for (const table of ["sessions", "users", "sign_in_codes", "rate_limits"]) { + paygateCalls.length = 0; + for (const table of ["sessions", "users", "sign_in_codes", "rate_limits", "billing_events"]) { await db.prepare(`DELETE FROM ${table}`).run(); } } - return { mf, db, outbox, call, lastCode, codeFor, signIn, age, reset, stop: () => mf.dispose() }; + return { mf, db, outbox, paygateCalls, call, lastCode, codeFor, signIn, age, reset, stop: () => mf.dispose() }; } diff --git a/api/wrangler.jsonc b/api/wrangler.jsonc index 3d4640a..15e17e4 100644 --- a/api/wrangler.jsonc +++ b/api/wrangler.jsonc @@ -19,7 +19,9 @@ "ALLOWED_ORIGINS": "https://floodwall.ai,https://preview.floodwall.ai", // "waitlist": new accounts wait for an admin to approve them at /app/admin. // "open": anyone can sign up and use the console, the waitlist included. - "SIGNUP_MODE": "waitlist" + "SIGNUP_MODE": "waitlist", + // Paygate, our Stripe hub. PAYGATE_SECRET_KEY and PAYGATE_WEBHOOK_SECRET are secrets. + "PAYGATE_URL": "https://pay.erpai.studio" }, // Clears out expired codes, sessions and rate-limit counts once a day. "triggers": { "crons": ["17 3 * * *"] }, diff --git a/docs/404.html b/docs/404.html index 94f1b2e..2d9eb32 100644 --- a/docs/404.html +++ b/docs/404.html @@ -33,8 +33,8 @@ - - + + diff --git a/docs/assets/index-B5vhWxNj.js b/docs/assets/index-B5vhWxNj.js new file mode 100644 index 0000000..ab14c20 --- /dev/null +++ b/docs/assets/index-B5vhWxNj.js @@ -0,0 +1,67 @@ +function RM(e,t){for(var i=0;ia[o]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))a(o);new MutationObserver(o=>{for(const c of o)if(c.type==="childList")for(const u of c.addedNodes)u.tagName==="LINK"&&u.rel==="modulepreload"&&a(u)}).observe(document,{childList:!0,subtree:!0});function i(o){const c={};return o.integrity&&(c.integrity=o.integrity),o.referrerPolicy&&(c.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?c.credentials="include":o.crossOrigin==="anonymous"?c.credentials="omit":c.credentials="same-origin",c}function a(o){if(o.ep)return;o.ep=!0;const c=i(o);fetch(o.href,c)}})();function CM(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var kp={exports:{}},fc={};var Wb;function TM(){if(Wb)return fc;Wb=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function i(a,o,c){var u=null;if(c!==void 0&&(u=""+c),o.key!==void 0&&(u=""+o.key),"key"in o){c={};for(var f in o)f!=="key"&&(c[f]=o[f])}else c=o;return o=c.ref,{$$typeof:e,type:a,key:u,ref:o!==void 0?o:null,props:c}}return fc.Fragment=t,fc.jsx=i,fc.jsxs=i,fc}var Zb;function AM(){return Zb||(Zb=1,kp.exports=TM()),kp.exports}var y=AM(),zp={exports:{}},it={};var Qb;function MM(){if(Qb)return it;Qb=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.portal"),i=Symbol.for("react.fragment"),a=Symbol.for("react.strict_mode"),o=Symbol.for("react.profiler"),c=Symbol.for("react.consumer"),u=Symbol.for("react.context"),f=Symbol.for("react.forward_ref"),d=Symbol.for("react.suspense"),m=Symbol.for("react.memo"),g=Symbol.for("react.lazy"),v=Symbol.for("react.activity"),S=Symbol.iterator;function x(M){return M===null||typeof M!="object"?null:(M=S&&M[S]||M["@@iterator"],typeof M=="function"?M:null)}var E={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},w=Object.assign,R={};function T(M,z,B){this.props=M,this.context=z,this.refs=R,this.updater=B||E}T.prototype.isReactComponent={},T.prototype.setState=function(M,z){if(typeof M!="object"&&typeof M!="function"&&M!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,M,z,"setState")},T.prototype.forceUpdate=function(M){this.updater.enqueueForceUpdate(this,M,"forceUpdate")};function O(){}O.prototype=T.prototype;function N(M,z,B){this.props=M,this.context=z,this.refs=R,this.updater=B||E}var j=N.prototype=new O;j.constructor=N,w(j,T.prototype),j.isPureReactComponent=!0;var L=Array.isArray;function P(){}var D={H:null,A:null,T:null,S:null},A=Object.prototype.hasOwnProperty;function F(M,z,B){var I=B.ref;return{$$typeof:e,type:M,key:z,ref:I!==void 0?I:null,props:B}}function H(M,z){return F(M.type,z,M.props)}function X(M){return typeof M=="object"&&M!==null&&M.$$typeof===e}function J(M){var z={"=":"=0",":":"=2"};return"$"+M.replace(/[=:]/g,function(B){return z[B]})}var $=/\/+/g;function ee(M,z){return typeof M=="object"&&M!==null&&M.key!=null?J(""+M.key):z.toString(36)}function re(M){switch(M.status){case"fulfilled":return M.value;case"rejected":throw M.reason;default:switch(typeof M.status=="string"?M.then(P,P):(M.status="pending",M.then(function(z){M.status==="pending"&&(M.status="fulfilled",M.value=z)},function(z){M.status==="pending"&&(M.status="rejected",M.reason=z)})),M.status){case"fulfilled":return M.value;case"rejected":throw M.reason}}throw M}function V(M,z,B,I,W){var ie=typeof M;(ie==="undefined"||ie==="boolean")&&(M=null);var fe=!1;if(M===null)fe=!0;else switch(ie){case"bigint":case"string":case"number":fe=!0;break;case"object":switch(M.$$typeof){case e:case t:fe=!0;break;case g:return fe=M._init,V(fe(M._payload),z,B,I,W)}}if(fe)return W=W(M),fe=I===""?"."+ee(M,0):I,L(W)?(B="",fe!=null&&(B=fe.replace($,"$&/")+"/"),V(W,z,B,"",function(Ae){return Ae})):W!=null&&(X(W)&&(W=H(W,B+(W.key==null||M&&M.key===W.key?"":(""+W.key).replace($,"$&/")+"/")+fe)),z.push(W)),1;fe=0;var pe=I===""?".":I+":";if(L(M))for(var ce=0;ce>>1,_=V[Y];if(0>>1;Yo(B,Z))I<_&&0>o(W,B)?(V[Y]=W,V[I]=Z,Y=I):(V[Y]=B,V[z]=Z,Y=z);else if(I<_&&0>o(W,Z))V[Y]=W,V[I]=Z,Y=I;else break e}}return K}function o(V,K){var Z=V.sortIndex-K.sortIndex;return Z!==0?Z:V.id-K.id}if(e.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var c=performance;e.unstable_now=function(){return c.now()}}else{var u=Date,f=u.now();e.unstable_now=function(){return u.now()-f}}var d=[],m=[],g=1,v=null,S=3,x=!1,E=!1,w=!1,R=!1,T=typeof setTimeout=="function"?setTimeout:null,O=typeof clearTimeout=="function"?clearTimeout:null,N=typeof setImmediate<"u"?setImmediate:null;function j(V){for(var K=i(m);K!==null;){if(K.callback===null)a(m);else if(K.startTime<=V)a(m),K.sortIndex=K.expirationTime,t(d,K);else break;K=i(m)}}function L(V){if(w=!1,j(V),!E)if(i(d)!==null)E=!0,P||(P=!0,J());else{var K=i(m);K!==null&&re(L,K.startTime-V)}}var P=!1,D=-1,A=5,F=-1;function H(){return R?!0:!(e.unstable_now()-FV&&H());){var Y=v.callback;if(typeof Y=="function"){v.callback=null,S=v.priorityLevel;var _=Y(v.expirationTime<=V);if(V=e.unstable_now(),typeof _=="function"){v.callback=_,j(V),K=!0;break t}v===i(d)&&a(d),j(V)}else a(d);v=i(d)}if(v!==null)K=!0;else{var M=i(m);M!==null&&re(L,M.startTime-V),K=!1}}break e}finally{v=null,S=Z,x=!1}K=void 0}}finally{K?J():P=!1}}}var J;if(typeof N=="function")J=function(){N(X)};else if(typeof MessageChannel<"u"){var $=new MessageChannel,ee=$.port2;$.port1.onmessage=X,J=function(){ee.postMessage(null)}}else J=function(){T(X,0)};function re(V,K){D=T(function(){V(e.unstable_now())},K)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(V){V.callback=null},e.unstable_forceFrameRate=function(V){0>V||125Y?(V.sortIndex=Z,t(m,V),i(d)===null&&V===i(m)&&(w?(O(D),D=-1):w=!0,re(L,Z-Y))):(V.sortIndex=_,t(d,V),E||x||(E=!0,P||(P=!0,J()))),V},e.unstable_shouldYield=H,e.unstable_wrapCallback=function(V){var K=S;return function(){var Z=S;S=K;try{return V.apply(this,arguments)}finally{S=Z}}}})(Vp)),Vp}var tx;function DM(){return tx||(tx=1,_p.exports=OM()),_p.exports}var Up={exports:{}},lr={};var nx;function NM(){if(nx)return lr;nx=1;var e=pu();function t(d){var m="https://react.dev/errors/"+d;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),Up.exports=NM(),Up.exports}var ix;function LM(){if(ix)return dc;ix=1;var e=DM(),t=pu(),i=QE();function a(n){var r="https://react.dev/errors/"+n;if(1_||(n.current=Y[_],Y[_]=null,_--)}function B(n,r){_++,Y[_]=n.current,n.current=r}var I=M(null),W=M(null),ie=M(null),fe=M(null);function pe(n,r){switch(B(ie,r),B(W,n),B(I,null),r.nodeType){case 9:case 11:n=(n=r.documentElement)&&(n=n.namespaceURI)?bb(n):0;break;default:if(n=r.tagName,r=r.namespaceURI)r=bb(r),n=xb(r,n);else switch(n){case"svg":n=1;break;case"math":n=2;break;default:n=0}}z(I),B(I,n)}function ce(){z(I),z(W),z(ie)}function Ae(n){n.memoizedState!==null&&B(fe,n);var r=I.current,s=xb(r,n.type);r!==s&&(B(W,n),B(I,s))}function ke(n){W.current===n&&(z(I),z(W)),fe.current===n&&(z(fe),oc._currentValue=Z)}var we,Re;function ye(n){if(we===void 0)try{throw Error()}catch(s){var r=s.stack.trim().match(/\n( *(at )?)/);we=r&&r[1]||"",Re=-1)":-1h||q[l]!==se[h]){var me=` +`+q[l].replace(" at new "," at ");return n.displayName&&me.includes("")&&(me=me.replace("",n.displayName)),me}while(1<=l&&0<=h);break}}}finally{ze=!1,Error.prepareStackTrace=s}return(s=n?n.displayName||n.name:"")?ye(s):""}function Qe(n,r){switch(n.tag){case 26:case 27:case 5:return ye(n.type);case 16:return ye("Lazy");case 13:return n.child!==r&&r!==null?ye("Suspense Fallback"):ye("Suspense");case 19:return ye("SuspenseList");case 0:case 15:return Ye(n.type,!1);case 11:return Ye(n.type.render,!1);case 1:return Ye(n.type,!0);case 31:return ye("Activity");default:return""}}function nt(n){try{var r="",s=null;do r+=Qe(n,s),s=n,n=n.return;while(n);return r}catch(l){return` +Error generating stack: `+l.message+` +`+l.stack}}var Ne=Object.prototype.hasOwnProperty,Xe=e.unstable_scheduleCallback,Me=e.unstable_cancelCallback,et=e.unstable_shouldYield,Et=e.unstable_requestPaint,at=e.unstable_now,ue=e.unstable_getCurrentPriorityLevel,be=e.unstable_ImmediatePriority,$e=e.unstable_UserBlockingPriority,Te=e.unstable_NormalPriority,Oe=e.unstable_LowPriority,bt=e.unstable_IdlePriority,Nt=e.log,xt=e.unstable_setDisableYieldValue,Ot=null,Lt=null;function Ft(n){if(typeof Nt=="function"&&xt(n),Lt&&typeof Lt.setStrictMode=="function")try{Lt.setStrictMode(Ot,n)}catch{}}var Yt=Math.clz32?Math.clz32:Gn,mn=Math.log,qn=Math.LN2;function Gn(n){return n>>>=0,n===0?32:31-(mn(n)/qn|0)|0}var bn=256,Rt=262144,un=4194304;function kt(n){var r=n&42;if(r!==0)return r;switch(n&-n){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return n&261888;case 262144:case 524288:case 1048576:case 2097152:return n&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return n&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return n}}function jn(n,r,s){var l=n.pendingLanes;if(l===0)return 0;var h=0,p=n.suspendedLanes,C=n.pingedLanes;n=n.warmLanes;var k=l&134217727;return k!==0?(l=k&~p,l!==0?h=kt(l):(C&=k,C!==0?h=kt(C):s||(s=k&~n,s!==0&&(h=kt(s))))):(k=l&~p,k!==0?h=kt(k):C!==0?h=kt(C):s||(s=l&~n,s!==0&&(h=kt(s)))),h===0?0:r!==0&&r!==h&&(r&p)===0&&(p=h&-h,s=r&-r,p>=s||p===32&&(s&4194048)!==0)?r:h}function Pn(n,r){return(n.pendingLanes&~(n.suspendedLanes&~n.pingedLanes)&r)===0}function ct(n,r){switch(n){case 1:case 2:case 4:case 8:case 64:return r+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return r+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function sn(){var n=un;return un<<=1,(un&62914560)===0&&(un=4194304),n}function Jt(n){for(var r=[],s=0;31>s;s++)r.push(n);return r}function _t(n,r){n.pendingLanes|=r,r!==268435456&&(n.suspendedLanes=0,n.pingedLanes=0,n.warmLanes=0)}function en(n,r,s,l,h,p){var C=n.pendingLanes;n.pendingLanes=s,n.suspendedLanes=0,n.pingedLanes=0,n.warmLanes=0,n.expiredLanes&=s,n.entangledLanes&=s,n.errorRecoveryDisabledLanes&=s,n.shellSuspendCounter=0;var k=n.entanglements,q=n.expirationTimes,se=n.hiddenUpdates;for(s=C&~s;0"u")return null;try{return n.activeElement||n.body}catch{return n.body}}var Ue=/[\n"\\]/g;function qe(n){return n.replace(Ue,function(r){return"\\"+r.charCodeAt(0).toString(16)+" "})}function Je(n,r,s,l,h,p,C,k){n.name="",C!=null&&typeof C!="function"&&typeof C!="symbol"&&typeof C!="boolean"?n.type=C:n.removeAttribute("type"),r!=null?C==="number"?(r===0&&n.value===""||n.value!=r)&&(n.value=""+qt(r)):n.value!==""+qt(r)&&(n.value=""+qt(r)):C!=="submit"&&C!=="reset"||n.removeAttribute("value"),r!=null?on(n,C,qt(r)):s!=null?on(n,C,qt(s)):l!=null&&n.removeAttribute("value"),h==null&&p!=null&&(n.defaultChecked=!!p),h!=null&&(n.checked=h&&typeof h!="function"&&typeof h!="symbol"),k!=null&&typeof k!="function"&&typeof k!="symbol"&&typeof k!="boolean"?n.name=""+qt(k):n.removeAttribute("name")}function At(n,r,s,l,h,p,C,k){if(p!=null&&typeof p!="function"&&typeof p!="symbol"&&typeof p!="boolean"&&(n.type=p),r!=null||s!=null){if(!(p!=="submit"&&p!=="reset"||r!=null)){oe(n);return}s=s!=null?""+qt(s):"",r=r!=null?""+qt(r):s,k||r===n.value||(n.value=r),n.defaultValue=r}l=l??h,l=typeof l!="function"&&typeof l!="symbol"&&!!l,n.checked=k?n.checked:!!l,n.defaultChecked=!!l,C!=null&&typeof C!="function"&&typeof C!="symbol"&&typeof C!="boolean"&&(n.name=C),oe(n)}function on(n,r,s){r==="number"&&xe(n.ownerDocument)===n||n.defaultValue===""+s||(n.defaultValue=""+s)}function Mt(n,r,s,l){if(n=n.options,r){r={};for(var h=0;h"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Rr=!1;if(zr)try{var Cr={};Object.defineProperty(Cr,"passive",{get:function(){Rr=!0}}),window.addEventListener("test",Cr,Cr),window.removeEventListener("test",Cr,Cr)}catch{Rr=!1}var mr=null,oo=null,pr=null;function lo(){if(pr)return pr;var n,r=oo,s=r.length,l,h="value"in mr?mr.value:mr.textContent,p=h.length;for(n=0;n=Ml),Tv=" ",Av=!1;function Mv(n,r){switch(n){case"keyup":return G5.indexOf(r.keyCode)!==-1;case"keydown":return r.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function jv(n){return n=n.detail,typeof n=="object"&&"data"in n?n.data:null}var co=!1;function X5(n,r){switch(n){case"compositionend":return jv(r);case"keypress":return r.which!==32?null:(Av=!0,Tv);case"textInput":return n=r.data,n===Tv&&Av?null:n;default:return null}}function $5(n,r){if(co)return n==="compositionend"||!Bh&&Mv(n,r)?(n=lo(),pr=oo=mr=null,co=!1,n):null;switch(n){case"paste":return null;case"keypress":if(!(r.ctrlKey||r.altKey||r.metaKey)||r.ctrlKey&&r.altKey){if(r.char&&1=r)return{node:s,offset:r-n};n=l}e:{for(;s;){if(s.nextSibling){s=s.nextSibling;break e}s=s.parentNode}s=void 0}s=_v(s)}}function Uv(n,r){return n&&r?n===r?!0:n&&n.nodeType===3?!1:r&&r.nodeType===3?Uv(n,r.parentNode):"contains"in n?n.contains(r):n.compareDocumentPosition?!!(n.compareDocumentPosition(r)&16):!1:!1}function Bv(n){n=n!=null&&n.ownerDocument!=null&&n.ownerDocument.defaultView!=null?n.ownerDocument.defaultView:window;for(var r=xe(n.document);r instanceof n.HTMLIFrameElement;){try{var s=typeof r.contentWindow.location.href=="string"}catch{s=!1}if(s)n=r.contentWindow;else break;r=xe(n.document)}return r}function Fh(n){var r=n&&n.nodeName&&n.nodeName.toLowerCase();return r&&(r==="input"&&(n.type==="text"||n.type==="search"||n.type==="tel"||n.type==="url"||n.type==="password")||r==="textarea"||n.contentEditable==="true")}var r3=zr&&"documentMode"in document&&11>=document.documentMode,uo=null,Yh=null,Nl=null,qh=!1;function Iv(n,r,s){var l=s.window===s?s.document:s.nodeType===9?s:s.ownerDocument;qh||uo==null||uo!==xe(l)||(l=uo,"selectionStart"in l&&Fh(l)?l={start:l.selectionStart,end:l.selectionEnd}:(l=(l.ownerDocument&&l.ownerDocument.defaultView||window).getSelection(),l={anchorNode:l.anchorNode,anchorOffset:l.anchorOffset,focusNode:l.focusNode,focusOffset:l.focusOffset}),Nl&&Dl(Nl,l)||(Nl=l,l=bf(Yh,"onSelect"),0>=C,h-=C,Bi=1<<32-Yt(r)+h|s<ht?(Tt=Be,Be=null):Tt=Be.sibling;var Pt=le(ne,Be,ae[ht],ve);if(Pt===null){Be===null&&(Be=Tt);break}n&&Be&&Pt.alternate===null&&r(ne,Be),Q=p(Pt,Q,ht),zt===null?Ge=Pt:zt.sibling=Pt,zt=Pt,Be=Tt}if(ht===ae.length)return s(ne,Be),jt&&la(ne,ht),Ge;if(Be===null){for(;htht?(Tt=Be,Be=null):Tt=Be.sibling;var is=le(ne,Be,Pt.value,ve);if(is===null){Be===null&&(Be=Tt);break}n&&Be&&is.alternate===null&&r(ne,Be),Q=p(is,Q,ht),zt===null?Ge=is:zt.sibling=is,zt=is,Be=Tt}if(Pt.done)return s(ne,Be),jt&&la(ne,ht),Ge;if(Be===null){for(;!Pt.done;ht++,Pt=ae.next())Pt=Se(ne,Pt.value,ve),Pt!==null&&(Q=p(Pt,Q,ht),zt===null?Ge=Pt:zt.sibling=Pt,zt=Pt);return jt&&la(ne,ht),Ge}for(Be=l(Be);!Pt.done;ht++,Pt=ae.next())Pt=de(Be,ne,ht,Pt.value,ve),Pt!==null&&(n&&Pt.alternate!==null&&Be.delete(Pt.key===null?ht:Pt.key),Q=p(Pt,Q,ht),zt===null?Ge=Pt:zt.sibling=Pt,zt=Pt);return n&&Be.forEach(function(EM){return r(ne,EM)}),jt&&la(ne,ht),Ge}function Zt(ne,Q,ae,ve){if(typeof ae=="object"&&ae!==null&&ae.type===w&&ae.key===null&&(ae=ae.props.children),typeof ae=="object"&&ae!==null){switch(ae.$$typeof){case x:e:{for(var Ge=ae.key;Q!==null;){if(Q.key===Ge){if(Ge=ae.type,Ge===w){if(Q.tag===7){s(ne,Q.sibling),ve=h(Q,ae.props.children),ve.return=ne,ne=ve;break e}}else if(Q.elementType===Ge||typeof Ge=="object"&&Ge!==null&&Ge.$$typeof===A&&Ns(Ge)===Q.type){s(ne,Q.sibling),ve=h(Q,ae.props),Vl(ve,ae),ve.return=ne,ne=ve;break e}s(ne,Q);break}else r(ne,Q);Q=Q.sibling}ae.type===w?(ve=As(ae.props.children,ne.mode,ve,ae.key),ve.return=ne,ne=ve):(ve=zu(ae.type,ae.key,ae.props,null,ne.mode,ve),Vl(ve,ae),ve.return=ne,ne=ve)}return C(ne);case E:e:{for(Ge=ae.key;Q!==null;){if(Q.key===Ge)if(Q.tag===4&&Q.stateNode.containerInfo===ae.containerInfo&&Q.stateNode.implementation===ae.implementation){s(ne,Q.sibling),ve=h(Q,ae.children||[]),ve.return=ne,ne=ve;break e}else{s(ne,Q);break}else r(ne,Q);Q=Q.sibling}ve=Qh(ae,ne.mode,ve),ve.return=ne,ne=ve}return C(ne);case A:return ae=Ns(ae),Zt(ne,Q,ae,ve)}if(re(ae))return _e(ne,Q,ae,ve);if(J(ae)){if(Ge=J(ae),typeof Ge!="function")throw Error(a(150));return ae=Ge.call(ae),Ze(ne,Q,ae,ve)}if(typeof ae.then=="function")return Zt(ne,Q,Hu(ae),ve);if(ae.$$typeof===N)return Zt(ne,Q,Vu(ne,ae),ve);Fu(ne,ae)}return typeof ae=="string"&&ae!==""||typeof ae=="number"||typeof ae=="bigint"?(ae=""+ae,Q!==null&&Q.tag===6?(s(ne,Q.sibling),ve=h(Q,ae),ve.return=ne,ne=ve):(s(ne,Q),ve=Zh(ae,ne.mode,ve),ve.return=ne,ne=ve),C(ne)):s(ne,Q)}return function(ne,Q,ae,ve){try{_l=0;var Ge=Zt(ne,Q,ae,ve);return wo=null,Ge}catch(Be){if(Be===So||Be===Bu)throw Be;var zt=Br(29,Be,null,ne.mode);return zt.lanes=ve,zt.return=ne,zt}}}var ks=u1(!0),f1=u1(!1),Ia=!1;function um(n){n.updateQueue={baseState:n.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function fm(n,r){n=n.updateQueue,r.updateQueue===n&&(r.updateQueue={baseState:n.baseState,firstBaseUpdate:n.firstBaseUpdate,lastBaseUpdate:n.lastBaseUpdate,shared:n.shared,callbacks:null})}function Ha(n){return{lane:n,tag:0,payload:null,callback:null,next:null}}function Fa(n,r,s){var l=n.updateQueue;if(l===null)return null;if(l=l.shared,(Vt&2)!==0){var h=l.pending;return h===null?r.next=r:(r.next=h.next,h.next=r),l.pending=r,r=ku(n),Xv(n,null,s),r}return Lu(n,l,r,s),ku(n)}function Ul(n,r,s){if(r=r.updateQueue,r!==null&&(r=r.shared,(s&4194048)!==0)){var l=r.lanes;l&=n.pendingLanes,s|=l,r.lanes=s,Kn(n,s)}}function dm(n,r){var s=n.updateQueue,l=n.alternate;if(l!==null&&(l=l.updateQueue,s===l)){var h=null,p=null;if(s=s.firstBaseUpdate,s!==null){do{var C={lane:s.lane,tag:s.tag,payload:s.payload,callback:null,next:null};p===null?h=p=C:p=p.next=C,s=s.next}while(s!==null);p===null?h=p=r:p=p.next=r}else h=p=r;s={baseState:l.baseState,firstBaseUpdate:h,lastBaseUpdate:p,shared:l.shared,callbacks:l.callbacks},n.updateQueue=s;return}n=s.lastBaseUpdate,n===null?s.firstBaseUpdate=r:n.next=r,s.lastBaseUpdate=r}var hm=!1;function Bl(){if(hm){var n=xo;if(n!==null)throw n}}function Il(n,r,s,l){hm=!1;var h=n.updateQueue;Ia=!1;var p=h.firstBaseUpdate,C=h.lastBaseUpdate,k=h.shared.pending;if(k!==null){h.shared.pending=null;var q=k,se=q.next;q.next=null,C===null?p=se:C.next=se,C=q;var me=n.alternate;me!==null&&(me=me.updateQueue,k=me.lastBaseUpdate,k!==C&&(k===null?me.firstBaseUpdate=se:k.next=se,me.lastBaseUpdate=q))}if(p!==null){var Se=h.baseState;C=0,me=se=q=null,k=p;do{var le=k.lane&-536870913,de=le!==k.lane;if(de?(Ct&le)===le:(l&le)===le){le!==0&&le===bo&&(hm=!0),me!==null&&(me=me.next={lane:0,tag:k.tag,payload:k.payload,callback:null,next:null});e:{var _e=n,Ze=k;le=r;var Zt=s;switch(Ze.tag){case 1:if(_e=Ze.payload,typeof _e=="function"){Se=_e.call(Zt,Se,le);break e}Se=_e;break e;case 3:_e.flags=_e.flags&-65537|128;case 0:if(_e=Ze.payload,le=typeof _e=="function"?_e.call(Zt,Se,le):_e,le==null)break e;Se=v({},Se,le);break e;case 2:Ia=!0}}le=k.callback,le!==null&&(n.flags|=64,de&&(n.flags|=8192),de=h.callbacks,de===null?h.callbacks=[le]:de.push(le))}else de={lane:le,tag:k.tag,payload:k.payload,callback:k.callback,next:null},me===null?(se=me=de,q=Se):me=me.next=de,C|=le;if(k=k.next,k===null){if(k=h.shared.pending,k===null)break;de=k,k=de.next,de.next=null,h.lastBaseUpdate=de,h.shared.pending=null}}while(!0);me===null&&(q=Se),h.baseState=q,h.firstBaseUpdate=se,h.lastBaseUpdate=me,p===null&&(h.shared.lanes=0),Xa|=C,n.lanes=C,n.memoizedState=Se}}function d1(n,r){if(typeof n!="function")throw Error(a(191,n));n.call(r)}function h1(n,r){var s=n.callbacks;if(s!==null)for(n.callbacks=null,n=0;np?p:8;var C=V.T,k={};V.T=k,Nm(n,!1,r,s);try{var q=h(),se=V.S;if(se!==null&&se(k,q),q!==null&&typeof q=="object"&&typeof q.then=="function"){var me=d3(q,l);Yl(n,r,me,qr(n))}else Yl(n,r,l,qr(n))}catch(Se){Yl(n,r,{then:function(){},status:"rejected",reason:Se},qr())}finally{K.p=p,C!==null&&k.types!==null&&(C.types=k.types),V.T=C}}function v3(){}function Om(n,r,s,l){if(n.tag!==5)throw Error(a(476));var h=q1(n).queue;Y1(n,h,r,Z,s===null?v3:function(){return G1(n),s(l)})}function q1(n){var r=n.memoizedState;if(r!==null)return r;r={memoizedState:Z,baseState:Z,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:da,lastRenderedState:Z},next:null};var s={};return r.next={memoizedState:s,baseState:s,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:da,lastRenderedState:s},next:null},n.memoizedState=r,n=n.alternate,n!==null&&(n.memoizedState=r),r}function G1(n){var r=q1(n);r.next===null&&(r=n.alternate.memoizedState),Yl(n,r.next.queue,{},qr())}function Dm(){return Jn(oc)}function K1(){return An().memoizedState}function X1(){return An().memoizedState}function b3(n){for(var r=n.return;r!==null;){switch(r.tag){case 24:case 3:var s=qr();n=Ha(s);var l=Fa(r,n,s);l!==null&&(Or(l,r,s),Ul(l,r,s)),r={cache:sm()},n.payload=r;return}r=r.return}}function x3(n,r,s){var l=qr();s={lane:l,revertLane:0,gesture:null,action:s,hasEagerState:!1,eagerState:null,next:null},Ju(n)?W1(r,s):(s=$h(n,r,s,l),s!==null&&(Or(s,n,l),Z1(s,r,l)))}function $1(n,r,s){var l=qr();Yl(n,r,s,l)}function Yl(n,r,s,l){var h={lane:l,revertLane:0,gesture:null,action:s,hasEagerState:!1,eagerState:null,next:null};if(Ju(n))W1(r,h);else{var p=n.alternate;if(n.lanes===0&&(p===null||p.lanes===0)&&(p=r.lastRenderedReducer,p!==null))try{var C=r.lastRenderedState,k=p(C,s);if(h.hasEagerState=!0,h.eagerState=k,Ur(k,C))return Lu(n,r,h,0),tn===null&&Nu(),!1}catch{}if(s=$h(n,r,h,l),s!==null)return Or(s,n,l),Z1(s,r,l),!0}return!1}function Nm(n,r,s,l){if(l={lane:2,revertLane:up(),gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},Ju(n)){if(r)throw Error(a(479))}else r=$h(n,s,l,2),r!==null&&Or(r,n,2)}function Ju(n){var r=n.alternate;return n===lt||r!==null&&r===lt}function W1(n,r){Ro=Gu=!0;var s=n.pending;s===null?r.next=r:(r.next=s.next,s.next=r),n.pending=r}function Z1(n,r,s){if((s&4194048)!==0){var l=r.lanes;l&=n.pendingLanes,s|=l,r.lanes=s,Kn(n,s)}}var ql={readContext:Jn,use:$u,useCallback:xn,useContext:xn,useEffect:xn,useImperativeHandle:xn,useLayoutEffect:xn,useInsertionEffect:xn,useMemo:xn,useReducer:xn,useRef:xn,useState:xn,useDebugValue:xn,useDeferredValue:xn,useTransition:xn,useSyncExternalStore:xn,useId:xn,useHostTransitionStatus:xn,useFormState:xn,useActionState:xn,useOptimistic:xn,useMemoCache:xn,useCacheRefresh:xn};ql.useEffectEvent=xn;var Q1={readContext:Jn,use:$u,useCallback:function(n,r){return yr().memoizedState=[n,r===void 0?null:r],n},useContext:Jn,useEffect:z1,useImperativeHandle:function(n,r,s){s=s!=null?s.concat([n]):null,Zu(4194308,4,U1.bind(null,r,n),s)},useLayoutEffect:function(n,r){return Zu(4194308,4,n,r)},useInsertionEffect:function(n,r){Zu(4,2,n,r)},useMemo:function(n,r){var s=yr();r=r===void 0?null:r;var l=n();if(zs){Ft(!0);try{n()}finally{Ft(!1)}}return s.memoizedState=[l,r],l},useReducer:function(n,r,s){var l=yr();if(s!==void 0){var h=s(r);if(zs){Ft(!0);try{s(r)}finally{Ft(!1)}}}else h=r;return l.memoizedState=l.baseState=h,n={pending:null,lanes:0,dispatch:null,lastRenderedReducer:n,lastRenderedState:h},l.queue=n,n=n.dispatch=x3.bind(null,lt,n),[l.memoizedState,n]},useRef:function(n){var r=yr();return n={current:n},r.memoizedState=n},useState:function(n){n=Cm(n);var r=n.queue,s=$1.bind(null,lt,r);return r.dispatch=s,[n.memoizedState,s]},useDebugValue:Mm,useDeferredValue:function(n,r){var s=yr();return jm(s,n,r)},useTransition:function(){var n=Cm(!1);return n=Y1.bind(null,lt,n.queue,!0,!1),yr().memoizedState=n,[!1,n]},useSyncExternalStore:function(n,r,s){var l=lt,h=yr();if(jt){if(s===void 0)throw Error(a(407));s=s()}else{if(s=r(),tn===null)throw Error(a(349));(Ct&127)!==0||b1(l,r,s)}h.memoizedState=s;var p={value:s,getSnapshot:r};return h.queue=p,z1(S1.bind(null,l,p,n),[n]),l.flags|=2048,To(9,{destroy:void 0},x1.bind(null,l,p,s,r),null),s},useId:function(){var n=yr(),r=tn.identifierPrefix;if(jt){var s=Ii,l=Bi;s=(l&~(1<<32-Yt(l)-1)).toString(32)+s,r="_"+r+"R_"+s,s=Ku++,0<\/script>",p=p.removeChild(p.firstChild);break;case"select":p=typeof l.is=="string"?C.createElement("select",{is:l.is}):C.createElement("select"),l.multiple?p.multiple=!0:l.size&&(p.size=l.size);break;default:p=typeof l.is=="string"?C.createElement(h,{is:l.is}):C.createElement(h)}}p[Ce]=r,p[je]=l;e:for(C=r.child;C!==null;){if(C.tag===5||C.tag===6)p.appendChild(C.stateNode);else if(C.tag!==4&&C.tag!==27&&C.child!==null){C.child.return=C,C=C.child;continue}if(C===r)break e;for(;C.sibling===null;){if(C.return===null||C.return===r)break e;C=C.return}C.sibling.return=C.return,C=C.sibling}r.stateNode=p;e:switch(tr(p,h,l),h){case"button":case"input":case"select":case"textarea":l=!!l.autoFocus;break e;case"img":l=!0;break e;default:l=!1}l&&ma(r)}}return cn(r),Gm(r,r.type,n===null?null:n.memoizedProps,r.pendingProps,s),null;case 6:if(n&&r.stateNode!=null)n.memoizedProps!==l&&ma(r);else{if(typeof l!="string"&&r.stateNode===null)throw Error(a(166));if(n=ie.current,yo(r)){if(n=r.stateNode,s=r.memoizedProps,l=null,h=Qn,h!==null)switch(h.tag){case 27:case 5:l=h.memoizedProps}n[Ce]=r,n=!!(n.nodeValue===s||l!==null&&l.suppressHydrationWarning===!0||yb(n.nodeValue,s)),n||Ua(r,!0)}else n=xf(n).createTextNode(l),n[Ce]=r,r.stateNode=n}return cn(r),null;case 31:if(s=r.memoizedState,n===null||n.memoizedState!==null){if(l=yo(r),s!==null){if(n===null){if(!l)throw Error(a(318));if(n=r.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(a(557));n[Ce]=r}else Ms(),(r.flags&128)===0&&(r.memoizedState=null),r.flags|=4;cn(r),n=!1}else s=nm(),n!==null&&n.memoizedState!==null&&(n.memoizedState.hydrationErrors=s),n=!0;if(!n)return r.flags&256?(Hr(r),r):(Hr(r),null);if((r.flags&128)!==0)throw Error(a(558))}return cn(r),null;case 13:if(l=r.memoizedState,n===null||n.memoizedState!==null&&n.memoizedState.dehydrated!==null){if(h=yo(r),l!==null&&l.dehydrated!==null){if(n===null){if(!h)throw Error(a(318));if(h=r.memoizedState,h=h!==null?h.dehydrated:null,!h)throw Error(a(317));h[Ce]=r}else Ms(),(r.flags&128)===0&&(r.memoizedState=null),r.flags|=4;cn(r),h=!1}else h=nm(),n!==null&&n.memoizedState!==null&&(n.memoizedState.hydrationErrors=h),h=!0;if(!h)return r.flags&256?(Hr(r),r):(Hr(r),null)}return Hr(r),(r.flags&128)!==0?(r.lanes=s,r):(s=l!==null,n=n!==null&&n.memoizedState!==null,s&&(l=r.child,h=null,l.alternate!==null&&l.alternate.memoizedState!==null&&l.alternate.memoizedState.cachePool!==null&&(h=l.alternate.memoizedState.cachePool.pool),p=null,l.memoizedState!==null&&l.memoizedState.cachePool!==null&&(p=l.memoizedState.cachePool.pool),p!==h&&(l.flags|=2048)),s!==n&&s&&(r.child.flags|=8192),af(r,r.updateQueue),cn(r),null);case 4:return ce(),n===null&&mp(r.stateNode.containerInfo),cn(r),null;case 10:return ua(r.type),cn(r),null;case 19:if(z(Tn),l=r.memoizedState,l===null)return cn(r),null;if(h=(r.flags&128)!==0,p=l.rendering,p===null)if(h)Kl(l,!1);else{if(Sn!==0||n!==null&&(n.flags&128)!==0)for(n=r.child;n!==null;){if(p=qu(n),p!==null){for(r.flags|=128,Kl(l,!1),n=p.updateQueue,r.updateQueue=n,af(r,n),r.subtreeFlags=0,n=s,s=r.child;s!==null;)$v(s,n),s=s.sibling;return B(Tn,Tn.current&1|2),jt&&la(r,l.treeForkCount),r.child}n=n.sibling}l.tail!==null&&at()>uf&&(r.flags|=128,h=!0,Kl(l,!1),r.lanes=4194304)}else{if(!h)if(n=qu(p),n!==null){if(r.flags|=128,h=!0,n=n.updateQueue,r.updateQueue=n,af(r,n),Kl(l,!0),l.tail===null&&l.tailMode==="hidden"&&!p.alternate&&!jt)return cn(r),null}else 2*at()-l.renderingStartTime>uf&&s!==536870912&&(r.flags|=128,h=!0,Kl(l,!1),r.lanes=4194304);l.isBackwards?(p.sibling=r.child,r.child=p):(n=l.last,n!==null?n.sibling=p:r.child=p,l.last=p)}return l.tail!==null?(n=l.tail,l.rendering=n,l.tail=n.sibling,l.renderingStartTime=at(),n.sibling=null,s=Tn.current,B(Tn,h?s&1|2:s&1),jt&&la(r,l.treeForkCount),n):(cn(r),null);case 22:case 23:return Hr(r),pm(),l=r.memoizedState!==null,n!==null?n.memoizedState!==null!==l&&(r.flags|=8192):l&&(r.flags|=8192),l?(s&536870912)!==0&&(r.flags&128)===0&&(cn(r),r.subtreeFlags&6&&(r.flags|=8192)):cn(r),s=r.updateQueue,s!==null&&af(r,s.retryQueue),s=null,n!==null&&n.memoizedState!==null&&n.memoizedState.cachePool!==null&&(s=n.memoizedState.cachePool.pool),l=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(l=r.memoizedState.cachePool.pool),l!==s&&(r.flags|=2048),n!==null&&z(Ds),null;case 24:return s=null,n!==null&&(s=n.memoizedState.cache),r.memoizedState.cache!==s&&(r.flags|=2048),ua(Dn),cn(r),null;case 25:return null;case 30:return null}throw Error(a(156,r.tag))}function C3(n,r){switch(em(r),r.tag){case 1:return n=r.flags,n&65536?(r.flags=n&-65537|128,r):null;case 3:return ua(Dn),ce(),n=r.flags,(n&65536)!==0&&(n&128)===0?(r.flags=n&-65537|128,r):null;case 26:case 27:case 5:return ke(r),null;case 31:if(r.memoizedState!==null){if(Hr(r),r.alternate===null)throw Error(a(340));Ms()}return n=r.flags,n&65536?(r.flags=n&-65537|128,r):null;case 13:if(Hr(r),n=r.memoizedState,n!==null&&n.dehydrated!==null){if(r.alternate===null)throw Error(a(340));Ms()}return n=r.flags,n&65536?(r.flags=n&-65537|128,r):null;case 19:return z(Tn),null;case 4:return ce(),null;case 10:return ua(r.type),null;case 22:case 23:return Hr(r),pm(),n!==null&&z(Ds),n=r.flags,n&65536?(r.flags=n&-65537|128,r):null;case 24:return ua(Dn),null;case 25:return null;default:return null}}function w2(n,r){switch(em(r),r.tag){case 3:ua(Dn),ce();break;case 26:case 27:case 5:ke(r);break;case 4:ce();break;case 31:r.memoizedState!==null&&Hr(r);break;case 13:Hr(r);break;case 19:z(Tn);break;case 10:ua(r.type);break;case 22:case 23:Hr(r),pm(),n!==null&&z(Ds);break;case 24:ua(Dn)}}function Xl(n,r){try{var s=r.updateQueue,l=s!==null?s.lastEffect:null;if(l!==null){var h=l.next;s=h;do{if((s.tag&n)===n){l=void 0;var p=s.create,C=s.inst;l=p(),C.destroy=l}s=s.next}while(s!==h)}}catch(k){Kt(r,r.return,k)}}function Ga(n,r,s){try{var l=r.updateQueue,h=l!==null?l.lastEffect:null;if(h!==null){var p=h.next;l=p;do{if((l.tag&n)===n){var C=l.inst,k=C.destroy;if(k!==void 0){C.destroy=void 0,h=r;var q=s,se=k;try{se()}catch(me){Kt(h,q,me)}}}l=l.next}while(l!==p)}}catch(me){Kt(r,r.return,me)}}function E2(n){var r=n.updateQueue;if(r!==null){var s=n.stateNode;try{h1(r,s)}catch(l){Kt(n,n.return,l)}}}function R2(n,r,s){s.props=Ps(n.type,n.memoizedProps),s.state=n.memoizedState;try{s.componentWillUnmount()}catch(l){Kt(n,r,l)}}function $l(n,r){try{var s=n.ref;if(s!==null){switch(n.tag){case 26:case 27:case 5:var l=n.stateNode;break;case 30:l=n.stateNode;break;default:l=n.stateNode}typeof s=="function"?n.refCleanup=s(l):s.current=l}}catch(h){Kt(n,r,h)}}function Hi(n,r){var s=n.ref,l=n.refCleanup;if(s!==null)if(typeof l=="function")try{l()}catch(h){Kt(n,r,h)}finally{n.refCleanup=null,n=n.alternate,n!=null&&(n.refCleanup=null)}else if(typeof s=="function")try{s(null)}catch(h){Kt(n,r,h)}else s.current=null}function C2(n){var r=n.type,s=n.memoizedProps,l=n.stateNode;try{e:switch(r){case"button":case"input":case"select":case"textarea":s.autoFocus&&l.focus();break e;case"img":s.src?l.src=s.src:s.srcSet&&(l.srcset=s.srcSet)}}catch(h){Kt(n,n.return,h)}}function Km(n,r,s){try{var l=n.stateNode;K3(l,n.type,s,r),l[je]=r}catch(h){Kt(n,n.return,h)}}function T2(n){return n.tag===5||n.tag===3||n.tag===26||n.tag===27&&Ja(n.type)||n.tag===4}function Xm(n){e:for(;;){for(;n.sibling===null;){if(n.return===null||T2(n.return))return null;n=n.return}for(n.sibling.return=n.return,n=n.sibling;n.tag!==5&&n.tag!==6&&n.tag!==18;){if(n.tag===27&&Ja(n.type)||n.flags&2||n.child===null||n.tag===4)continue e;n.child.return=n,n=n.child}if(!(n.flags&2))return n.stateNode}}function $m(n,r,s){var l=n.tag;if(l===5||l===6)n=n.stateNode,r?(s.nodeType===9?s.body:s.nodeName==="HTML"?s.ownerDocument.body:s).insertBefore(n,r):(r=s.nodeType===9?s.body:s.nodeName==="HTML"?s.ownerDocument.body:s,r.appendChild(n),s=s._reactRootContainer,s!=null||r.onclick!==null||(r.onclick=Lr));else if(l!==4&&(l===27&&Ja(n.type)&&(s=n.stateNode,r=null),n=n.child,n!==null))for($m(n,r,s),n=n.sibling;n!==null;)$m(n,r,s),n=n.sibling}function sf(n,r,s){var l=n.tag;if(l===5||l===6)n=n.stateNode,r?s.insertBefore(n,r):s.appendChild(n);else if(l!==4&&(l===27&&Ja(n.type)&&(s=n.stateNode),n=n.child,n!==null))for(sf(n,r,s),n=n.sibling;n!==null;)sf(n,r,s),n=n.sibling}function A2(n){var r=n.stateNode,s=n.memoizedProps;try{for(var l=n.type,h=r.attributes;h.length;)r.removeAttributeNode(h[0]);tr(r,l,s),r[Ce]=n,r[je]=s}catch(p){Kt(n,n.return,p)}}var pa=!1,kn=!1,Wm=!1,M2=typeof WeakSet=="function"?WeakSet:Set,$n=null;function T3(n,r){if(n=n.containerInfo,yp=Af,n=Bv(n),Fh(n)){if("selectionStart"in n)var s={start:n.selectionStart,end:n.selectionEnd};else e:{s=(s=n.ownerDocument)&&s.defaultView||window;var l=s.getSelection&&s.getSelection();if(l&&l.rangeCount!==0){s=l.anchorNode;var h=l.anchorOffset,p=l.focusNode;l=l.focusOffset;try{s.nodeType,p.nodeType}catch{s=null;break e}var C=0,k=-1,q=-1,se=0,me=0,Se=n,le=null;t:for(;;){for(var de;Se!==s||h!==0&&Se.nodeType!==3||(k=C+h),Se!==p||l!==0&&Se.nodeType!==3||(q=C+l),Se.nodeType===3&&(C+=Se.nodeValue.length),(de=Se.firstChild)!==null;)le=Se,Se=de;for(;;){if(Se===n)break t;if(le===s&&++se===h&&(k=C),le===p&&++me===l&&(q=C),(de=Se.nextSibling)!==null)break;Se=le,le=Se.parentNode}Se=de}s=k===-1||q===-1?null:{start:k,end:q}}else s=null}s=s||{start:0,end:0}}else s=null;for(vp={focusedElem:n,selectionRange:s},Af=!1,$n=r;$n!==null;)if(r=$n,n=r.child,(r.subtreeFlags&1028)!==0&&n!==null)n.return=r,$n=n;else for(;$n!==null;){switch(r=$n,p=r.alternate,n=r.flags,r.tag){case 0:if((n&4)!==0&&(n=r.updateQueue,n=n!==null?n.events:null,n!==null))for(s=0;s title"))),tr(p,l,s),p[Ce]=n,st(p),l=p;break e;case"link":var C=kb("link","href",h).get(l+(s.href||""));if(C){for(var k=0;kZt&&(C=Zt,Zt=Ze,Ze=C);var ne=Vv(k,Ze),Q=Vv(k,Zt);if(ne&&Q&&(de.rangeCount!==1||de.anchorNode!==ne.node||de.anchorOffset!==ne.offset||de.focusNode!==Q.node||de.focusOffset!==Q.offset)){var ae=Se.createRange();ae.setStart(ne.node,ne.offset),de.removeAllRanges(),Ze>Zt?(de.addRange(ae),de.extend(Q.node,Q.offset)):(ae.setEnd(Q.node,Q.offset),de.addRange(ae))}}}}for(Se=[],de=k;de=de.parentNode;)de.nodeType===1&&Se.push({element:de,left:de.scrollLeft,top:de.scrollTop});for(typeof k.focus=="function"&&k.focus(),k=0;ks?32:s,V.T=null,s=rp,rp=null;var p=Wa,C=xa;if(In=0,Do=Wa=null,xa=0,(Vt&6)!==0)throw Error(a(331));var k=Vt;if(Vt|=4,U2(p.current),P2(p,p.current,C,s),Vt=k,tc(0,!1),Lt&&typeof Lt.onPostCommitFiberRoot=="function")try{Lt.onPostCommitFiberRoot(Ot,p)}catch{}return!0}finally{K.p=h,V.T=l,rb(n,r)}}function ab(n,r,s){r=ii(s,r),r=Pm(n.stateNode,r,2),n=Fa(n,r,2),n!==null&&(_t(n,2),Fi(n))}function Kt(n,r,s){if(n.tag===3)ab(n,n,s);else for(;r!==null;){if(r.tag===3){ab(r,n,s);break}else if(r.tag===1){var l=r.stateNode;if(typeof r.type.getDerivedStateFromError=="function"||typeof l.componentDidCatch=="function"&&($a===null||!$a.has(l))){n=ii(s,n),s=s2(2),l=Fa(r,s,2),l!==null&&(o2(s,l,r,n),_t(l,2),Fi(l));break}}r=r.return}}function op(n,r,s){var l=n.pingCache;if(l===null){l=n.pingCache=new j3;var h=new Set;l.set(r,h)}else h=l.get(r),h===void 0&&(h=new Set,l.set(r,h));h.has(s)||(Jm=!0,h.add(s),n=k3.bind(null,n,r,s),r.then(n,n))}function k3(n,r,s){var l=n.pingCache;l!==null&&l.delete(r),n.pingedLanes|=n.suspendedLanes&s,n.warmLanes&=~s,tn===n&&(Ct&s)===s&&(Sn===4||Sn===3&&(Ct&62914560)===Ct&&300>at()-cf?(Vt&2)===0&&No(n,0):ep|=s,Oo===Ct&&(Oo=0)),Fi(n)}function sb(n,r){r===0&&(r=sn()),n=Ts(n,r),n!==null&&(_t(n,r),Fi(n))}function z3(n){var r=n.memoizedState,s=0;r!==null&&(s=r.retryLane),sb(n,s)}function P3(n,r){var s=0;switch(n.tag){case 31:case 13:var l=n.stateNode,h=n.memoizedState;h!==null&&(s=h.retryLane);break;case 19:l=n.stateNode;break;case 22:l=n.stateNode._retryCache;break;default:throw Error(a(314))}l!==null&&l.delete(r),sb(n,s)}function _3(n,r){return Xe(n,r)}var gf=null,ko=null,lp=!1,yf=!1,cp=!1,Qa=0;function Fi(n){n!==ko&&n.next===null&&(ko===null?gf=ko=n:ko=ko.next=n),yf=!0,lp||(lp=!0,U3())}function tc(n,r){if(!cp&&yf){cp=!0;do for(var s=!1,l=gf;l!==null;){if(n!==0){var h=l.pendingLanes;if(h===0)var p=0;else{var C=l.suspendedLanes,k=l.pingedLanes;p=(1<<31-Yt(42|n)+1)-1,p&=h&~(C&~k),p=p&201326741?p&201326741|1:p?p|2:0}p!==0&&(s=!0,ub(l,p))}else p=Ct,p=jn(l,l===tn?p:0,l.cancelPendingCommit!==null||l.timeoutHandle!==-1),(p&3)===0||Pn(l,p)||(s=!0,ub(l,p));l=l.next}while(s);cp=!1}}function V3(){ob()}function ob(){yf=lp=!1;var n=0;Qa!==0&&$3()&&(n=Qa);for(var r=at(),s=null,l=gf;l!==null;){var h=l.next,p=lb(l,r);p===0?(l.next=null,s===null?gf=h:s.next=h,h===null&&(ko=s)):(s=l,(n!==0||(p&3)!==0)&&(yf=!0)),l=h}In!==0&&In!==5||tc(n),Qa!==0&&(Qa=0)}function lb(n,r){for(var s=n.suspendedLanes,l=n.pingedLanes,h=n.expirationTimes,p=n.pendingLanes&-62914561;0k)break;var me=q.transferSize,Se=q.initiatorType;me&&vb(Se)&&(q=q.responseEnd,C+=me*(q"u"?null:document;function Ob(n,r,s){var l=zo;if(l&&typeof r=="string"&&r){var h=qe(r);h='link[rel="'+n+'"][href="'+h+'"]',typeof s=="string"&&(h+='[crossorigin="'+s+'"]'),jb.has(h)||(jb.add(h),n={rel:n,crossOrigin:s,href:r},l.querySelector(h)===null&&(r=l.createElement("link"),tr(r,"link",n),st(r),l.head.appendChild(r)))}}function iM(n){Sa.D(n),Ob("dns-prefetch",n,null)}function aM(n,r){Sa.C(n,r),Ob("preconnect",n,r)}function sM(n,r,s){Sa.L(n,r,s);var l=zo;if(l&&n&&r){var h='link[rel="preload"][as="'+qe(r)+'"]';r==="image"&&s&&s.imageSrcSet?(h+='[imagesrcset="'+qe(s.imageSrcSet)+'"]',typeof s.imageSizes=="string"&&(h+='[imagesizes="'+qe(s.imageSizes)+'"]')):h+='[href="'+qe(n)+'"]';var p=h;switch(r){case"style":p=Po(n);break;case"script":p=_o(n)}ui.has(p)||(n=v({rel:"preload",href:r==="image"&&s&&s.imageSrcSet?void 0:n,as:r},s),ui.set(p,n),l.querySelector(h)!==null||r==="style"&&l.querySelector(ac(p))||r==="script"&&l.querySelector(sc(p))||(r=l.createElement("link"),tr(r,"link",n),st(r),l.head.appendChild(r)))}}function oM(n,r){Sa.m(n,r);var s=zo;if(s&&n){var l=r&&typeof r.as=="string"?r.as:"script",h='link[rel="modulepreload"][as="'+qe(l)+'"][href="'+qe(n)+'"]',p=h;switch(l){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":p=_o(n)}if(!ui.has(p)&&(n=v({rel:"modulepreload",href:n},r),ui.set(p,n),s.querySelector(h)===null)){switch(l){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(s.querySelector(sc(p)))return}l=s.createElement("link"),tr(l,"link",n),st(l),s.head.appendChild(l)}}}function lM(n,r,s){Sa.S(n,r,s);var l=zo;if(l&&n){var h=Ht(l).hoistableStyles,p=Po(n);r=r||"default";var C=h.get(p);if(!C){var k={loading:0,preload:null};if(C=l.querySelector(ac(p)))k.loading=5;else{n=v({rel:"stylesheet",href:n,"data-precedence":r},s),(s=ui.get(p))&&Cp(n,s);var q=C=l.createElement("link");st(q),tr(q,"link",n),q._p=new Promise(function(se,me){q.onload=se,q.onerror=me}),q.addEventListener("load",function(){k.loading|=1}),q.addEventListener("error",function(){k.loading|=2}),k.loading|=4,wf(C,r,l)}C={type:"stylesheet",instance:C,count:1,state:k},h.set(p,C)}}}function cM(n,r){Sa.X(n,r);var s=zo;if(s&&n){var l=Ht(s).hoistableScripts,h=_o(n),p=l.get(h);p||(p=s.querySelector(sc(h)),p||(n=v({src:n,async:!0},r),(r=ui.get(h))&&Tp(n,r),p=s.createElement("script"),st(p),tr(p,"link",n),s.head.appendChild(p)),p={type:"script",instance:p,count:1,state:null},l.set(h,p))}}function uM(n,r){Sa.M(n,r);var s=zo;if(s&&n){var l=Ht(s).hoistableScripts,h=_o(n),p=l.get(h);p||(p=s.querySelector(sc(h)),p||(n=v({src:n,async:!0,type:"module"},r),(r=ui.get(h))&&Tp(n,r),p=s.createElement("script"),st(p),tr(p,"link",n),s.head.appendChild(p)),p={type:"script",instance:p,count:1,state:null},l.set(h,p))}}function Db(n,r,s,l){var h=(h=ie.current)?Sf(h):null;if(!h)throw Error(a(446));switch(n){case"meta":case"title":return null;case"style":return typeof s.precedence=="string"&&typeof s.href=="string"?(r=Po(s.href),s=Ht(h).hoistableStyles,l=s.get(r),l||(l={type:"style",instance:null,count:0,state:null},s.set(r,l)),l):{type:"void",instance:null,count:0,state:null};case"link":if(s.rel==="stylesheet"&&typeof s.href=="string"&&typeof s.precedence=="string"){n=Po(s.href);var p=Ht(h).hoistableStyles,C=p.get(n);if(C||(h=h.ownerDocument||h,C={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},p.set(n,C),(p=h.querySelector(ac(n)))&&!p._p&&(C.instance=p,C.state.loading=5),ui.has(n)||(s={rel:"preload",as:"style",href:s.href,crossOrigin:s.crossOrigin,integrity:s.integrity,media:s.media,hrefLang:s.hrefLang,referrerPolicy:s.referrerPolicy},ui.set(n,s),p||fM(h,n,s,C.state))),r&&l===null)throw Error(a(528,""));return C}if(r&&l!==null)throw Error(a(529,""));return null;case"script":return r=s.async,s=s.src,typeof s=="string"&&r&&typeof r!="function"&&typeof r!="symbol"?(r=_o(s),s=Ht(h).hoistableScripts,l=s.get(r),l||(l={type:"script",instance:null,count:0,state:null},s.set(r,l)),l):{type:"void",instance:null,count:0,state:null};default:throw Error(a(444,n))}}function Po(n){return'href="'+qe(n)+'"'}function ac(n){return'link[rel="stylesheet"]['+n+"]"}function Nb(n){return v({},n,{"data-precedence":n.precedence,precedence:null})}function fM(n,r,s,l){n.querySelector('link[rel="preload"][as="style"]['+r+"]")?l.loading=1:(r=n.createElement("link"),l.preload=r,r.addEventListener("load",function(){return l.loading|=1}),r.addEventListener("error",function(){return l.loading|=2}),tr(r,"link",s),st(r),n.head.appendChild(r))}function _o(n){return'[src="'+qe(n)+'"]'}function sc(n){return"script[async]"+n}function Lb(n,r,s){if(r.count++,r.instance===null)switch(r.type){case"style":var l=n.querySelector('style[data-href~="'+qe(s.href)+'"]');if(l)return r.instance=l,st(l),l;var h=v({},s,{"data-href":s.href,"data-precedence":s.precedence,href:null,precedence:null});return l=(n.ownerDocument||n).createElement("style"),st(l),tr(l,"style",h),wf(l,s.precedence,n),r.instance=l;case"stylesheet":h=Po(s.href);var p=n.querySelector(ac(h));if(p)return r.state.loading|=4,r.instance=p,st(p),p;l=Nb(s),(h=ui.get(h))&&Cp(l,h),p=(n.ownerDocument||n).createElement("link"),st(p);var C=p;return C._p=new Promise(function(k,q){C.onload=k,C.onerror=q}),tr(p,"link",l),r.state.loading|=4,wf(p,s.precedence,n),r.instance=p;case"script":return p=_o(s.src),(h=n.querySelector(sc(p)))?(r.instance=h,st(h),h):(l=s,(h=ui.get(p))&&(l=v({},s),Tp(l,h)),n=n.ownerDocument||n,h=n.createElement("script"),st(h),tr(h,"link",l),n.head.appendChild(h),r.instance=h);case"void":return null;default:throw Error(a(443,r.type))}else r.type==="stylesheet"&&(r.state.loading&4)===0&&(l=r.instance,r.state.loading|=4,wf(l,s.precedence,n));return r.instance}function wf(n,r,s){for(var l=s.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),h=l.length?l[l.length-1]:null,p=h,C=0;C title"):null)}function dM(n,r,s){if(s===1||r.itemProp!=null)return!1;switch(n){case"meta":case"title":return!0;case"style":if(typeof r.precedence!="string"||typeof r.href!="string"||r.href==="")break;return!0;case"link":if(typeof r.rel!="string"||typeof r.href!="string"||r.href===""||r.onLoad||r.onError)break;return r.rel==="stylesheet"?(n=r.disabled,typeof r.precedence=="string"&&n==null):!0;case"script":if(r.async&&typeof r.async!="function"&&typeof r.async!="symbol"&&!r.onLoad&&!r.onError&&r.src&&typeof r.src=="string")return!0}return!1}function Pb(n){return!(n.type==="stylesheet"&&(n.state.loading&3)===0)}function hM(n,r,s,l){if(s.type==="stylesheet"&&(typeof l.media!="string"||matchMedia(l.media).matches!==!1)&&(s.state.loading&4)===0){if(s.instance===null){var h=Po(l.href),p=r.querySelector(ac(h));if(p){r=p._p,r!==null&&typeof r=="object"&&typeof r.then=="function"&&(n.count++,n=Rf.bind(n),r.then(n,n)),s.state.loading|=4,s.instance=p,st(p);return}p=r.ownerDocument||r,l=Nb(l),(h=ui.get(h))&&Cp(l,h),p=p.createElement("link"),st(p);var C=p;C._p=new Promise(function(k,q){C.onload=k,C.onerror=q}),tr(p,"link",l),s.instance=p}n.stylesheets===null&&(n.stylesheets=new Map),n.stylesheets.set(s,r),(r=s.state.preload)&&(s.state.loading&3)===0&&(n.count++,s=Rf.bind(n),r.addEventListener("load",s),r.addEventListener("error",s))}}var Ap=0;function mM(n,r){return n.stylesheets&&n.count===0&&Tf(n,n.stylesheets),0Ap?50:800)+r);return n.unsuspend=s,function(){n.unsuspend=null,clearTimeout(l),clearTimeout(h)}}:null}function Rf(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Tf(this,this.stylesheets);else if(this.unsuspend){var n=this.unsuspend;this.unsuspend=null,n()}}}var Cf=null;function Tf(n,r){n.stylesheets=null,n.unsuspend!==null&&(n.count++,Cf=new Map,r.forEach(pM,n),Cf=null,Rf.call(n))}function pM(n,r){if(!(r.state.loading&4)){var s=Cf.get(n);if(s)var l=s.get(null);else{s=new Map,Cf.set(n,s);for(var h=n.querySelectorAll("link[data-precedence],style[data-precedence]"),p=0;p"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),Pp.exports=LM(),Pp.exports}var sx=kM();const I0=b.createContext({});function gu(e){const t=b.useRef(null);return t.current===null&&(t.current=e()),t.current}const zM=typeof window<"u",Fc=zM?b.useLayoutEffect:b.useEffect,nh=b.createContext(null);function H0(e,t){e.indexOf(t)===-1&&e.push(t)}function Rd(e,t){const i=e.indexOf(t);i>-1&&e.splice(i,1)}const ja=(e,t,i)=>i>t?t:i/^-?(?:\d+(?:\.\d+)?|\.\d+)$/u.test(e),JE=e=>typeof e=="object"&&e!==null,Y0=e=>/^0[^.\s]+$/u.test(e);function PM(e){let t;return()=>(t===void 0&&(t=e()),t)}const Li=e=>e,al=(...e)=>e.reduce((t,i)=>a=>i(t(a))),Qs=(e,t,i)=>{const a=t-e;return a?(i-e)/a:1};class Cd{constructor(){this.subscriptions=[]}add(t){return H0(this.subscriptions,t),()=>this.remove(t)}remove(t){Rd(this.subscriptions,t)}notify(t,i,a){const o=this.subscriptions.length;if(o)if(o===1)this.subscriptions[0](t,i,a);else for(let c=0;ce*1e3,$r=e=>e/1e3,eR=(e,t)=>t?e*(1e3/t):0,Bp=(e,t,i)=>e*(3*(1-e)*((1-e)*t+e*i)+e*e);function yu(e,t,i,a){return e===t&&i===a?Li:o=>{let c=0,u=1,f=o;for(let d=0;;d++){f>=c&&f<=u||(f=(c+u)/2);const m=Bp(f,e,i)-o;if(m*m<1e-28||d===40)break;m>0?u=f:c=f,f-=m*1e-7/(Bp(f+1e-7,e,i)-o-m)}return Bp(f,t,a)}}const tR=e=>t=>t<=.5?e(2*t)/2:(2-e(2*(1-t)))/2,nR=e=>t=>1-e(1-t),rR=yu(.33,1.53,.69,.99),q0=nR(rR),iR=tR(q0),aR=e=>e>=1?1:(e*=2)<1?.5*q0(e):.5*(2-Math.pow(2,-10*(e-1))),G0=e=>1-Math.sin(Math.acos(e)),sR=nR(G0),oR=tR(G0),_M=yu(.42,0,1,1),VM=yu(0,0,.58,1),K0=yu(.42,0,.58,1),lR=e=>Array.isArray(e)&&typeof e[0]!="number",X0=e=>Array.isArray(e)&&typeof e[0]=="number",UM={linear:Li,easeIn:_M,easeInOut:K0,easeOut:VM,circIn:G0,circInOut:oR,circOut:sR,backIn:q0,backInOut:iR,backOut:rR,anticipate:aR},BM=e=>typeof e=="string",Bg=e=>{if(X0(e)){const[t,i,a,o]=e;return yu(t,i,a,o)}else if(BM(e))return UM[e];return e},Mn={delta:0,timestamp:0,isProcessing:!1};let id;function IM(){id=void 0}const Ut={now:()=>(id===void 0&&Ut.set(Mn.isProcessing||_i.useManualTiming?Mn.timestamp:performance.now()),id),set:e=>{id=e,queueMicrotask(IM)}},Zo=e=>Math.round(e*1e5)/1e5,cR=e=>t=>typeof t=="string"&&t.startsWith(e),uR=cR("--"),HM=cR("var(--"),rh=e=>HM(e)?FM.test(e.split("/*")[0].trim()):!1,FM=/var\(--(?:[\w-]+\s*|[\w-]+\s*,(?:\s*[^)(\s]|\s*\((?:[^)(]|\([^)(]*\))*\))+\s*)\)$/iu;function Ip(e){return typeof e!="string"?!1:e.split("/*")[0].includes("var(--")}const wl={test:e=>typeof e=="number",parse:parseFloat,transform:e=>e},Yc={...wl,transform:e=>ja(0,1,e)},kf={...wl,default:1},$0=/-?(?:\d+(?:\.\d+)?|\.\d+)/gu;function YM(e){return e==null}const qM=/^(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\))$/iu,W0=(e,t)=>i=>!!(typeof i=="string"&&qM.test(i)&&i.startsWith(e)||t&&!YM(i)&&Object.prototype.hasOwnProperty.call(i,t)),fR=(e,t,i)=>a=>{if(typeof a!="string")return a;const[o,c,u,f]=a.match($0);return{[e]:parseFloat(o),[t]:parseFloat(c),[i]:parseFloat(u),alpha:f!==void 0?parseFloat(f):1}},GM=e=>ja(0,255,e),Hp={...wl,transform:e=>Math.round(GM(e))},Gs={test:W0("rgb","red"),parse:fR("red","green","blue"),transform:({red:e,green:t,blue:i,alpha:a=1})=>"rgba("+Hp.transform(e)+", "+Hp.transform(t)+", "+Hp.transform(i)+", "+Zo(Yc.transform(a))+")"},zf=(e,t,i)=>{const a=e.substring(1+t*i,1+(t+1)*i);return i>1?a:a+a};function KM(e){const t=e.length>5?2:1,i=zf(e,3,t);return{red:parseInt(zf(e,0,t),16),green:parseInt(zf(e,1,t),16),blue:parseInt(zf(e,2,t),16),alpha:i?parseInt(i,16)/255:1}}const Ig={test:W0("#"),parse:KM,transform:Gs.transform},vu=e=>({test:t=>typeof t=="string"&&t.endsWith(e)&&t.split(" ").length===1,parse:parseFloat,transform:t=>`${t}${e}`}),wa=vu("deg"),Zi=vu("%"),Ve=vu("px"),XM=vu("vh"),$M=vu("vw"),ox={...Zi,parse:e=>Zi.parse(e)/100,transform:e=>Zi.transform(e*100)},Yo={test:W0("hsl","hue"),parse:fR("hue","saturation","lightness"),transform:({hue:e,saturation:t,lightness:i,alpha:a=1})=>"hsla("+Math.round(e)+", "+Zi.transform(Zo(t))+", "+Zi.transform(Zo(i))+", "+Zo(Yc.transform(a))+")"},Fn={test:e=>Gs.test(e)||Ig.test(e)||Yo.test(e),parse:e=>Gs.test(e)?Gs.parse(e):Yo.test(e)?Yo.parse(e):Ig.parse(e),transform:e=>typeof e=="string"?e:e.hasOwnProperty("red")?Gs.transform(e):Yo.transform(e),getAnimatableNone:e=>{const t=Fn.parse(e);return t.alpha=0,Fn.transform(t)}},WM=/(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\))/giu,dR=new RegExp($0.source),hR=new RegExp(WM.source,"i");function ZM(e){return isNaN(e)&&typeof e=="string"&&(dR.test(e)||hR.test(e))}const mR="number",pR="color",QM="var",JM="var(",lx="${}",e4=/var\s*\(\s*--(?:[\w-]+\s*|[\w-]+\s*,(?:\s*[^)(\s]|\s*\((?:[^)(]|\([^)(]*\))*\))+\s*)\)|#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\)|-?(?:\d+(?:\.\d+)?|\.\d+)(?![a-z]*\()/giu;function t4(e){const t=e.toString();return dR.test(t)||hR.test(t)}function qc(e){const t=e.toString(),i=[],a={color:[],number:[],var:[]},o=[];let c=0;const f=t.replace(e4,d=>(Fn.test(d)?(a.color.push(c),o.push(pR),i.push(Fn.parse(d))):d.startsWith(JM)?(a.var.push(c),o.push(QM),i.push(d)):(a.number.push(c),o.push(mR),i.push(parseFloat(d))),++c,lx)).split(lx);return{values:i,split:f,indexes:a,types:o}}function n4(e){return qc(e).values}function Z0({split:e,types:t}){const i=e.length;return a=>{let o="";for(let c=0;ctypeof e=="number"?0:Fn.test(e)?Fn.getAnimatableNone(e):e,a4=(e,t)=>typeof e=="number"?t?.trim().endsWith("/")?e:0:i4(e);function s4(e){const t=qc(e);return Z0(t)(t.values.map((a,o)=>a4(a,t.split[o])))}const mi={test:ZM,parse:n4,createTransformer:r4,getAnimatableNone:s4};function Fp(e,t,i){return i<0&&(i+=1),i>1&&(i-=1),i<1/6?e+(t-e)*6*i:i<1/2?t:i<2/3?e+(t-e)*(2/3-i)*6:e}function o4({hue:e,saturation:t,lightness:i,alpha:a}){e/=360,t/=100,i/=100;let o=0,c=0,u=0;if(!t)o=c=u=i;else{const f=i<.5?i*(1+t):i+t-i*t,d=2*i-f;o=Fp(d,f,e+1/3),c=Fp(d,f,e),u=Fp(d,f,e-1/3)}return{red:Math.round(o*255),green:Math.round(c*255),blue:Math.round(u*255),alpha:a}}function Td(e,t){return i=>i>0?t:e}const rn=(e,t,i)=>e+(t-e)*i,Yp=(e,t,i)=>{const a=e*e,o=i*(t*t-a)+a;return o<0?0:Math.sqrt(o)},l4=[Ig,Gs,Yo],c4=e=>l4.find(t=>t.test(e));function cx(e){const t=c4(e);if(!t)return!1;let i=t.parse(e);return t===Yo&&(i=o4(i)),i}const ux=(e,t)=>{const i=cx(e),a=cx(t);if(!i||!a)return Td(e,t);const o={...i};return c=>(o.red=Yp(i.red,a.red,c),o.green=Yp(i.green,a.green,c),o.blue=Yp(i.blue,a.blue,c),o.alpha=rn(i.alpha,a.alpha,c),Gs.transform(o))},Hg=new Set(["none","hidden"]);function u4(e,t){return Hg.has(e)?i=>i<=0?e:t:i=>i>=1?t:e}function f4(e,t){return i=>rn(e,t,i)}function Q0(e){return typeof e=="number"?f4:typeof e=="string"?rh(e)?Td:Fn.test(e)?ux:m4:Array.isArray(e)?gR:typeof e=="object"?Fn.test(e)?ux:d4:Td}function gR(e,t){const i=[...e],a=i.length,o=e.map((c,u)=>Q0(c)(c,t[u]));return c=>{for(let u=0;u{for(const c in a)i[c]=a[c](o);return i}}function h4(e,t){const i=[],a={color:0,var:0,number:0};for(let o=0;o{const i=qc(e),a=qc(t);return i.indexes.var.length===a.indexes.var.length&&i.indexes.color.length===a.indexes.color.length&&i.indexes.number.length>=a.indexes.number.length?Hg.has(e)&&!a.values.length||Hg.has(t)&&!i.values.length?u4(e,t):al(gR(h4(i,a),a.values),Z0(a)):Td(e,t)},fx=/^(-?(?:\d+(?:\.\d*)?|\.\d+))([a-z%]*)$/iu;function p4(e,t){const i=fx.exec(e);if(!i)return;const a=fx.exec(t);if(!a||i[2]!==a[2])return;const o=i[2],c=parseFloat(i[1]),u=parseFloat(a[1]);return f=>Zo(rn(c,u,f))+o}function J0(e,t,i){if(typeof e=="number"&&typeof t=="number"&&typeof i=="number")return rn(e,t,i);if(typeof e=="string"&&typeof t=="string"){const o=p4(e,t);if(o)return o}return Q0(e)(e,t)}const Pf=["setup","read","resolveKeyframes","preUpdate","update","preRender","render","postRender"];function g4(e){let t=new Set,i=new Set,a=!1,o=!1,c;const u=new Set;let f={delta:0,timestamp:0,isProcessing:!1};function d(g){u.has(g)&&(i.add(g),e()),(c=g)(f)}const m={schedule:(g,v=!1,S=!1)=>{const x=S&&a,E=x?t:i;return v&&u.add(g),x&&g!==c&&E.delete(g),E.add(g),g},cancel:g=>{i.delete(g),u.delete(g)},process:g=>{if(f=g,a){o=!0;return}a=!0;const v=t;t=i,i=v,t.forEach(d),t.clear(),c=void 0,a=!1,o&&(o=!1,m.process(g))}};return m}const y4=40;function yR(e,t,i={delta:0,timestamp:0,isProcessing:!1}){let a=!1,o=!0;const c=()=>a=!0,u=Pf.reduce((N,j)=>(N[j]=g4(c),N),{}),{setup:f,read:d,resolveKeyframes:m,preUpdate:g,update:v,preRender:S,render:x,postRender:E}=u,w=()=>{const N=_i.useManualTiming,j=N?i.timestamp:performance.now();a=!1,N||(i.delta=o?1e3/60:Math.max(Math.min(j-i.timestamp,y4),1)),i.timestamp=j,i.isProcessing=!0,f.process(i),d.process(i),m.process(i),g.process(i),v.process(i),S.process(i),x.process(i),E.process(i),i.isProcessing=!1,a&&t&&(o=!1,e(w))},R=()=>{a=!0,o=!0,i.isProcessing||e(w)};return{schedule:Pf.reduce((N,j)=>{const L=u[j];return N[j]=(P,D=!1,A=!1)=>(a||R(),L.schedule(P,D,A)),N},{}),cancel:N=>{for(let j=0;j{const t=({timestamp:i})=>e(i);return{start:(i=!0)=>Xt.update(t,i),stop:()=>Xr(t),now:()=>Mn.isProcessing?Mn.timestamp:Ut.now()}},vR=(e,t,i=10)=>{let a="";const o=Math.max(Math.round(t/i),2);for(let c=0;c=i?1/0:o}function v4(e,t=100,i){const{keyframes:a,velocity:o}=e,c=a&&a[a.length-1]-a[0],u=i({...e,velocity:o&&c?o*t/c:o,keyframes:[0,t]}),f=Math.min(ny(u),ty);return{type:"keyframes",ease:d=>u.next(f*d).value/t,duration:$r(f)}}const dx=100,hx=10,b4=1,x4=800,bR=.3,S4=.3,w4=.01,E4=2,R4=.005,C4=.5,T4=.01,A4=10,mx=.05,xR=e=>e<0?1/Math.max(1+e,mx):Math.max(1-e,mx);function SR(e,t){if(!(e>1))return 1;const i=Math.sqrt(e*e-1),a=e-i,o=e+i,c=2*i*Math.exp(-t)*(1+t);return wR(u=>o*Math.exp(-a*u)-a*Math.exp(-o*u)-c,u=>Math.exp(-o*u)-Math.exp(-a*u),t)/t}function Fg(e,t){return e*Math.sqrt(1-t*t)}const M4=12;function wR(e,t,i){let a=i;for(let o=1;o{const g=m*o,v=g*e,S=Fg(m,o),x=Math.exp(-v);return Gp-g/S*x},a=m=>{const v=m*o*e,S=o*o*m*m*e,x=Math.exp(-v),E=Fg(m*m,o);return(-i(m)+Gp>0?-1:1)*-S*x/E}):(i=m=>{const g=Math.exp(-m*e),v=m*e+1;return-Gp+g*v},a=m=>{const g=Math.exp(-m*e),v=-m*(e*e);return g*v});const c=5/e,u=wR(i,a,c),f=u*SR(o,u*e),d=f*f;return{stiffness:d,damping:o*2*Math.sqrt(d),duration:Sr(e)}}const Yg=(e,t)=>(t?e>=0:e>0)&&e<1/0;function Kp(e,t){if(Yg(e,t))return e}function O4(e){const t=Kp(e.stiffness),i=Kp(e.damping,!0),a=Kp(e.mass),o={...e,stiffness:t??dx,damping:i??hx,mass:a??b4,isResolvedFromDuration:!1,isTimeDefined:(t??i??a)===void 0&&(e.duration!==void 0||e.bounce!==void 0)};if(o.isTimeDefined){if(e.visualDuration){const c=xR(e.bounce||0),u=2*Math.PI/(e.visualDuration*1.2)*SR(c,2*Math.PI/1.2);o.stiffness=u*u,o.damping=2*c*Math.sqrt(o.stiffness)}else Object.assign(o,j4(o)),o.isResolvedFromDuration=!0;(!Yg(o.stiffness)||!Yg(o.damping,!0))&&(o.stiffness=dx,o.damping=hx)}return o}function px(e=S4,t=bR){const i=typeof e!="object"?{visualDuration:e,keyframes:[0,1],bounce:t}:e,a=i.keyframes[0],o=i.keyframes[i.keyframes.length-1],c={done:!1,value:a},{stiffness:u,damping:f,mass:d,duration:m,isResolvedFromDuration:g,isTimeDefined:v}=O4({...i}),S=D=>v?0:-$r(D),x=f/(2*Math.sqrt(u*d)),E=$r(Math.sqrt(u/d)),w=x*E,R={target:o,delta:o-a,velocity:S(i.velocity||0)||0,restSpeed:0,restDelta:0},T=()=>{const D=Math.abs(R.delta)<5;R.restSpeed=i.restSpeed||(D?w4:E4),R.restDelta=i.restDelta||(D?R4:C4)};T();let O,N,j;if(x<1){const D=Fg(E,x),A={A:0,sinC:0,cosC:0,t:-1,env:0,sin:0,cos:0};j=()=>{A.A=(R.velocity+w*R.delta)/D,A.sinC=w*A.A+R.delta*D,A.cosC=w*R.delta-A.A*D};const F=H=>{H!==A.t&&(A.t=H,A.env=Math.exp(-w*H),A.sin=Math.sin(D*H),A.cos=Math.cos(D*H))};O=H=>(F(H),R.target-A.env*(A.A*A.sin+R.delta*A.cos)),N=H=>(F(H),A.env*(A.sinC*A.sin+A.cosC*A.cos))}else if(x===1){O=A=>R.target-Math.exp(-E*A)*(R.delta+(R.velocity+E*R.delta)*A);const D={C:0};j=()=>{D.C=R.velocity+E*R.delta},N=A=>Math.exp(-E*A)*(E*D.C*A-R.velocity)}else{const D=E*Math.sqrt(x*x-1),A=w-D,F=w+D,H=D<1||v?1/0:300/D,X=($,ee)=>Math.exp(ee>H?(w-$)*H-w*ee:-$*ee),J={S:0,F:0};j=()=>{const $=(R.velocity+w*R.delta)/D;J.S=(R.delta+$)/2,J.F=(R.delta-$)/2},O=$=>R.target-J.S*X(A,$)-J.F*X(F,$),N=$=>A*J.S*X(A,$)+F*J.F*X(F,$)}j();const L=g&&m||null,P={calculatedDuration:L,retarget:(D,A)=>{R.target=D[D.length-1],R.delta=R.target-D[0],R.velocity=S(A),i.restSpeed&&i.restDelta||T(),P.calculatedDuration=L,c.done=!1,j()},velocity:D=>Sr(N(D)),next:D=>{const A=O(D);if(g)c.done=D>=m;else{const F=Sr(N(D));c.done=Math.abs(F)<=R.restSpeed&&Math.abs(R.target-A)<=R.restDelta}return c.value=c.done?R.target:A,c},toString:()=>{const D=Math.min(ny(P),ty),A=vR(F=>P.next(D*F).value,D,30);return D+"ms "+A},toTransition:()=>{}};return P}const ER=Object.assign(px,{applyToOptions:e=>{const t=v4(e,100,px);return e.ease=t.ease,e.duration=Sr(t.duration),e.type="keyframes",e}});function Ad({keyframes:e,velocity:t=0,power:i=.8,timeConstant:a=325,bounceDamping:o=10,bounceStiffness:c=500,modifyTarget:u,min:f,max:d,restDelta:m=.5,restSpeed:g}){const v=e[0],S={done:!1,value:v},x=D=>Dd,E=D=>f===void 0?d:d===void 0||Math.abs(f-D)-w*Math.exp(-D/a),N=D=>{const A=O(D);S.done=Math.abs(A)<=m,S.value=S.done?T:D?T+A:v};let j,L;const P=D=>{x(S.value)&&(j=D,L=ER({keyframes:[S.value,E(S.value)],velocity:-O(D)/a*1e3,damping:o,stiffness:c,restDelta:m,restSpeed:g}))};return P(0),{calculatedDuration:null,next:D=>{let A=!1;return!L&&j===void 0&&(A=!0,N(D),P(D)),j!==void 0&&D>=j?L.next(D-j):(!A&&N(D),S)}}}function D4(e,t,i){const a=[],o=_i.mix||J0,c=e.length-1;for(let u=0;ut[0];if(c===2&&t[0]===t[1])return()=>t[1];const u=e[0]===e[1];e[0]>e[c-1]&&(e=[...e].reverse(),t=[...t].reverse());const f=D4(t,a,o),d=f.length,m=g=>{if(u&&g1)for(;vm(ja(e[0],e[c-1],g)):m}function L4(e,t){const i=e[e.length-1];for(let a=1;a<=t;a++){const o=Qs(0,t,a);e.push(rn(i,1,o))}}function Gc(e){const t=[0];return L4(t,e.length-1),t}function k4(e,t){return e.map(i=>i*t)}function z4(e,t){return e.map(()=>t||K0).splice(0,e.length-1)}function us({duration:e=300,keyframes:t,times:i,ease:a="easeInOut",mixer:o}){const c=typeof t[0]=="number"?void 0:o,u=lR(a)?a.map(Bg):Bg(a)||K0,f={done:!1,value:t[0]};let d=-1;if(!c){for(let v=1;v=0){d=-2;break}d=v-1}}if(d>=0){const v=i&&i.length===t.length?i:Gc(t),S=v[d]*e,x=v[d+1]*e,E=t[d],w=t[d+1],R=Array.isArray(u)?u[d]:u,T=(_i.mix||J0)(E,w),O=t.length-2;return{calculatedDuration:e,next:N=>(f.value=d&&N=x||!e)?typeof w=="number"?w:T(1):T(R(N>=x||!e?1:N<=S?0:(N-S)/(x-S))),f.done=N>=e,f)}}const m=k4(i&&i.length===t.length?i:Gc(t),e),g=N4(m,t,{ease:Array.isArray(u)?u:z4(t,u),mixer:c});return{calculatedDuration:e,next:v=>(f.value=g(v),f.done=v>=e,f)}}const P4=5;function _4(e,t,i){const a=Math.max(t-P4,0);return eR(i-e(a),t-a)}function V4(e,t,i=0){return t<=0?i:e.velocity?e.velocity(t):_4(a=>e.next(a).value,t,e.next(t).value)}function Kc(e,{repeat:t,repeatType:i="loop"},a,o=1){let c,u,f=0;for(let g=0;gt-e>B4&&!_i.useManualTiming?t:e;function TR(e,t){return{kind:e,animation:t,timestamp:Ut.now(),frameTimestamp:Mn.timestamp,frameIsProcessing:Mn.isProcessing}}function AR(e,t,i){const a=globalThis.__MOTION_INSPECT__;if(a)try{a({...TR("animation-start",e),options:i?{...t,...i}:t})}catch{}}function I4(e,t){const i=globalThis.__MOTION_INSPECT__;if(i)try{i({...TR("layout-animation-start",e),node:t})}catch{}}class ry{constructor(){this.isResolved=!1}get finished(){return this._finished||(this._finished=this.isResolved?Promise.resolve():new Promise(t=>{this._resolve=t})),this._finished}updateFinished(){this._finished=this._resolve=void 0,this.isResolved=!1}notifyFinished(){this.isResolved=!0,this._resolve?.()}then(t,i){return this.finished.then(t,i)}}const H4=e=>e/100,Xc=e=>Math.round(e*1e4)/1e4;class sl extends ry{constructor(t){super(),this.state="idle",this.startTime=null,this.isStopped=!1,this.currentTime=0,this.holdTime=null,this.playbackSpeed=1,this.delayState={done:!1,value:void 0},this.stop=()=>{const{motionValue:i}=this.options;i&&i.updatedAt!==Ut.now()&&this.tick(Ut.now()),this.isStopped=!0,this.state!=="idle"&&(this.teardown(),this.options.onStop?.())},this.options=t,this.initAnimation(),this.play(),t.autoplay===!1&&this.pause(),AR(this,this.options)}initAnimation(){const{options:t}=this;RR(t);const{type:i=us,repeat:a=0,repeatDelay:o=0,repeatType:c,velocity:u=0}=t;let{keyframes:f}=t;const d=i||us;this.mixKeyframes=void 0,d!==us&&typeof f[0]!="number"&&(this.mixKeyframes=al(H4,t.mixer?.(f[0],f[1])||J0(f[0],f[1])),f=[0,100]);const m=d(f===t.keyframes?t:{...t,keyframes:f});c==="mirror"&&(this.mirroredGenerator=d({...t,keyframes:[...f].reverse(),velocity:-u})),m.calculatedDuration===null&&(m.calculatedDuration=ny(m));const{calculatedDuration:g}=m;this.calculatedDuration=g,this.resolvedDuration=g+o,this.totalDuration=this.resolvedDuration*(a+1)-o,this.generator=m}updateTime(t){this.currentTime=this.holdTime??Math.round(t-this.startTime)*this.playbackSpeed}tick(t,i=!1){const{generator:a,totalDuration:o,calculatedDuration:c}=this;if(this.startTime===null)return a.next(0);const{delay:u=0,keyframes:f,type:d,onUpdate:m,finalKeyframe:g}=this.options;this.startTime===this.pendingStartTime&&(this.startTime=CR(this.startTime,t)),this.pendingStartTime=void 0,this.speed>0?this.startTime=Math.min(this.startTime,t):this.speed<0&&(this.startTime=Math.min(t-o/this.speed,this.startTime)),i?this.currentTime=t:this.updateTime(t);const v=this.currentTime-u*(this.playbackSpeed>=0?1:-1),S=this.playbackSpeed>=0?v<0:v>o;this.currentTime=Math.max(v,0),this.state==="finished"&&this.holdTime===null&&(this.currentTime=o);const x=this.generate(this.currentTime,S);let{done:E}=x;S||(E=this.playbackSpeed>=0?c<1/0?this.currentTime>=o:E:this.currentTime<=0);const w=this.holdTime===null&&(this.state==="finished"||this.state==="running"&&E);return w&&d!==Ad&&(x.value=Kc(f,this.options,g,this.speed)),m&&m(x.value),w&&this.finish(),x}at(t){return this.holdTime??Xc((t-this.startTime)*this.playbackSpeed)}sampleAt(t,i){const{options:a,totalDuration:o}=this,c=this.at(t)-(a.delay||0);return c>=o&&a.type!==Ad?Kc(a.keyframes,a,i?void 0:a.finalKeyframe):this.generate(Math.max(c,0),c<0).value}generate(t,i){const{generator:a,totalDuration:o,mixKeyframes:c,mirroredGenerator:u,resolvedDuration:f}=this,{keyframes:d,repeat:m,repeatType:g,repeatDelay:v}=this.options;let S=t,x=a;if(m){const w=Math.min(t,o)/f;let R=Math.floor(w),T=w%1;!T&&w>=1&&(T=1),T===1&&R--,R=Math.min(R,m+1),R%2&&(g==="reverse"?(T=1-T,v&&(T-=v/f)):g==="mirror"&&(x=u)),S=ja(0,1,T)*f}let E;return i?(this.delayState.value=d[0],E=this.delayState):E=x.next(S),c&&!i&&(E.value=c(E.value)),E}get duration(){return $r(this.calculatedDuration)}get iterationDuration(){return this.duration+$r(this.options.delay??0)}get time(){return $r(this.currentTime)}set time(t){this.state==="finished"&&this.updateFinished(),t=Sr(t),this.currentTime=t,this.startTime===null||this.holdTime!==null||this.playbackSpeed===0?this.holdTime=t:this.driver&&(this.startTime=this.driver.now()-t/this.playbackSpeed),this.driver?this.driver.start(!1):(this.startTime=0,this.state="paused",this.holdTime=t,this.tick(t))}getGeneratorVelocity(){return V4(this.generator,this.currentTime,this.options.velocity)}get speed(){return this.playbackSpeed}set speed(t){const i=this.playbackSpeed!==t;i&&this.driver&&this.updateTime(Ut.now()),this.playbackSpeed=t,i&&this.driver&&(this.time=$r(this.currentTime))}play(){if(this.isStopped)return;const{driver:t=ey,startTime:i}=this.options;this.driver||(this.driver=t(o=>this.tick(o))),this.options.onPlay?.();const a=this.driver.now();this.state==="finished"?(this.updateFinished(),this.startTime=a):this.holdTime!==null?this.startTime=a-this.holdTime/(this.playbackSpeed||1):this.startTime||(this.startTime=i??(this.pendingStartTime=a)),this.state==="finished"&&this.speed<0&&(this.startTime+=this.calculatedDuration),this.holdTime=null,this.state="running",this.driver.start()}pause(){this.state="paused",this.updateTime(Ut.now()),this.holdTime=this.currentTime}complete(){this.state!=="running"&&this.play(),this.state="finished",this.holdTime=null}finish(){this.notifyFinished(),this.teardown(),this.state="finished",this.options.onComplete?.()}cancel(){this.holdTime=null,this.startTime=0,this.tick(0),this.teardown(),this.options.onCancel?.()}teardown(){this.state="idle",this.driver?.stop(),this.driver=void 0,this.startTime=this.holdTime=null}sample(t){return this.startTime=0,this.tick(t,!0)}attachTimeline(t){return this.options.allowFlatten&&(this.options.type="keyframes",this.options.ease="linear",this.initAnimation()),this.driver?.stop(),t.observe(this)}}const F4=new Set(["brightness","contrast","saturate","opacity"]);function Y4(e){const[t,i]=e.slice(0,-1).split("(");if(t==="drop-shadow")return e;const[a]=i.match($0)||[];if(!a)return e;const o=i.replace(a,"");let c=F4.has(t)?1:0;return a!==i&&(c*=100),t+"("+c+o+")"}const q4=/\b([a-z-]*)\(.*?\)/gu,qg={...mi,getAnimatableNone:e=>{const t=e.match(q4);return t?t.map(Y4).join(" "):e}},Gg={...mi,getAnimatableNone:e=>{const t=mi.parse(e);return mi.createTransformer(e)(t.map(a=>typeof a=="number"?0:typeof a=="object"?{...a,alpha:1}:a))}},gx={...wl,transform:Math.round},MR={rotate:wa,pathRotation:wa,rotateX:wa,rotateY:wa,rotateZ:wa,scale:kf,scaleX:kf,scaleY:kf,scaleZ:kf,skew:wa,skewX:wa,skewY:wa,distance:Ve,translateX:Ve,translateY:Ve,translateZ:Ve,x:Ve,y:Ve,z:Ve,perspective:Ve,transformPerspective:Ve,opacity:Yc,originX:ox,originY:ox,originZ:Ve},iy={borderWidth:Ve,borderTopWidth:Ve,borderRightWidth:Ve,borderBottomWidth:Ve,borderLeftWidth:Ve,borderRadius:Ve,borderTopLeftRadius:Ve,borderTopRightRadius:Ve,borderBottomRightRadius:Ve,borderBottomLeftRadius:Ve,width:Ve,maxWidth:Ve,height:Ve,maxHeight:Ve,top:Ve,right:Ve,bottom:Ve,left:Ve,inset:Ve,insetBlock:Ve,insetBlockStart:Ve,insetBlockEnd:Ve,insetInline:Ve,insetInlineStart:Ve,insetInlineEnd:Ve,padding:Ve,paddingTop:Ve,paddingRight:Ve,paddingBottom:Ve,paddingLeft:Ve,paddingBlock:Ve,paddingBlockStart:Ve,paddingBlockEnd:Ve,paddingInline:Ve,paddingInlineStart:Ve,paddingInlineEnd:Ve,margin:Ve,marginTop:Ve,marginRight:Ve,marginBottom:Ve,marginLeft:Ve,marginBlock:Ve,marginBlockStart:Ve,marginBlockEnd:Ve,marginInline:Ve,marginInlineStart:Ve,marginInlineEnd:Ve,fontSize:Ve,backgroundPositionX:Ve,backgroundPositionY:Ve,...MR,zIndex:gx,fillOpacity:Yc,strokeOpacity:Yc,numOctaves:gx},G4={...iy,color:Fn,backgroundColor:Fn,outlineColor:Fn,fill:Fn,stroke:Fn,borderColor:Fn,borderTopColor:Fn,borderRightColor:Fn,borderBottomColor:Fn,borderLeftColor:Fn,filter:qg,WebkitFilter:qg,mask:Gg,WebkitMask:Gg},jR=e=>G4[e],K4=new Set([qg,Gg]);let yx,vx,Xp;function ay(e,t){if(e===yx&&t===vx)return Xp;let i=jR(e);return K4.has(i)||(i=mi),Xp=i.getAnimatableNone?i.getAnimatableNone(t):void 0,yx=e,vx=t,Xp}function X4(e){for(let t=1;te*180/Math.PI,Kg=e=>{const t=Ks(Math.atan2(e[1],e[0]));return Xg(t)},$4={x:4,y:5,translateX:4,translateY:5,scaleX:0,scaleY:3,scaleZ:()=>1,scale:e=>(Math.abs(e[0])+Math.abs(e[3]))/2,rotate:Kg,rotateZ:Kg,skewX:e=>Ks(Math.atan(e[1])),skewY:e=>Ks(Math.atan(e[2])),skew:e=>(Math.abs(e[1])+Math.abs(e[2]))/2},Xg=e=>(e=e%360,e<0&&(e+=360),e),bx=Kg,xx=e=>Math.hypot(e[0],e[1]),Sx=e=>Math.hypot(e[4],e[5]),W4={x:12,y:13,z:14,translateX:12,translateY:13,translateZ:14,scaleX:xx,scaleY:Sx,scaleZ:e=>Math.hypot(e[8],e[9],e[10]),scale:e=>(xx(e)+Sx(e))/2,rotateX:e=>Xg(Ks(Math.atan2(e[6],e[5]))),rotateY:e=>Xg(Ks(Math.atan2(-e[2],e[0]))),rotateZ:bx,rotate:bx,skewX:e=>Ks(Math.atan(e[4])),skewY:e=>Ks(Math.atan(e[1])),skew:e=>(Math.abs(e[1])+Math.abs(e[4]))/2};function $c(e){return e.includes("scale")?1:0}function sy(e,t){if(!e||e==="none")return $c(t);const i=e.match(/^matrix(3d)?\(([-\d.e\s,]+)\)$/u);if(!i)return $c(t);const a=(i[1]?W4:$4)[t],o=i[2].split(",").map(c=>parseFloat(c));return typeof a=="function"?a(o):o[a]}const Z4=(e,t)=>{const{transform:i="none"}=getComputedStyle(e);return sy(i,t)},Ta=["transformPerspective","x","y","z","translateX","translateY","translateZ","scale","scaleX","scaleY","scaleZ","rotate","rotateX","rotateY","rotateZ","skew","skewX","skewY"],fs=new Set([...Ta,"pathRotation"]),wx=e=>e===wl||e===Ve,Q4=new Set(["x","y","z"]),J4=Ta.filter(e=>!Q4.has(e));function e6(e){const t=[];return J4.forEach(i=>{const a=e.getValue(i);if(a!==void 0){const o=a.get(),c=i.startsWith("scale")?1:0;if(o===c)return;t.push([i,o]),a.set(c)}}),t}const t6=new Set(["bottom","right"]);function Ex(e,t,i,a,o,c){const u=parseFloat(e);if(!isNaN(u))return u;const{min:f,max:d}=t()[i],m=d-f;return c==="border-box"?m:m-parseFloat(a)-parseFloat(o)}const Rx=({transform:e})=>sy(e,"x"),Cx=({transform:e})=>sy(e,"y"),$p={width:({width:e,paddingLeft:t="0",paddingRight:i="0",boxSizing:a},o)=>Ex(e,o,"x",t,i,a),height:({height:e,paddingTop:t="0",paddingBottom:i="0",boxSizing:a},o)=>Ex(e,o,"y",t,i,a),top:({top:e})=>parseFloat(e),left:({left:e})=>parseFloat(e),bottom:({top:e},t)=>{const{y:i}=t();return parseFloat(e)+(i.max-i.min)},right:({left:e},t)=>{const{x:i}=t();return parseFloat(e)+(i.max-i.min)},x:Rx,y:Cx,translateX:Rx,translateY:Cx},$s=new Set;let $g=!1,Wg=!1,Zg=!1;function OR(){if(Wg){const e=[],t=new Set,i=new Set;$s.forEach(o=>{o.needsMeasurement&&(e.push(o),t.add(o.element),t6.has(o.name)&&i.add(o.element))});const a=new Map;i.forEach(o=>{const c=e6(o);c.length&&(a.set(o,c),o.render())}),e.forEach(o=>o.measureInitialState()),t.forEach(o=>{o.render();const c=a.get(o);c&&c.forEach(([u,f])=>{o.getValue(u)?.set(f)})}),e.forEach(o=>o.measureEndState()),e.forEach(o=>{o.suspendedScrollY!==void 0&&window.scrollTo(0,o.suspendedScrollY)})}Wg=!1,$g=!1,$s.forEach(e=>e.complete(Zg)),$s.clear()}function DR(){$s.forEach(e=>{e.readKeyframes(),e.needsMeasurement&&(Wg=!0)})}function n6(){Zg=!0,DR(),OR(),Zg=!1}function r6(e,t,i){if(typeof e=="string"){if(F0(e)||Y0(e))return parseFloat(e);if(!mi.test(e)&&mi.test(i))return ay(t,i)}return e??void 0}class oy{constructor(t,i,a,o,c,u=!1){this.state="pending",this.isAsync=!1,this.needsMeasurement=!1,this.unresolvedKeyframes=[...t],this.onComplete=i,this.name=a,this.motionValue=o,this.element=c,this.isAsync=u}scheduleResolve(){this.state="scheduled",this.isAsync?($s.add(this),$g||($g=!0,Xt.read(DR),Xt.resolveKeyframes(OR))):(this.readKeyframes(),this.complete())}readKeyframes(){const{unresolvedKeyframes:t,name:i,element:a,motionValue:o}=this;if(t[0]===null){const c=o?.get(),u=t[t.length-1];if(c!==void 0)t[0]=c;else if(a&&i){const f=r6(a.readValue(i,u),i,u);f!==void 0&&(t[0]=f)}t[0]===void 0&&(t[0]=u),o&&c===void 0&&o.set(t[0])}X4(t)}setFinalKeyframe(){}measureInitialState(){}renderEndStyles(){}measureEndState(){}complete(t=!1){this.state="complete",this.onComplete(this.unresolvedKeyframes,this.finalKeyframe,t),$s.delete(this)}cancel(){this.state==="scheduled"&&($s.delete(this),this.state="pending")}resume(){this.state==="pending"&&this.scheduleResolve()}}const i6=e=>e.startsWith("--");function NR(e,t,i){i6(t)?e.style.setProperty(t,i):e.style[t]=i}const a6={};function LR(e,t){const i=PM(e);return()=>a6[t]??i()}const s6=LR(()=>window.ScrollTimeline!==void 0,"scrollTimeline"),ly=LR(()=>{try{document.createElement("div").animate({opacity:0},{easing:"linear(0, 1)"})}catch{return!1}return!0},"linearEasing"),qo=([e,t,i,a])=>`cubic-bezier(${e}, ${t}, ${i}, ${a})`,Qg={linear:"linear",ease:"ease",easeIn:"ease-in",easeOut:"ease-out",easeInOut:"ease-in-out",circIn:qo([0,.65,.55,1]),circOut:qo([.55,0,1,.45]),backIn:qo([.31,.01,.66,-.59]),backOut:qo([.33,1.53,.69,.99])};function kR(e,t){if(e)return typeof e=="function"?ly()?vR(e,t):"ease-out":X0(e)?qo(e):Array.isArray(e)?e.map(i=>kR(i,t)||Qg.easeOut):Qg[e]}function o6(e,t,i,{delay:a=0,duration:o=300,repeat:c=0,repeatType:u="loop",ease:f="easeOut",times:d}={},m=void 0){const g={[t]:i};d&&(g.offset=d);const v=kR(f,o);Array.isArray(v)&&(g.easing=v);const S={delay:a,duration:o,easing:Array.isArray(v)?"linear":v,fill:"both",iterations:c+1,direction:u==="reverse"?"alternate":"normal"};return m&&(S.pseudoElement=m),e.animate(g,S)}function zR(e){return typeof e=="function"&&"applyToOptions"in e}function l6({type:e,...t}){return zR(e)&&ly()?e.applyToOptions(t):(t.duration??(t.duration=300),t.ease??(t.ease="easeOut"),t)}class PR extends ry{constructor(t){if(super(),this.finishedTime=null,this.isStopped=!1,this.manualStartTime=null,!t)return;const{element:i,name:a,keyframes:o,pseudoElement:c,allowFlatten:u=!1,finalKeyframe:f,onComplete:d}=t;this.isPseudoElement=!!c,this.allowFlatten=u,this.options=t;const m=l6(t);this.animation=o6(i,a,o,m,c),m.autoplay===!1&&this.animation.pause(),this.animation.onfinish=this.onFinish=()=>{if(this.animation.onfinish=null,this.finishedTime=this.time,!c){const g=Kc(o,this.options,f,this.speed);this.updateMotionValue?.(g),NR(i,a,g),this.animation.cancel()}d?.(),this.notifyFinished()},AR(this,t,m)}play(){this.isStopped||(this.manualStartTime=null,this.animation.onfinish=this.onFinish,this.animation.play(),this.state==="finished"&&this.updateFinished())}pause(){this.animation.pause()}complete(){this.isStopped||(this.animation.onfinish=this.onFinish),this.animation.finish?.()}cancel(){this.animation.onfinish=null;try{this.animation.cancel()}catch{}}stop(){this.isStopped||(this.isStopped=!0,!(this.state==="idle"||this.finishedTime!==null)&&(this.updateMotionValue?this.updateMotionValue():this.commitStyles(),this.isPseudoElement||this.cancel()))}commitStyles(){const t=this.options?.element;!this.isPseudoElement&&t?.isConnected&&this.animation.commitStyles?.()}get duration(){const t=this.animation.effect?.getComputedTiming?.().duration||0;return $r(Number(t))}get iterationDuration(){const{delay:t=0}=this.options||{};return this.duration+$r(t)}get time(){return $r(Number(this.animation.currentTime)||0)}set time(t){const i=this.finishedTime!==null;this.manualStartTime=null,this.finishedTime=null,this.animation.currentTime=Sr(t),i&&(this.animation.pause(),this.updateFinished())}get speed(){return this.animation.playbackRate}set speed(t){t<0&&(this.finishedTime=null),this.animation.playbackRate=t}get state(){return this.finishedTime!==null?"finished":this.animation.playState}get startTime(){return this.manualStartTime??Number(this.animation.startTime)}set startTime(t){this.manualStartTime=this.animation.startTime=t}attachTimeline({timeline:t,onAttach:i,observe:a}){return this.allowFlatten&&this.animation.effect?.updateTiming({easing:"linear"}),this.animation.onfinish=this.onFinish=null,t&&s6()?(this.animation.timeline=t,i?.(this.animation),Li):a(this)}}const _R={anticipate:aR,backInOut:iR,circInOut:oR};function c6(e){return e in _R}function u6(e){typeof e.ease=="string"&&c6(e.ease)&&(e.ease=_R[e.ease])}const Md=10;class f6 extends PR{constructor(t){u6(t),RR(t),super(t),t.startTime!==void 0&&t.autoplay!==!1&&(this.startTime=t.startTime),this.options=t}elapsed(){return this.state==="running"?(Ut.now()-this.startTime)*this.speed:this.time*1e3}sample(t){if(!this.sampler){const{motionValue:i,onUpdate:a,onComplete:o,onPlay:c,onStop:u,element:f,...d}=this.options;this.sampler=new sl({...d,autoplay:!1}),this.sampler.stop()}return this.sampler.sample(Math.max(0,t)).value}liveValue(){const{state:t}=this;if(t==="running"||t==="paused")return this.sample(this.elapsed())}updateMotionValue(t){const{motionValue:i,element:a,name:o}=this.options;if(!i)return;if(t!==void 0){i.set(t);return}const{speed:c}=this,u=this.elapsed(),f=this.state==="running"&&c?ja(0,Md,u):0,d=this.sample(u);a&&o&&NR(a,o,d),i.setWithVelocity(this.sample(u-f*Math.sign(c)),d,f/Math.abs(c||1))}}const Tx=(e,t)=>t==="zIndex"?!1:!!(typeof e=="number"||Array.isArray(e)||typeof e=="string"&&(mi.test(e)||e==="0")&&!e.startsWith("url("));function d6(e){const t=e[0];if(e.length===1)return!0;for(let i=0;ie&&typeof t[0]!="number"&&t.some((i,a)=>a&&e(t[a-1],i)),Ax=new Set(["color","backgroundColor","outlineColor","fill","stroke","borderColor","borderTopColor","borderRightColor","borderBottomColor","borderLeftColor"]),UR=()=>!_i.useManualTiming&&Object.hasOwnProperty.call(Element.prototype,"animate");function g6(e){const{motionValue:t,name:i,repeatDelay:a,repeatType:o,damping:c,type:u,keyframes:f}=e;if(!i||!(e0.has(i)||Ax.has(i)))return!1;const d=t?.owner?.current;if(!(d instanceof HTMLElement)&&!(d instanceof SVGElement))return!1;const{onUpdate:m,transformTemplate:g}=t.owner.getProps();return UR()&&(e0.has(i)||Ax.has(i)&&p6(f))&&(i!=="transform"||!g)&&!m&&!a&&o!=="mirror"&&c!==0&&u!=="inertia"&&!VR(e)}const cy=(e,t)=>t&&typeof e=="number"?t.transform(e):e,y6={x:"translateX",y:"translateY",z:"translateZ",transformPerspective:"perspective"},v6=Ta.length,Mx={},t0=(e,t,i=cy(t,MR[e]))=>(Mx[e]||(Mx[e]=(y6[e]||e)+"("))+i+")",n0=(e,t)=>(typeof t=="number"?t:parseFloat(t))===(e.startsWith("scale")?1:0);function b6(e,t,i){let a="";for(let c=0;cR6.has(e),Ox=new WeakMap,T6=(e,t)=>{let i=Ox.get(e);return i?.[0]!==t&&(i=[t,"linear("+Gc(Array(t+1)).map(a=>Xc(e(a))+" "+Xc(a*100)+"%")+")"],Ox.set(e,i)),i[1]},Dx=(e,t)=>Math.min(x6,Math.max(2,Math.ceil((t-e)/Md))),zc=(e,t)=>Math.abs(e-t)<=BR,Wp=(e,t)=>e-t,Nx=(e,t,i)=>Gc(Array(i+1)).map(a=>rn(e,t,a)),ad=e=>e.motionValue.owner,jd=e=>ol.get(e),Lx=({state:e})=>e==="idle"||e==="finished",Go=(e,t)=>e.latestValues?e.latestValues[t]:e.getValue(t)?.get(),A6=({name:e,motionValue:t})=>e&&Ta.includes(e)&&t?.owner?.current instanceof HTMLElement&&UR()&&ly();function M6(e){const t=ad(e),{onUpdate:i,transformTemplate:a}=t.getProps();return!e.isHandoff&&!i&&!e.hasOnUpdate&&!a&&e.type!=="inertia"&&(Go(t,"transform")||"none")==="none"&&!Go(t,"pathRotation")&&!t.projection?.isProjecting()&&!VR(e)}class j6{constructor(t,i,a,o){this.element=t,this.update=i,this.makeDriver=a,this.animation=o}get js(){return this.driver||(this.driver=this.makeDriver(this.update))}now(){return this.driver||this.makeDriver!==ey?this.js.now():Mn.isProcessing?Mn.timestamp:Ut.now()}start(t=!0){const i=jd(this.element);!i||i.isJS?this.js.start(t):i.schedule(!1,!t)}stopJS(){this.driver?.stop()}stop(){this.stopJS();const t=jd(this.element);t&&!t.isFinishing&&t.release(this.animation)}}let kx;class O6 extends sl{constructor(t){const i=ad(t).current,{driver:a=ey}=t;let o;const c=M6(t);t.driver=d=>new j6(i,d,a,o),super(t),o=this;const u=this.driver;u&&(u.animation=this),this.canAccelerate=c;const{stop:f}=this;this.stop=()=>{this.isAccelerated()&&this.sync(),f()}}offsets(){const{keyframes:t,times:i}=this.options;return i||(this.offsetsOf!==t&&(this.offsetsOf=t,this.cachedOffsets=Gc(t)),this.cachedOffsets)}get group(){return jd(ad(this.options).current)}get js(){return this.driver?.js}stopJS(){this.driver?.stopJS()}get name(){return this.options.name}timing(){const{startTime:t,speed:i,totalDuration:a}=this,{delay:o=0,repeatType:c}=this.options;return this.holdTime!==null?[1/0,0]:a===1/0?[t+o/i,this.resolvedDuration*(c==="loop"?1:2)/i||1]:[t+(o+a)/i,0]}isAccelerated(){const{group:t,state:i}=this;return t?.tracks.has(this)&&!t.isJS&&this.canAccelerate&&(i==="running"||i==="paused")}liveValue(){return this.isAccelerated()?this.sampleAt(Ut.now()):void 0}tween(){const{keyframes:t,type:i,repeat:a,delay:o=0}=this.options;let c=-1;if(a||i!==us||this.holdTime!==null)return;for(let m=1;m=0)return;c=m-1}let{ease:u}=this.options;lR(u)&&(u=u[c]);const f=this.offsets(),d=m=>this.startTime+(o+f[m]*this.totalDuration)/this.speed;if(c>=0){const m=X0(u)?qo(u):C6(u)?Qg[u]:Bg(u);return[d(c),d(c+1),typeof m=="string"||zc(m(0),0)&&zc(m(1),1)?m:void 0]}}boundaries(t,i){const{startTime:a,speed:o,resolvedDuration:c,options:u}=this,{delay:f=0,repeat:d=0,repeatDelay:m=0,repeatType:g,type:v}=u,S=(v||us)===us?this.offsets():[0,1],x=a+f/o,E=[];if(this.holdTime!==null||!(c>0))return E;for(let w=Math.max(0,Math.floor((t-x)*o/c));w<=d;w++){const R=x+w*c/o;if(R>i)break;for(const T of S){const O=R+(w%2&&g&&g!=="loop"?1-T:T)*(c-m)/o;O>t&&O{hc||queueMicrotask(()=>{const t=hc;hc=void 0,t.forEach(i=>i())}),(hc||(hc=[])).push(e)};function N6(e){const t=e.current,i=new Set,a=new Map;let o={},c=[],u=new Map,f=[],d=!1,m=!1,g=!1,v=!1,S=-1/0,x,E=1/0,w;const R=_=>{for(const M of i)if(M.name===_)return!0},T=(_,M)=>{const z={};for(const B of _===void 0?Ta:c){const I=a.get(B),W=_===void 0?Go(e,B):I?I.sampleAt(M>_&&!I.timing()[1]?M:_):o[B];W!==void 0&&(z[B]=W)}return z},O=(_,M)=>{let z="";for(const B in _){const I=_[B];(!M||!n0(B,I))&&(z+=t0(B,I)+" ")}return(M?z.trim():z)||"none"},N=(_,M)=>O(T(_,M)),j=(_=T())=>{t.style.transform=O(_,!0)},L=_=>{_.onfinish=_.oncancel=null,_.cancel()},P=(_=!0)=>{clearTimeout(x),E=1/0,w=void 0,_&&j(),f.forEach(({animation:M})=>L(M)),f=[]},D=(_,M)=>new Animation(new KeyframeEffect(t,_,M)),A=(_,M,z=1/0)=>{const B={animation:_,offset:M,end:z};_.startTime=Ut.now()+M,z<1/0&&(_.onfinish=()=>{B.isDone=!0,f.some(I=>I.end===1/0)&&(L(_),f=f.filter(I=>I!==B)),Y.schedule(!1)}),_.oncancel=()=>f.includes(B)&&Y.demote(),f.push(B)},F=(_,M,z)=>{const B=(W,ie)=>Math.abs(_(ie)-_(W)),I=B(M,z);for(;z-M>.01;){const W=(M+z)/2;B(M,W)>B(W,z)?z=W:M=W}return B(M,z)>I/2?[M,z]:[]},H=(_,M,z,B)=>{const I=Dx(M,z);if(B.length*4>I)return;let W;for(const we of _){const Re=we.numberAt(M),ye=(we.numberAt((M+z)/2)-Re)/(we.numberAt(z)-Re);if(ye===ye){if(W===void 0)W=ye;else if(!zc(ye,W))return}}const ie=Nx(M,z,I).concat(B).sort(Wp),fe=we=>Qs(M,z,we);let pe,ce;for(const we of _){const Re=we.numberAt(M),ye=ie.map(nt=>we.numberAt(nt)-Re),ze=ye[ye.length-1],Ye=ye.some(nt=>Math.abs(nt)*BR>Math.abs(ze))?0:ze,Qe=ye.map(nt=>Ye?nt/Ye:nt);if(Ye&&!pe)pe=Qe,ce=nt=>(we.numberAt(nt)-Re)/Ye;else if(Qe.some((nt,Ne)=>!zc(nt,Ye&&pe[Ne])))return}if(!pe||pe.every((we,Re)=>zc(we,fe(ie[Re]))))return"linear";const Ae=[],ke=(we,Re=ce(we))=>Ae.push(Xc(Re)+" "+Xc(fe(we)*100)+"%");return pe.forEach((we,Re)=>{Re&&Math.abs(we-pe[Re-1])>.2&&F(ce,ie[Re-1],ie[Re]).forEach(ye=>ke(ye)),ke(ie[Re],we)}),"linear("+Ae+")"},X=(_,M,z,B)=>{const I=[M],W=[];let ie=z,fe=M;for(const we of _){const Re=we.tween();if(Re?.[2]!=="linear"){const[ye,ze]=we.timing(),[Ye,Qe]=Re||[M,ze?z:ye];ie=Math.min(ie,Ye),fe=Math.max(fe,Qe),W.push(we)}}ie=Math.max(M,ie),fe=Math.min(z,fe);const pe=(we,Re)=>W.every(ye=>!(Math.abs(ye.numberAt((we+Re)/2)-(ye.numberAt(we)+ye.numberAt(Re))/2)>(ye.name.startsWith("scale")?w6:S6))),ce=(we,Re,ye)=>{if(Re-we<1||pe(we,Re))I.push(Re);else if(ye<4)ce(we,(we+Re)/2,ye+1),ce((we+Re)/2,Re,ye+1);else{for(const ze of _)I.push(...F(Ye=>ze.numberAt(Ye),we,Re));I.push(Re)}},Ae=fe>ie?Nx(ie,fe,Math.ceil((fe-ie)/100)):[];Ae.push(z);for(const we of B)Ae.push(we,Math.min(we+.01,z));let ke=M;for(const we of Ae.sort(Wp))we>ke&&ce(ke,we,0),ke=we;return I.sort(Wp)},J=_=>{let M;for(const z of _){const B=z.tween();if(!B||M&&(Math.abs(B[0]-M[0])>1||Math.abs(B[1]-M[1])>1))return;M=[B[0],B[1],!M||B[2]===M[2]?B[2]:void 0]}return M},$=(_,M,z,B,I={fill:"both"},W)=>{const ie=B?[]:_.flatMap(ke=>ke.boundaries(M,z)),fe=B||H(_,M,z,ie),pe=fe?[M,z]:X(_,M,z,ie),ce=pe.map(ke=>N(ke,W));let Ae={transform:ce};return fe||(Ae.offset=pe.map(ke=>Qs(M,z,ke))),ce.every(ke=>ke===ce[0])&&(j(T(M,W)),Ae=null),D(Ae,{...I,duration:z-M,easing:fe||"linear"})},ee=_=>{const M=Ut.now()+_;M{E=1/0,Y.schedule(!1)},_))},re=_=>{let M=_,z=0,B=0;const I=[],W=[],ie=new Set;a.clear(),u=new Map;for(const pe of i){a.set(pe.name,pe);const[ce,Ae]=pe.timing(),ke=ce===1/0;if(u.set(pe,[pe.at(_),pe.speed,ke]),!ke){if(pe.speed<0)return;if(Ae){if(z){const we=(ce-B)/Ae;if(Math.abs(Ae-z)>1||Math.abs(we-Math.round(we))*z>1)return}else z=Ae,B=ce;W.push(pe)}else ie.add(ce);I.push(pe),M=Math.max(M,ce)}}o={},c=Ta.filter(pe=>{if(a.has(pe))return!0;const ce=o[pe]=Go(e,pe);return ce!==void 0&&!n0(pe,ce)}),P(!1);const fe=!z&&J(I);try{if(M>_){let pe;if(fe&&fe[1]>_){const[ce,Ae,ke]=fe;if(ce-_>jx)return I.forEach(we=>we.sync()),ee(w=ce-_-jx),!0;pe=typeof ke=="string"?ke:ke?T6(ke,Dx(ce,Ae)):H(I,ce,Ae,[]),pe&&A($(I,ce,Ae,pe,{fill:"both",endDelay:M-Ae}),ce-_,M-ce)}pe||A($(I,_,M),0,M-_),ie.forEach(ce=>ce{let z,B=0;for(const I of i){const W=u.get(I);if(!W)return!1;const[ie,fe,pe]=W,ce=I.at(_),Ae=I.timing()[0]===1/0;if(pe){if(Ae&&(ce===ie||!f.length))continue;return!1}const ke=(ce-ie)/fe,we=Ae?0:I.speed/fe;if(z===void 0)z=ke,B=we;else if(Math.abs(ke-z)>1||we!==B)return!1}if(z===void 0)return!0;if(!f.length){if(w===void 0||M&&B)return!1;if(B){const I=(w-z)/B;if(I<1)return!1;ee(I)}return!0}for(const{offset:I,end:W,isDone:ie}of f){const fe=z-I;if(W<1/0&&(ie?fe=W))return!1}for(const{animation:I,offset:W,isDone:ie}of f){if(ie)continue;const fe=z-W;B&&I.updatePlaybackRate&&I.playState==="running"&&Math.abs(Number(I.currentTime)-fe)<20?I.playbackRate!==B&&I.updatePlaybackRate(B):B?(I.playbackRate!==B&&(I.playbackRate=B),I.startTime=_-fe/B):(I.startTime=null,I.currentTime=fe)}return!0},K=()=>i.size?!1:(g=!0,jd(t)===Y&&ol.delete(t),Y.isJS||P(),!0),Z=()=>{const _=Ut.now();if(Y.isJS||(Y.isFinishing=!0,i.forEach(B=>{const[I,W]=B.timing();B.state==="running"&&B.speed>0&&!W&&I<=_+1&&(B.complete(),o[B.name]=Go(e,B.name),u.has(B)||(d=!0))}),Y.isFinishing=!1),m=!1,g||(i.forEach(B=>Lx(B)&&i.delete(B)),K()))return;for(const B of i)if(!B.canAccelerate)return Y.demote(!0);Y.isJS&&(Y.isJS=!1,d=!0,i.forEach(B=>B.stopJS()));const M=d,z=v;if(d=v=!1,M||!V(_,z)){if(z){if(_-SB.timing()[0]===1/0&&B.sync())},Y={tracks:i,isJS:!1,isFinishing:!1,schedule(_,M){g||(d||(d=_),v||(v=!!M),m||(m=!0,Mn.isProcessing?Xt.render(Z,!1,!0):D6(Z)))},release(_){Lx(_)&&i.delete(_),K()||Y.schedule(!0)},check(){if(!Y.isJS){for(const _ in o)if(Go(e,_)!==o[_]&&!R(_))return Y.schedule(!0,!0)}},demote(_){if(!(Y.isJS||g))return i.forEach(M=>{M.isAccelerated()&&M.sync(),_||(M.canAccelerate=!1)}),Y.isJS=!0,u=new Map,P(),i.forEach(M=>M.state==="running"&&M.js?.start()),!0}};return ol.set(t,Y),Y}class L6 extends ry{constructor(t){super(),this.stop=()=>{this._animation&&(this._animation.stop(),this.stopTimeline?.()),this.keyframeResolver?.cancel()},this.createdAt=Ut.now();const{keyframes:i,name:a,motionValue:o,element:c}=t,u=t;u.autoplay??(u.autoplay=!0),u.delay??(u.delay=0),u.type??(u.type="keyframes"),u.repeat??(u.repeat=0),u.repeatDelay??(u.repeatDelay=0),u.repeatType??(u.repeatType="loop");const f=c?.KeyframeResolver||oy;this.keyframeResolver=new f(i,(d,m,g)=>this.onKeyframesResolved(d,m,u,!g),a,o,c),this.keyframeResolver?.scheduleResolve()}onKeyframesResolved(t,i,a,o){this.keyframeResolver=void 0;const{name:c,type:u,velocity:f,delay:d,isHandoff:m,onUpdate:g}=a;this.resolvedAt=Ut.now();const v=h6(t,c,u,f);v||((_i.instantAnimations||!d)&&g?.(Kc(t,a,i)),t[0]=t[t.length-1],Jg(a),a.repeat=0);const{onComplete:S}=a;a.finalKeyframe=i,a.keyframes=t,a.onComplete=()=>{S?.(),this.notifyFinished()};const x=v&&!m&&g6(a),E=!x&&A6(a);o&&(x||E||this.resolvedAt!==this.createdAt)&&(a.startTime??(a.startTime=CR(this.createdAt,this.resolvedAt)));let w;if(x){a.element=a.motionValue?.owner?.current;try{w=new f6(a)}catch{w=new sl(a)}}else E?w=new O6(a):w=new sl(a);this.pendingTimeline&&(this.stopTimeline=w.attachTimeline(this.pendingTimeline),this.pendingTimeline=void 0),this._animation=w}get finished(){return this._animation?this._animation.finished:super.finished}then(t,i){return this.finished.finally(t).then(()=>{})}liveValue(){return this._animation?.liveValue?.()}get animation(){return this._animation||(this.keyframeResolver?.resume(),n6()),this._animation}get duration(){return this.animation.duration}get iterationDuration(){return this.animation.iterationDuration}get time(){return this.animation.time}set time(t){this.animation.time=t}get speed(){return this.animation.speed}get state(){return this.animation.state}set speed(t){this.animation.speed=t}get startTime(){return this.animation.startTime}attachTimeline(t){return this._animation?this.stopTimeline=this.animation.attachTimeline(t):this.pendingTimeline=t,()=>this.stop()}play(){this.animation.play()}pause(){this.animation.pause()}complete(){this.animation.complete()}cancel(){this._animation?.cancel(),this.keyframeResolver?.cancel()}}function IR(e,t,i,a=0,o=1){const c=Array.from(e).sort((m,g)=>m.sortNodePosition(g)).indexOf(t),u=e.size,f=(u-1)*a;return typeof i=="function"?i(c,u):o===1?c*a:f-c*a}const zx=30,k6=e=>!isNaN(parseFloat(e));class z6{constructor(t,i={}){this.canTrackVelocity=null,this.events={},this.updateAndNotify=a=>{const o=Ut.now();if(this.updatedAt!==o&&this.setPrevFrameValue(),this.prev=this.current,this.setCurrent(a),this.current!==this.prev&&(this.dirty(),this.dependents))for(const c of this.dependents)c.dirty()},this.hasAnimated=!1,this.setCurrent(t),this.owner=i.owner}setCurrent(t){this.current=t,this.updatedAt=Ut.now(),this.canTrackVelocity===null&&t!==void 0&&(this.canTrackVelocity=k6(this.current))}setPrevFrameValue(t=this.current){this.prevFrameValue=t,this.prevUpdatedAt=this.updatedAt}onChange(t){return this.on("change",t)}on(t,i){var a;return t==="change"?this.onChangeSubscribe(i):((a=this.events)[t]||(a[t]=new Cd)).add(i)}onChangeSubscribe(t){const{events:i}=this;return!i.change&&!this.changeSubscriber?this.changeSubscriber=t:(i.change||(i.change=new Cd,i.change.add(this.changeSubscriber),this.changeSubscriber=void 0),i.change.add(t)),()=>{this.changeSubscriber===t?this.changeSubscriber=void 0:i.change?.remove(t),this.stopIfUnobserved()}}stopIfUnobserved(){Xt.read(()=>{!this.changeSubscriber&&!this.events.change?.getSize()&&this.stop()})}clearListeners(){this.changeSubscriber=void 0;for(const t in this.events)this.events[t].clear()}attach(t,i){this.passiveEffect=t,this.stopPassiveEffect=i}set(t){this.passiveEffect?this.passiveEffect(t,this.updateAndNotify):this.updateAndNotify(t)}setWithVelocity(t,i,a){this.set(i),this.prev=void 0,this.prevFrameValue=t,this.prevUpdatedAt=this.updatedAt-a}jump(t,i=!0){i&&(this.updatedAt=Ut.now(),this.stop()),this.updateAndNotify(t),this.prev=t,this.prevUpdatedAt=this.prevFrameValue=void 0,this.stopPassiveEffect?.()}dirty(){const{current:t,changeSubscriber:i}=this;i?i(t):this.events.change?.notify(t)}addDependent(t){(this.dependents||(this.dependents=new Set)).add(t)}removeDependent(t){this.dependents?.delete(t)}get(){const t=this.animation?.liveValue?.();return t===void 0?this.current:t}getCurrent(){return this.current}getPrevious(){return this.prev}getVelocity(){const t=Ut.now();if(!this.canTrackVelocity||this.prevFrameValue===void 0||t-this.updatedAt>zx)return 0;const i=Math.min(this.updatedAt-this.prevUpdatedAt,zx);return eR(parseFloat(this.current)-parseFloat(this.prevFrameValue),i)}start(t){return new Promise(i=>this.run(t,i))}run(t,i){this.stop(),this.hasAnimated=!0;let a=!1,o;o=t(()=>{a=!0,this.events.animationComplete?.notify(),this.animation===o&&(this.animation=void 0),i?.()}),a||(this.animation=o),this.events.animationStart?.notify()}stop(){this.animation&&(this.animation.stop(),this.events.animationCancel?.notify()),this.animation=void 0}isAnimating(){return!!this.animation}destroy(){this.dependents?.clear(),this.events.destroy?.notify(),this.clearListeners(),this.stop(),this.stopPassiveEffect?.()}}function ll(e,t){return new z6(e,t)}function uy(e,t){if(e?.inherit&&t){const{inherit:i,...a}=e;return{...t,...a}}return e}function fy(e,t){const i=e?.[t]??e?.default??e;return i!==e?uy(i,e):i}const P6={type:"spring",stiffness:500,damping:25,restSpeed:10},_6=e=>({type:"spring",stiffness:550,damping:e===0?2*Math.sqrt(550):30,restSpeed:10}),V6={type:"keyframes",duration:.8},U6={type:"keyframes",ease:[.25,.1,.35,1],duration:.3},B6=(e,{keyframes:t})=>t.length>2?V6:fs.has(e)?e.startsWith("scale")?_6(t[1]):P6:U6,I6=new Set(["when","delay","delayChildren","staggerChildren","staggerDirection","repeat","repeatType","repeatDelay","from","elapsed","out","mixer"]);function H6(e){for(const t in e)if(!I6.has(t))return!0;return!1}const dy=(e,t,i,a={},o,c)=>u=>{const f=fy(a,e)||{},d=f.delay||a.delay||0;let{elapsed:m=0}=a;m=m-Sr(d);const g={keyframes:Array.isArray(i)?i:[null,i],ease:"easeOut",velocity:t.getVelocity(),...f,delay:-m,onUpdate:S=>{t.set(S),f.onUpdate&&f.onUpdate(S)},onComplete:()=>{u(),f.onComplete&&f.onComplete()},name:e,motionValue:t,element:c?void 0:o,hasOnUpdate:!!f.onUpdate};H6(f)||Object.assign(g,B6(e,g)),g.duration&&(g.duration=Sr(g.duration)),g.repeatDelay&&(g.repeatDelay=Sr(g.repeatDelay)),g.from!==void 0&&(g.keyframes[0]=g.from);let v=!1;if((g.type===!1||g.duration===0&&!g.repeatDelay)&&(Jg(g),g.delay===0&&(v=!0)),(_i.instantAnimations||_i.skipAnimations||o?.shouldSkipAnimations||f.skipAnimations)&&(v=!0,Jg(g),g.delay=0),g.allowFlatten=!f.type&&!f.ease,v&&!c&&t.get()!==void 0){const S=Kc(g.keyframes,f);if(S!==void 0){Xt.update(()=>{g.onUpdate(S),g.onComplete()});return}}return f.isSync?new sl(g):new L6(g)},F6=/^var\(--(?:([\w-]+)|([\w-]+), ?([a-zA-Z\d ()%#.,-]+))\)/u;function Y6(e){const t=F6.exec(e);if(!t)return[,];const[,i,a,o]=t;return[`--${i??a}`,o]}function hy(e,t,i=1){const[a,o]=Y6(e);if(!a)return;const c=window.getComputedStyle(t).getPropertyValue(a);if(c){const u=c.trim();return F0(u)?parseFloat(u):u}return rh(o)?hy(o,t,i+1):o}function q6(e){const t=[{},{}];return e?.values.forEach((i,a)=>{t[0][a]=i.get(),t[1][a]=i.getVelocity()}),t}function HR(e,t,i,a){const o=c=>typeof c=="function"?c(i!==void 0?i:e.custom,...q6(a)):c;return t=o(t),typeof t=="string"&&(t=e.variants&&e.variants[t]),o(t)}function Ws(e,t,i){return HR(e.getProps(),t,i,e)}const FR=(e,t)=>t==="exit"?e.presenceContext?.custom:void 0,YR=new Set(["width","height","top","left","right","bottom",...Ta]),G6=e=>Array.isArray(e);function K6(e,t,i){e.hasValue(t)?e.getValue(t).set(i):e.addValue(t,ll(i))}function X6(e){return G6(e)?e[e.length-1]||0:e}function $6(e,t){const i=Ws(e,t);let{transitionEnd:a={},transition:o={},...c}=i||{};c={...c,...a};for(const u in c){const f=X6(c[u]);K6(e,u,f)}}const ar=e=>!!(e&&e.getVelocity);function W6(e){return!!(ar(e)&&e.add)}function r0(e,t){const i=e.getValue("willChange");if(W6(i))return i.add(t);if(!i&&_i.WillChange){const a=new _i.WillChange("auto");e.addValue("willChange",a),a.add(t)}}const qR="data-framer-appear-id";function GR(e){return e.props[qR]}const Z6=typeof window<"u";function Q6({protectedKeys:e,needsAnimating:t},i){const a=i in e&&!t[i];return t[i]=!1,a}function KR(e,t,{delay:i=0,transitionOverride:a,type:o}={}){let{transition:c,transitionEnd:u,...f}=t;const d=e.getDefaultTransition();c=c?uy(c,d):d;const m=c?.reduceMotion,g=c?.skipAnimations;a&&(c=a);const v=[],S=o&&e.animationState?.getState()[o],x=c?.path;x&&(x.animateValues?x.animateValues(E=>e.getValue(E,e.latestValues[E]??0),f,c,i,v):x.animateVisualElement?.(e,f,c,i,v));for(const E in f){const w=e.getValue(E,e.latestValues[E]??null),R=f[E];if(R===void 0||S&&Q6(S,E))continue;const T={delay:i,...fy(S?.out[E]||c||{},E)};g&&(T.skipAnimations=!0);const O=w.get();if(O!==void 0&&!w.isAnimating()&&!Array.isArray(R)&&R===O&&!T.velocity){Xt.update(()=>w.set(R));continue}let N=!1;if(Z6&&window.MotionHandoffAnimation){const P=GR(e);if(P){const D=window.MotionHandoffAnimation(P,E,Xt);D!==null&&(T.startTime=D,N=!0)}}r0(e,E);const j=m??e.shouldReduceMotion;w.run(dy(E,w,R,j&&YR.has(E)?{type:!1}:T,e,N));const L=w.animation;L&&v.push(L)}if(u){const E=()=>Xt.update(()=>{u&&$6(e,u)});v.length?Promise.all(v).then(E):E()}return v}function i0(e,t,i={}){const a=Ws(e,t,FR(e,i.type)),o=i.transitionOverride||(a?.transition??(e.getDefaultTransition()||{})),c=()=>Promise.all(a?KR(e,a,i):[]),u=(d=0)=>{const{variantChildren:m}=e,{delayChildren:g=0,staggerChildren:v,staggerDirection:S}=o,x=[];return m?.forEach(E=>{E.notify("AnimationStart",t),x.push(i0(E,t,{...i,delay:d+(typeof g=="function"?0:g)+IR(m,E,g,v,S)}).then(()=>E.notify("AnimationComplete",t)))}),Promise.all(x)},{when:f}=o;return f?f==="beforeChildren"?c().then(()=>u()):u().then(c):Promise.all([c(),u(i.delay)])}function J6(e,t,i={}){return e.notify("AnimationStart",t),(Array.isArray(t)?Promise.all(t.map(o=>i0(e,o,i))):typeof t=="string"?i0(e,t,i):Promise.all(KR(e,Ws(e,t,i.custom),i))).then(()=>{e.notify("AnimationComplete",t)})}const ej={test:e=>e==="auto",parse:e=>e},tj=e=>t=>t.test(e),nj=[wl,Ve,Zi,wa,$M,XM,ej],Px=e=>nj.find(tj(e));function rj(e){return typeof e=="number"?e===0:e!==null?e==="none"||e==="0"||Y0(e):!0}const ij=new Set(["auto","none","0"]);function aj(e,t,i){let a=0,o;for(;at.measureViewportBox())}measureInitialState(){const{element:t,unresolvedKeyframes:i,name:a}=this;if(!t?.current)return;a==="height"&&(this.suspendedScrollY=window.pageYOffset),this.measuredOrigin=this.measure(),i[0]=this.measuredOrigin;const o=i[i.length-1];o!==void 0&&this.motionValue?.jump(o,!1)}measureEndState(){const{element:t,unresolvedKeyframes:i}=this;if(!t?.current)return;this.motionValue?.jump(this.measuredOrigin,!1);const a=i.length-1,o=i[a];i[a]=this.measure(),o!==null&&this.finalKeyframe===void 0&&(this.finalKeyframe=o),this.resolveNoneKeyframes()}}const my=["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"];function sd(e){return JE(e)&&"offsetHeight"in e&&!("ownerSVGElement"in e)}function py(e){return JE(e)&&"ownerSVGElement"in e}const Od={};function gy(e){return Od.current?.add(e),e}const yy=e=>Od.current?Od.current.bind(e):e;function XR(e,t,i){if(e==null)return[];if(e instanceof EventTarget)return[e];if(typeof e=="string"){const a=t?t.current:Od.current?.root||document,o=i?.[e]??a.querySelectorAll(e);return o?Array.from(o):[]}return Array.from(e).filter(a=>a!=null)}function $R(e){return e.replace(/([A-Z])/g,t=>`-${t.toLowerCase()}`)}function vy(e,t,i){const{style:a,vars:o,transformOrigin:c}=e;let u=!1,f=!1;for(const d in t){const m=t[d];if(fs.has(d)){u=!0;continue}else if(uR(d)){o[d]=m;continue}else{const g=cy(m,iy[d]);d.startsWith("origin")?(f=!0,c[d]=g):a[d]=g}}if(t.transform||(u||i?a.transform=b6(t,e.transform,i):a.transform&&(a.transform="none")),f){const{originX:d="50%",originY:m="50%",originZ:g=0}=c;a.transformOrigin=`${d} ${m} ${g}`}}const oj={offset:"stroke-dashoffset",array:"stroke-dasharray"},lj={offset:"strokeDashoffset",array:"strokeDasharray"};function cj(e,t,i=1,a=0,o=!0){e.pathLength=1;const c=o?oj:lj;e[c.offset]=`${-a}`,e[c.array]=`${t} ${i}`}const WR=["transform","opacity","clipPath","filter","offsetDistance","offsetPath","offsetRotate","offsetAnchor"];function ZR(e,{attrX:t,attrY:i,attrScale:a,pathLength:o,pathSpacing:c=1,pathOffset:u=0,...f},d,m,g){if(vy(e,f,m),d){e.style.viewBox&&(e.attrs.viewBox=e.style.viewBox);return}e.attrs=e.style,e.style={};const{attrs:v,style:S}=e;for(const x of WR)v[x]!==void 0&&(S[x]=v[x],delete v[x]);(S.transform||v.transformOrigin)&&(S.transformOrigin=v.transformOrigin??"50% 50%",delete v.transformOrigin),S.transform&&(S.transformBox=g?.transformBox??"fill-box",delete v.transformBox),t!==void 0&&(v.x=t),i!==void 0&&(v.y=i),a!==void 0&&(v.scale=a),o!==void 0&&cj(v,o,c,u,!1)}function QR({top:e,left:t,right:i,bottom:a}){return{x:{min:t,max:i},y:{min:e,max:a}}}function uj({x:e,y:t}){return{top:t.min,right:e.max,bottom:t.max,left:e.min}}function fj(e,t){if(!t)return e;const i=t({x:e.left,y:e.top}),a=t({x:e.right,y:e.bottom});return{top:i.y,left:i.x,bottom:a.y,right:a.x}}function Zp(e){return e===void 0||e===1}function a0({scale:e,scaleX:t,scaleY:i}){return!Zp(e)||!Zp(t)||!Zp(i)}const cl=["rotate","rotateX","rotateY","rotateZ","skewX","skewY"];function Fs(e){return a0(e)||eC(e)||JR(e)}function JR(e){return e.z||e.rotate||e.rotateX||e.rotateY||e.rotateZ||e.skewX||e.skewY}function eC(e){return _x(e.x)||_x(e.y)}function _x(e){return e&&e!=="0%"}function Dd(e,t,i){const a=e-i,o=t*a;return i+o}function Vx(e,t,i,a,o){return o!==void 0&&(e=Dd(e,o,a)),Dd(e,i,a)+t}function s0(e,t=0,i=1,a,o){e.min=Vx(e.min,t,i,a,o),e.max=Vx(e.max,t,i,a,o)}function tC(e,{x:t,y:i}){s0(e.x,t.translate,t.scale,t.originPoint),s0(e.y,i.translate,i.scale,i.originPoint)}const Ux=.999999999999,Bx=1.0000000000001;function dj(e,t,i,a=!1){const o=i.length;if(!o)return;t.x=t.y=1;let c,u;for(let f=0;fUx&&(t.x=1),t.yUx&&(t.y=1)}function Ni(e,t){e.min+=t,e.max+=t}function Ix(e,t,i,a,o=.5){const c=rn(e.min,e.max,o);s0(e,t,i,c,a)}function Hx(e,t){return typeof e=="string"?parseFloat(e)/100*(t.max-t.min):e}function od(e,t,i){const a=i??e;Ix(e.x,Hx(t.x,a.x),t.scaleX,t.scale,t.originX),Ix(e.y,Hx(t.y,a.y),t.scaleY,t.scale,t.originY)}function nC(e,t){return QR(fj(e.getBoundingClientRect(),t))}function hj(e,t,i){const a=nC(e,i),{scroll:o}=t;return o&&(Ni(a.x,o.offset.x),Ni(a.y,o.offset.y)),a}const mj=()=>({x:document.documentElement.scrollLeft||document.body?.scrollLeft||0,y:document.documentElement.scrollTop||document.body?.scrollTop||0}),{schedule:Wc}=yR(queueMicrotask,!1);function pj(e,t,i){const a=ar(e)?e:ll(e);return a.run(dy("",a,t,i)),a.animation}const jc={};function gj(e,t){const i=Ut.now();e=yy(e);const a=({timestamp:o})=>{const c=o-i;c>=t&&(Xr(a),e(c-t))};return Xt.setup(a,!0),gy(()=>Xr(a))}function yj(e){return e&&typeof e=="object"&&Object.prototype.hasOwnProperty.call(e,"current")}function vj(e){return py(e)&&e.tagName==="svg"}function ld(e){return ar(e)?e.get():e}const Fx=e=>typeof e=="number"?e:parseFloat(e),bj=my.length,Yx=e=>typeof e=="number"||Ve.test(e);function xj(e,t,i,a,o,c){o?(e.opacity=rn(0,i.opacity??1,Sj(a)),e.opacityExit=rn(t.opacity??1,0,wj(a))):c&&(e.opacity=rn(t.opacity??1,i.opacity??1,a));for(let u=0;uat?1:i(Qs(e,t,a))}function o0(e,t){e.min=t.min,e.max=t.max}function Ai(e,t){o0(e.x,t.x),o0(e.y,t.y)}function Gx(e,t){e.translate=t.translate,e.scale=t.scale,e.originPoint=t.originPoint,e.origin=t.origin}const iC=1e-4,Ej=1-iC,Rj=1+iC,aC=.01,Cj=0-aC,Tj=0+aC;function Dr(e){return e.max-e.min}function Aj(e,t,i){return Math.abs(e-t)<=i}function Kx(e,t,i,a=.5){e.origin=a,e.originPoint=rn(t.min,t.max,e.origin),e.scale=Dr(i)/Dr(t),e.translate=rn(i.min,i.max,e.origin)-e.originPoint,(e.scale>=Ej&&e.scale<=Rj||isNaN(e.scale))&&(e.scale=1),(e.translate>=Cj&&e.translate<=Tj||isNaN(e.translate))&&(e.translate=0)}function Nd(e,t,i,a){Kx(e.x,t.x,i.x,a?.originX),Kx(e.y,t.y,i.y,a?.originY)}function Xx(e,t,i,a=0){const o=a?rn(i.min,i.max,a):i.min;e.min=o+t.min,e.max=e.min+Dr(t)}function Mj(e,t,i,a){Xx(e.x,t.x,i.x,a?.x),Xx(e.y,t.y,i.y,a?.y)}function $x(e,t,i,a=0){const o=a?rn(i.min,i.max,a):i.min;e.min=t.min-o,e.max=e.min+Dr(t)}function Ld(e,t,i,a){$x(e.x,t.x,i.x,a?.x),$x(e.y,t.y,i.y,a?.y)}function Wx(e,t,i,a,o){return e-=t,e=Dd(e,1/i,a),o!==void 0&&(e=Dd(e,1/o,a)),e}function jj(e,t=0,i=1,a=.5,o,c=e,u=e){if(Zi.test(t)&&(t=parseFloat(t),t=rn(u.min,u.max,t/100)-u.min),typeof t!="number")return;let f=rn(c.min,c.max,a);e===c&&(f-=t),e.min=Wx(e.min,t,i,f,o),e.max=Wx(e.max,t,i,f,o)}function Zx(e,t,[i,a,o],c,u){jj(e,t[i],t[a],t[o],t.scale,c,u)}const Oj=["x","scaleX","originX"],Dj=["y","scaleY","originY"];function Qx(e,t,i,a){Zx(e.x,t,Oj,i?.x,a?.x),Zx(e.y,t,Dj,i?.y,a?.y)}const Jx=e=>typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().includes(e),eS=Jx("applewebkit/")&&!Jx("chrome/")?Math.round:Li;function tS(e){e.min=eS(e.min),e.max=eS(e.max)}function Nj(e){tS(e.x),tS(e.y)}const nS=()=>({translate:0,scale:1,origin:0,originPoint:0}),Ko=()=>({x:nS(),y:nS()}),rS=()=>({min:0,max:0}),Hn=()=>({x:rS(),y:rS()});function iS(e){return e.translate===0&&e.scale===1}function sC(e){return iS(e.x)&&iS(e.y)}function aS(e,t){return e.min===t.min&&e.max===t.max}function Lj(e,t){return aS(e.x,t.x)&&aS(e.y,t.y)}function sS(e,t){return Math.round(e.min)===Math.round(t.min)&&Math.round(e.max)===Math.round(t.max)}function oC(e,t){return sS(e.x,t.x)&&sS(e.y,t.y)}function oS(e){return Dr(e.x)/Dr(e.y)}function lS(e,t){return e.translate===t.translate&&e.scale===t.scale&&e.originPoint===t.originPoint}class kj{constructor(){this.members=[]}add(t){H0(this.members,t);for(let i=this.members.length-1;i>=0;i--){const a=this.members[i];if(a===t||a===this.lead||a===this.prevLead)continue;const o=a.instance;(!o||o.isConnected===!1)&&!a.snapshot&&(Rd(this.members,a),a.unmount())}t.scheduleRender()}remove(t){if(Rd(this.members,t),t===this.prevLead&&(this.prevLead=void 0),t===this.lead){const i=this.members[this.members.length-1];i&&this.promote(i)}}relegate(t){for(let i=this.members.indexOf(t)-1;i>=0;i--){const a=this.members[i];if(a.isPresent!==!1&&a.instance?.isConnected!==!1)return this.promote(a),!0}return!1}promote(t,i){const a=this.lead;if(t!==a&&(this.prevLead=a,this.lead=t,t.show(),a)){a.updateSnapshot(),t.scheduleRender();const{layoutDependency:o}=a.options,{layoutDependency:c}=t.options;(o===void 0||o!==c)&&(t.resumeFrom=a,i&&(a.preserveOpacity=!0),a.snapshot&&(t.snapshot=a.snapshot,t.snapshot.latestValues=a.animationValues||a.latestValues),t.root?.isUpdating&&(t.isLayoutDirty=!0)),t.options.crossfade===!1&&a.hide()}}exitAnimationComplete(){this.members.forEach(t=>{t.options.onExitComplete?.(),t.resumingFrom?.options.onExitComplete?.()})}scheduleRender(){this.members.forEach(t=>t.instance&&t.scheduleRender(!1))}removeLeadSnapshot(){this.lead?.snapshot&&(this.lead.snapshot=void 0)}}function cS(e,t){return t.max===t.min?0:e/(t.max-t.min)*100}const mc={correct:(e,t)=>{if(!t.target)return e;if(typeof e=="string")if(Ve.test(e))e=parseFloat(e);else return e;const i=cS(e,t.target.x),a=cS(e,t.target.y);return`${i}% ${a}%`}},zj={correct:(e,{treeScale:t,projectionDelta:i})=>{const a=e,o=mi.parse(e);if(o.length>5)return a;const c=mi.createTransformer(e),u=typeof o[0]!="number"?1:0,f=i.x.scale*t.x,d=i.y.scale*t.y;o[0+u]/=f,o[1+u]/=d;const m=rn(f,d,.5);return typeof o[2+u]=="number"&&(o[2+u]/=m),typeof o[3+u]=="number"&&(o[3+u]/=m),c(o)}},Pj={borderRadius:Object.assign({},mc,{applyTo:my.slice()}),borderTopLeftRadius:mc,borderTopRightRadius:mc,borderBottomLeftRadius:mc,borderBottomRightRadius:mc,boxShadow:zj};function _j(e,t,i){let a="";const o=e.x.translate/t.x,c=e.y.translate/t.y,u=i?.z||0;(o||c||u)&&(a=`translate3d(${o}px, ${c}px, ${u}px) `);let f="";if(i){const{transformPerspective:d}=i;d&&(a=`perspective(${d}px) ${a}`);for(let m=0;me.depth-t.depth;class Uj{constructor(){this.children=[],this.isDirty=!1}add(t){H0(this.children,t),this.isDirty=!0}remove(t){Rd(this.children,t),this.isDirty=!0}forEach(t){this.isDirty&&this.children.sort(Vj),this.isDirty=!1,this.children.forEach(t)}}const cd={hasAnimatedSinceResize:!0,hasEverUpdated:!1},uS=["z","skew","skewZ"],Bj=1e3;let Ij=0;function fS(e,t,i,a){const{latestValues:o}=t;o[e]&&(i[e]=o[e],t.setStaticValue(e,0),a&&(a[e]=0))}const Qp=e=>e.instance&&ol.get(e.instance)?.demote()&&e.resetSkewAndRotation();function lC(e){if(e.hasCheckedOptimisedAppear=!0,e.root===e)return;const{visualElement:t}=e.options;if(!t)return;const i=GR(t);if(window.MotionHasOptimisedAnimation(i,"transform")){const{layout:o,layoutId:c}=e.options;window.MotionCancelOptimisedAnimation(i,"transform",Xt,!(o||c))}const{parent:a}=e;a&&!a.hasCheckedOptimisedAppear&&lC(a)}function cC(e){if(e)return e.options.allowProjection!==!1?e.projection:cC(e.parent)}function uC({attachResizeListener:e,defaultParent:t,measureScroll:i,checkIsScrollRoot:a,resetTransform:o}){return Object.assign(jc,{...Pj,...jc}),class{static create(u,f,d){const{layoutId:m,layout:g,drag:v,dragConstraints:S,layoutScroll:x,layoutRoot:E,layoutAnchor:w,layoutCrossfade:R}=f,T=u.projection=new this(u.latestValues,f["data-framer-portal-id"]?void 0:cC(u.parent));T.setOptions({layoutId:m,layout:g,alwaysMeasureLayout:!!v||S&&yj(S),visualElement:u,animationType:typeof g=="string"?g:"both",initialPromotionConfig:d,crossfade:R,layoutScroll:x,layoutRoot:E,layoutAnchor:w});const O=T.getStack()?.lead;O&&!T.root.isUpdateBlocked()&&(O.willUpdate(),O.scheduleCheckAfterUnmount())}constructor(u={},f=t?.()){this.id=Ij++,this.animationId=0,this.animationCommitId=0,this.children=new Set,this.options={},this.isTreeAnimating=!1,this.isAnimationBlocked=!1,this.isLayoutDirty=!1,this.isProjectionDirty=!1,this.isSharedProjectionDirty=!1,this.isTransformDirty=!1,this.updateManuallyBlocked=!1,this.updateBlockedByResize=!1,this.isUpdating=!1,this.isSVG=!1,this.needsReset=!1,this.shouldResetTransform=!1,this.hasCheckedOptimisedAppear=!1,this.treeScale={x:1,y:1},this.eventHandlers=new Map,this.hasTreeAnimated=!1,this.updateScheduled=!1,this.scheduleUpdate=()=>this.update(),this.projectionUpdateScheduled=!1,this.checkUpdateFailed=()=>{this.isUpdating&&(this.isUpdating=!1,this.clearAllSnapshots())},this.updateProjection=()=>{this.projectionUpdateScheduled=!1,this.nodes.forEach(Yj),this.nodes.forEach(Qj),this.nodes.forEach(Jj),this.nodes.forEach(qj)},this.resolvedRelativeTargetAt=0,this.hasProjected=!1,this.isVisible=!0,this.animationProgress=0,this.sharedNodes=new Map,this.latestValues=u,this.root=f?f.root||f:this,this.path=f?[...f.path,f]:[],this.parent=f,this.depth=f?f.depth+1:0;for(let d=0;dthis.root.updateBlockedByResize=!1;Xt.read(()=>{v=window.innerWidth}),e(u,()=>{const x=window.innerWidth;x!==v&&(v=x,this.root.updateBlockedByResize=!0,g?.(),g=gj(S,250),cd.hasAnimatedSinceResize&&(cd.hasAnimatedSinceResize=!1,this.nodes.forEach(mS)))})}f&&this.root.registerSharedNode(f,this),this.addLayoutListener()}addLayoutListener(){const{layoutId:u,layout:f,visualElement:d,animate:m}=this.options;!this.instance||this.hasLayoutListener||m===!1||!d||!(u||f)||(this.hasLayoutListener=!0,this.addEventListener("didUpdate",({delta:g,hasLayoutChanged:v,hasRelativeLayoutChanged:S,layout:x})=>{if(this.isAnimationBlocked){this.target=void 0,this.relativeTarget=void 0;return}const E=this.options.transition||d.getDefaultTransition()||r8,{onLayoutAnimationStart:w,onLayoutAnimationComplete:R}=d.getProps(),T=!this.targetLayout||!oC(this.targetLayout,x),O=!v&&S;if(this.options.layoutRoot||this.resumeFrom||O||v&&(T||!this.currentAnimation)){this.resumeFrom&&(this.resumingFrom=this.resumeFrom,this.resumingFrom.resumingFrom=void 0);const N={...fy(E,"layout"),onPlay:w,onComplete:R};(d.shouldReduceMotion||this.options.layoutRoot)&&(N.delay=0,N.type=!1),this.startAnimation(N),this.setAnimationOrigin(g,O,N.path)}else v||mS(this),this.isLead()&&this.options.onExitComplete?.();this.targetLayout=x}))}unmount(){this.options.layoutId&&this.willUpdate(),this.root.nodes.remove(this),this.getStack()?.remove(this),this.parent?.children.delete(this),this.instance=void 0,this.eventHandlers.clear(),this.hasLayoutListener=!1,Xr(this.updateProjection)}blockUpdate(){this.updateManuallyBlocked=!0}unblockUpdate(){this.updateManuallyBlocked=!1}isUpdateBlocked(){return this.updateManuallyBlocked||this.updateBlockedByResize}startUpdate(){this.isUpdateBlocked()||(this.isUpdating=!0,this.nodes?.forEach(e8),this.animationId++)}getTransformTemplate(){const{visualElement:u}=this.options;return u&&u.getProps().transformTemplate}willUpdate(u=!0){if(this.root.hasTreeAnimated=!0,this.root.isUpdateBlocked()){this.options.onExitComplete?.();return}if(window.MotionCancelOptimisedAnimation&&!this.hasCheckedOptimisedAppear&&lC(this),!this.root.isUpdating&&this.root.startUpdate(),this.isLayoutDirty)return;Qp(this),this.isLayoutDirty=!0;for(let g=0;gu.members.length?u.removeLeadSnapshot():this.sharedNodes.delete(f))}scheduleUpdateProjection(){this.projectionUpdateScheduled||(this.projectionUpdateScheduled=!0,Xt.preRender(this.updateProjection,!1,!0))}scheduleCheckAfterUnmount(){Xt.postRender(()=>{this.isLayoutDirty?this.root.didUpdate():this.root.checkUpdateFailed()})}updateSnapshot(){this.snapshot||!this.instance||(this.snapshot=this.measure(),this.snapshot&&!Dr(this.snapshot.measuredBox.x)&&!Dr(this.snapshot.measuredBox.y)&&(this.snapshot=void 0))}updateLayout(){if(!this.instance||(this.updateScroll(),!(this.options.alwaysMeasureLayout&&this.isLead())&&!this.isLayoutDirty))return;if(this.resumeFrom&&!this.resumeFrom.instance)for(let d=0;d{const L=j/1e3,P=N?.(L);pS(S.x,u.x,L),pS(S.y,u.y,L),P&&(S.x.translate=P.x,S.y.translate=P.y),this.setTargetDelta(S),this.relativeTarget&&this.relativeTargetOrigin&&this.layout&&this.relativeParent&&this.relativeParent.layout&&(Ld(x,this.layout.layoutBox,this.relativeParent.layout.layoutBox,this.options.layoutAnchor||void 0),t8(this.relativeTarget,this.relativeTargetOrigin,x,L),O&&Lj(this.relativeTarget,O)&&(this.isProjectionDirty=!1),O||(O=Hn()),Ai(O,this.relativeTarget)),E&&(this.animationValues=v,xj(v,g,this.latestValues,L,T,R)),P?.rotate!==void 0&&(this.animationValues||(this.animationValues=v),this.animationValues.pathRotation=P.rotate),this.root.scheduleUpdateProjection(),this.scheduleRender(),this.animationProgress=L},this.mixTargetDelta(this.options.layoutRoot?1e3:0)}startAnimation(u){this.notifyListeners("animationStart"),this.currentAnimation?.stop(),this.resumingFrom?.currentAnimation?.stop(),this.pendingAnimation&&(Xr(this.pendingAnimation),this.pendingAnimation=void 0),this.pendingAnimation=Xt.update(()=>{cd.hasAnimatedSinceResize=!0,this.motionValue||(this.motionValue=ll(0)),this.motionValue.jump(0,!1),this.currentAnimation=pj(this.motionValue,[0,1e3],{...u,velocity:0,isSync:!0,onUpdate:f=>{this.mixTargetDelta(f),u.onUpdate&&u.onUpdate(f)},onComplete:()=>{u.onComplete&&u.onComplete(),this.completeAnimation()}}),I4(this.currentAnimation,this),this.resumingFrom&&(this.resumingFrom.currentAnimation=this.currentAnimation),this.pendingAnimation=void 0})}completeAnimation(){this.resumingFrom&&(this.resumingFrom.currentAnimation=void 0,this.resumingFrom.preserveOpacity=void 0);const u=this.getStack();u&&u.exitAnimationComplete(),this.resumingFrom=this.currentAnimation=this.animationValues=void 0,this.notifyListeners("animationComplete")}finishAnimation(){this.currentAnimation&&(this.mixTargetDelta?.(Bj),this.currentAnimation.stop()),this.completeAnimation()}applyTransformsToTarget(){const u=this.getLead(),{targetWithTransforms:f,layout:d,latestValues:m}=u;let{target:g}=u;if(!(!f||!g||!d)){if(this!==u&&this.layout&&d&&fC(this.options.animationType,this.layout.layoutBox,d.layoutBox)){const{layoutBox:v}=this.layout,S=g;g=this.target||Hn(),yS(g.x,S.x,v.x),yS(g.y,S.y,v.y)}Ai(f,g),od(f,m),Nd(this.projectionDeltaWithTransform,this.layoutCorrected,f,m)}}registerSharedNode(u,f){this.sharedNodes.has(u)||this.sharedNodes.set(u,new kj),this.sharedNodes.get(u).add(f);const m=f.options.initialPromotionConfig;f.promote({transition:m?.transition,preserveFollowOpacity:m?.shouldPreserveFollowOpacity?m.shouldPreserveFollowOpacity(f):void 0})}isLead(){const u=this.getStack();return u?u.lead===this:!0}getLead(){const{layoutId:u}=this.options;return u?this.getStack()?.lead||this:this}getPrevLead(){const{layoutId:u}=this.options;return u?this.getStack()?.prevLead:void 0}getStack(){const{layoutId:u}=this.options;if(u)return this.root.sharedNodes.get(u)}promote({needsReset:u,transition:f,preserveFollowOpacity:d}={}){this.getStack()?.promote(this,d),u&&(this.projectionDelta=void 0,this.needsReset=!0),f&&this.setOptions({transition:f})}relegate(){return this.getStack()?.relegate(this)||!1}resetSkewAndRotation(){const{visualElement:u}=this.options;if(!u)return;const{latestValues:f}=u;if(!JR(f))return;const d={};for(let m=0;mu.currentAnimation?.stop()),this.root.nodes.forEach(dS),this.root.sharedNodes.clear()}}}function Hj(e){e.updateLayout(),Xj(e)}function Fj(e){const t=e.resumeFrom?.snapshot||e.snapshot;if(e.isLead()&&e.layout&&t&&e.hasListeners("didUpdate")){const{layoutBox:i,measuredBox:a}=e.layout,{animationType:o}=e.options,c=t.source!==e.layout.source,u=(x,E)=>{if(o==="size")Oi(w=>{const R=Dr(x[w]);x[w].min=E[w].min,x[w].max=x[w].min+R});else if(o==="x"||o==="y"){const w=o==="x"?"y":"x";o0(x[w],E[w])}else fC(o,t.layoutBox,i)&&Oi(w=>{const R=Dr(E[w]);x[w].max=x[w].min+R,e.relativeTarget&&!e.currentAnimation&&(e.isProjectionDirty=!0,e.relativeTarget[w].max=e.relativeTarget[w].min+R)})},f=c?t.measuredBox:t.layoutBox;u(f,i);const d=Ko();Nd(d,i,t.layoutBox);const m=Ko();Nd(m,c?e.applyTransform(a,!0):i,f);const g=!sC(d);let v=!1;const S=e.getClosestProjectingParent();if((!c||S?.options.layoutRoot&&e.resumeFrom?.path.includes(S))&&S&&!S.resumeFrom){const{snapshot:x,layout:E}=S;if(x&&E){const w=e.options.layoutAnchor||void 0,R=Hn();Ld(R,c?e.resumeFrom.applyTransform(t.layoutBox,!0,void 0,!0,S.depth+1):t.layoutBox,x.layoutBox,w);const T=Hn();Ld(T,i,E.layoutBox,w),c&&u(R,T),oC(R,T)||(v=!0),S.options.layoutRoot&&(e.relativeTarget=T,e.relativeTargetOrigin=R,e.relativeParent=S)}}e.notifyListeners("didUpdate",{layout:i,snapshot:t,delta:m,layoutDelta:d,hasLayoutChanged:g,hasRelativeLayoutChanged:v})}else e.isLead()&&e.options.onExitComplete?.();e.options.transition=void 0}function Yj(e){e.parent&&(e.isProjecting()||(e.isProjectionDirty=e.parent.isProjectionDirty),e.isSharedProjectionDirty||(e.isSharedProjectionDirty=!!(e.isProjectionDirty||e.parent.isProjectionDirty||e.parent.isSharedProjectionDirty)),e.isTransformDirty||(e.isTransformDirty=e.parent.isTransformDirty))}function qj(e){e.isProjectionDirty=e.isSharedProjectionDirty=e.isTransformDirty=!1}function Gj(e){e.clearSnapshot()}function dS(e){e.clearMeasurements()}function Kj(e){e.isLayoutDirty=!0,e.updateLayout()}function hS(e){e.isLayoutDirty=!1}function Xj(e){const{snapshot:t,dragAncestor:i}=e,a=i?.isAnimationBlocked&&i.layout;if(!t||!a||e.resumeFrom||e.isAnimationBlocked)return;const o=i.dragSnapshot;Oi(c=>Ni(t.layoutBox[c],a.layoutBox[c].min-o.layoutBox[c].min))}function $j(e){e.isAnimationBlocked&&e.layout&&!e.isLayoutDirty&&(e.snapshot=e.dragSnapshot||e.layout,e.isLayoutDirty=!0)}function Wj(e){e.relativeTarget&&e.relativeParent?.isLayoutDirty&&(e.currentAnimation?e.isLayoutDirty=!0:(e.targetDelta=void 0,e.removeRelativeTarget()))}function Zj(e){const{visualElement:t}=e.options;t?.getProps().onBeforeLayoutMeasure&&t.notify("BeforeLayoutMeasure"),e.resetTransform()}function mS(e){e.finishAnimation(),e.targetDelta=e.relativeTarget=e.target=void 0,e.isProjectionDirty=!0}function Qj(e){e.resolveTargetDelta()}function Jj(e){e.calcProjection()}function e8(e){e.resetSkewAndRotation()}function pS(e,t,i){e.translate=rn(t.translate,0,i),e.scale=rn(t.scale,1,i),e.origin=t.origin,e.originPoint=t.originPoint}function gS(e,t,i,a){e.min=rn(t.min,i.min,a),e.max=rn(t.max,i.max,a)}function t8(e,t,i,a){gS(e.x,t.x,i.x,a),gS(e.y,t.y,i.y,a)}function n8(e){return e.animationValues?.opacityExit!==void 0}const r8={duration:.45,ease:[.4,0,.1,1]};function yS(e,t,i){e.max=Dr(i)+(e.min=t.min)}function fC(e,t,i){return e==="position"||e==="preserve-aspect"&&!Aj(oS(t),oS(i),.2)}function i8(e){return e!==e.root&&e.scroll?.wasRoot}function Js(e,t,i,a={passive:!0}){return e.addEventListener(t,i,a),()=>e.removeEventListener(t,i,a)}const a8=uC({attachResizeListener:(e,t)=>Js(e,"resize",t),measureScroll:mj,checkIsScrollRoot:()=>!0}),ud={current:void 0},dC=uC({measureScroll:e=>({x:e.scrollLeft,y:e.scrollTop}),defaultParent:()=>{if(!ud.current){const e=new a8({});e.mount(window),e.setOptions({layoutScroll:!0}),ud.current=e}return ud.current},resetTransform:(e,t)=>{e.style.transform=t!==void 0?t:"none"},checkIsScrollRoot:e=>window.getComputedStyle(e).position==="fixed"}),s8=new WeakMap;function ih(e){return e!==null&&typeof e=="object"&&typeof e.start=="function"}function Zc(e){return typeof e=="string"||Array.isArray(e)}const ah=["animate","whileInView","whileFocus","whileHover","whileTap","whileDrag","exit"],vS=["initial"].concat(ah);function sh(e){if(ih(e.animate))return!0;for(let t=0;tkd.current=e.matches;e.addEventListener("change",t),t()}else kd.current=!1}const bS=["AnimationStart","AnimationComplete","Update","BeforeLayoutMeasure","LayoutMeasure","LayoutAnimationStart","LayoutAnimationComplete"];let zd={};function pC(e){zd=e}function c8(){return zd}class u8{scrapeMotionValuesFromProps(t,i,a){return{}}constructor({parent:t,props:i,presenceContext:a,reducedMotionConfig:o,skipAnimations:c,blockInitialAnimation:u,visualState:f},d={}){this.current=null,this.children=new Set,this.isVariantNode=!1,this.isControllingVariants=!1,this.shouldReduceMotion=null,this.shouldSkipAnimations=!1,this.values=new Map,this.KeyframeResolver=oy,this.features={},this.valueSubscriptions=new Map,this.prevMotionValues={},this.hasBeenMounted=!1,this.events={},this.propEventSubscriptions={},this.notifyUpdate=()=>this.notify("Update",this.latestValues),this.render=()=>{this.current&&(this.triggerBuild(),this.renderInstance(this.current,this.renderState,this.props.style,this.projection))},this.renderScheduledAt=0,this.scheduleRender=()=>{const x=Ut.now();this.renderScheduledAto.delete(this)}}this.values.forEach((a,o)=>this.bindToMotionValue(o,a)),this.reducedMotionConfig==="never"?this.shouldReduceMotion=!1:this.reducedMotionConfig==="always"?this.shouldReduceMotion=!0:(by.current||mC(),this.shouldReduceMotion=kd.current),this.shouldSkipAnimations=this.skipAnimationsConfig??!1,this.parent?.addChild(this),this.update(this.props,this.presenceContext),this.hasBeenMounted=!0}unmount(){this.projection?.unmount(),Xr(this.notifyUpdate),Xr(this.render),this.valueSubscriptions.forEach(t=>t()),this.valueSubscriptions.clear(),this.removeFromVariantTree?.(),this.parent?.removeChild(this);for(const t in this.events)this.events[t].clear();for(const t in this.features){const i=this.features[t];i&&(i.unmount(),i.isMounted=!1)}this.current=null}addChild(t){this.children.add(t),(this.enteringChildren||(this.enteringChildren=new Set)).add(t)}removeChild(t){this.children.delete(t),this.enteringChildren?.delete(t)}bindToMotionValue(t,i){if(this.valueSubscriptions.get(t)?.(),i.accelerate&&e0.has(t)&&this.current instanceof HTMLElement){const{factory:u,keyframes:f,times:d,ease:m,duration:g}=i.accelerate,v=new PR({element:this.current,name:t,keyframes:f,times:d,ease:m,duration:Sr(g)}),S=u(v);this.valueSubscriptions.set(t,()=>{S(),v.cancel()});return}const a=fs.has(t);a&&this.onBindTransform&&this.onBindTransform();const o=i.on("change",u=>{this.latestValues[t]=u,this.props.onUpdate&&Xt.preRender(this.notifyUpdate),a&&(this.projection&&(this.projection.isTransformDirty=!0),ol.get(this.current)?.check()),this.scheduleRender()});let c;typeof window<"u"&&window.MotionCheckAppearSync&&(c=window.MotionCheckAppearSync(this,t,i)),this.valueSubscriptions.set(t,()=>{o(),c?.()})}sortNodePosition(t){return!this.current||!t.current||!this.sortInstanceNodePosition||this.type!==t.type?0:this.sortInstanceNodePosition(this.current,t.current)}updateFeatures(){let t="animation";for(t in zd){const i=zd[t];if(!i)continue;const{isEnabled:a,Feature:o}=i;if(!this.features[t]&&o&&a(this.props)&&(this.features[t]=new o(this)),this.features[t]){const c=this.features[t];c.isMounted?c.update():(c.mount(),c.isMounted=!0)}}}triggerBuild(){this.build(this.renderState,this.latestValues,this.props)}measureViewportBox(){return this.current?this.measureInstanceViewportBox(this.current,this.props):Hn()}getStaticValue(t){return this.latestValues[t]}setStaticValue(t,i){this.latestValues[t]=i}update(t,i){const{transformTemplate:a,onUpdate:o}=this.props;(t.transformTemplate||a)&&this.scheduleRender(),(t.transformTemplate&&!a||t.onUpdate&&!o)&&ol.get(this.current)?.demote(),this.prevProps=this.props,this.props=t,this.prevPresenceContext=this.presenceContext,this.presenceContext=i;for(let c=0;c{this.current&&(this.current.textContent=`${i}`)}))}}function yC(e,{style:t,vars:i},a,o){const c=e.style;let u;for(u in t)c[u]=t[u];o?.applyProjectionStyles(c,a);for(u in i)c.setProperty(u,i[u])}function vC(e,{layout:t,layoutId:i}){return fs.has(e)||e.startsWith("origin")||(t||i!==void 0)&&(!!jc[e]||e==="opacity")}function xy(e,t,i){const a=e.style,o=t?.style,c={};if(!a)return c;for(const u in a)(ar(a[u])||o&&ar(o[u])||vC(u,e)||i?.getValue(u)?.liveStyle!==void 0)&&(c[u]=a[u]);return c}function f8(e){return window.getComputedStyle(e)}class d8 extends gC{constructor(){super(...arguments),this.type="html",this.renderInstance=yC}mount(t){super.mount(t)}readValueFromInstance(t,i){if(fs.has(i))return this.projection?.isProjecting?$c(i):Z4(t,i);{const a=f8(t),o=(uR(i)?a.getPropertyValue(i):a[i])||0;return typeof o=="string"?o.trim():o}}measureInstanceViewportBox(t,{transformPagePoint:i}){return nC(t,i)}build(t,i,a){vy(t,i,a.transformTemplate)}scrapeMotionValuesFromProps(t,i,a){return xy(t,i,a)}}const Qc=e=>e.pointerType==="mouse"?typeof e.button!="number"||e.button<=0:e.isPrimary!==!1;function Sy(e){return{point:{x:e.pageX,y:e.pageY}}}const h8=e=>t=>Qc(t)&&e(t,Sy(t));function Pc(e,t,i,a){return Js(e,t,h8(i),a)}const fd=new WeakMap;let dd;const bC=(e,t,i)=>(a,o)=>o&&o[0]?o[0][e+"Size"]:py(a)&&"getBBox"in a?a.getBBox()[t]:a[i],m8=bC("inline","width","offsetWidth"),p8=bC("block","height","offsetHeight");function g8({target:e,borderBoxSize:t}){fd.get(e)?.forEach(i=>{i(e,{get width(){return m8(e,t)},get height(){return p8(e,t)}})})}function y8(e){e.forEach(g8)}function v8(){typeof ResizeObserver>"u"||(dd=new ResizeObserver(y8))}function b8(e,t){dd||v8();const i=XR(e);return i.forEach(a=>{let o=fd.get(a);o||(o=new Set,fd.set(a,o)),o.add(t),dd?.observe(a)}),()=>{i.forEach(a=>{const o=fd.get(a);o?.delete(t),o?.size||dd?.unobserve(a)})}}const hd=new Set;let Xo;function x8(){Xo=()=>{const e={get width(){return window.innerWidth},get height(){return window.innerHeight}};hd.forEach(t=>t(e))},window.addEventListener("resize",Xo)}function S8(e){return hd.add(e),Xo||x8(),()=>{hd.delete(e),!hd.size&&typeof Xo=="function"&&(window.removeEventListener("resize",Xo),Xo=void 0)}}function xS(e,t){return gy(typeof e=="function"?S8(e):b8(e,t))}const SS=(e,t)=>Math.abs(e-t);function w8(e,t){const i=SS(e.x,t.x),a=SS(e.y,t.y);return Math.sqrt(i**2+a**2)}const wS=new Set(["auto","scroll"]);class xC{constructor(t,i,{transformPagePoint:a,contextWindow:o=window,dragSnapToOrigin:c=!1,distanceThreshold:u=3,element:f,immediate:d}={}){if(this.startEvent=null,this.lastMoveEvent=null,this.lastMoveEventInfo=null,this.lastRawMoveEventInfo=null,this.handlers={},this.contextWindow=window,this.scrollPositions=new Map,this.onElementScroll=E=>{this.handleScroll(E.target)},this.onWindowScroll=()=>{this.handleScroll(window)},this.updatePoint=()=>{if(!(this.lastMoveEvent&&this.lastMoveEventInfo))return;this.hasPendingMove=!1,this.lastRawMoveEventInfo&&(this.lastMoveEventInfo=_f(this.lastRawMoveEventInfo,this.transformPagePoint));const E=eg(this.lastMoveEventInfo,this.history),w=this.startEvent!==null,R=w8(E.offset,{x:0,y:0})>=this.distanceThreshold;if(!w&&!R)return;const{point:T}=E;this.history.push({...T,timestamp:Ut.now()});const{onStart:O,onMove:N}=this.handlers;w||(O?.(this.lastMoveEvent,E),this.startEvent=this.lastMoveEvent),N?.(this.lastMoveEvent,E)},this.handlePointerMove=(E,w)=>{this.handleScroll(window),this.lastMoveEvent=E,this.lastRawMoveEventInfo=w,this.lastMoveEventInfo=_f(w,this.transformPagePoint),this.hasPendingMove=!0,Xt.update(this.updatePoint,!0)},this.handlePointerUp=(E,w)=>{this.hasPendingMove&&this.updatePoint(),this.end();const{onEnd:R,onSessionEnd:T,resumeAnimation:O}=this.handlers;if((this.dragSnapToOrigin||!this.startEvent)&&O?.(),!(this.lastMoveEvent&&this.lastMoveEventInfo))return;const N=eg(E.type==="pointercancel"?this.lastMoveEventInfo:_f(w,this.transformPagePoint),this.history);this.startEvent&&R?.(E,N),T?.(E,N)},!Qc(t))return;this.dragSnapToOrigin=c,this.handlers=i,this.transformPagePoint=a,this.distanceThreshold=d?0:u,this.contextWindow=o||window;const m=Sy(t),g=_f(m,this.transformPagePoint),{point:v}=g;this.history=[{...v,timestamp:Ut.now()}];const{onSessionStart:S}=i;S&&S(t,eg(g,this.history));const x={passive:!0,capture:!0};this.removeListeners=al(Pc(this.contextWindow,"pointermove",this.handlePointerMove,x),Pc(this.contextWindow,"pointerup",this.handlePointerUp,x),Pc(this.contextWindow,"pointercancel",this.handlePointerUp,x)),f&&this.startScrollTracking(f),d&&(this.handlePointerMove(t,m),this.updatePoint())}startScrollTracking(t){let i=t.parentElement;for(;i;){const a=getComputedStyle(i);(wS.has(a.overflowX)||wS.has(a.overflowY))&&this.scrollPositions.set(i,Jp(i)),i=i.parentElement}this.scrollPositions.set(window,Jp(window)),this.removeScrollListeners=al(Js(window,"scroll",this.onElementScroll,{capture:!0}),Js(window,"scroll",this.onWindowScroll,{}))}handleScroll(t){const i=this.scrollPositions.get(t);if(!i)return;const a=t===window,o=Jp(t),c={x:o.x-i.x,y:o.y-i.y};c.x===0&&c.y===0||(a?this.lastMoveEventInfo&&(this.lastMoveEventInfo.point.x+=c.x,this.lastMoveEventInfo.point.y+=c.y):this.history.length>0&&(this.history[0].x-=c.x,this.history[0].y-=c.y),this.scrollPositions.set(t,o),Xt.update(this.updatePoint,!0))}updateHandlers(t){this.handlers=t}end(){this.removeListeners?.(),this.removeScrollListeners?.(),this.scrollPositions.clear(),Xr(this.updatePoint)}}const Jp=e=>e===window?{x:window.scrollX,y:window.scrollY}:{x:e.scrollLeft,y:e.scrollTop};function _f(e,t){return t?{point:t(e.point)}:e}function ES(e,t){return{x:e.x-t.x,y:e.y-t.y}}function eg({point:e},t){return{point:e,delta:ES(e,SC(t)),offset:ES(e,E8(t)),velocity:R8(t,.1)}}function E8(e){return e[0]}function SC(e){return e[e.length-1]}function R8(e,t){if(e.length<2)return{x:0,y:0};let i=e.length-1,a=null;const o=SC(e);for(;i>=0&&(a=e[i],!(o.timestamp-a.timestamp>Sr(t)));)i--;if(!a)return{x:0,y:0};a===e[0]&&e.length>2&&o.timestamp-a.timestamp>Sr(t)*2&&(a=e[1]);const c=$r(o.timestamp-a.timestamp);if(c===0)return{x:0,y:0};const u={x:(o.x-a.x)/c,y:(o.y-a.y)/c};return u.x===1/0&&(u.x=0),u.y===1/0&&(u.y=0),u}const C8=new Set(["BUTTON","INPUT","SELECT","TEXTAREA","A"]);function T8(e){return C8.has(e.tagName)||e.isContentEditable===!0}const A8=new Set(["INPUT","SELECT","TEXTAREA"]);function M8(e){return A8.has(e.tagName)||e.isContentEditable===!0}const Mi={x:!1,y:!1};function Pd(){return Mi.x||Mi.y}function j8(e){return e==="x"||e==="y"?Mi[e]?null:(Mi[e]=!0,()=>{Mi[e]=!1}):Mi.x||Mi.y?null:(Mi.x=Mi.y=!0,()=>{Mi.x=Mi.y=!1})}function O8(e,{min:t,max:i},a){return t!==void 0&&ei&&(e=a?rn(i,e,a.max):Math.min(e,i)),e}function RS(e,t,i){return{min:t!==void 0?e.min+t:void 0,max:i!==void 0?e.max+i-(e.max-e.min):void 0}}function D8(e,{top:t,left:i,bottom:a,right:o}){return{x:RS(e.x,i,o),y:RS(e.y,t,a)}}function CS(e,t){let i=t.min-e.min,a=t.max-e.max;return t.max-t.mina?i=Qs(t.min,t.max-a,e.min):a>o&&(i=Qs(e.min,e.max-o,t.min)),ja(0,1,i)}function k8(e,t){const i={};return t.min!==void 0&&(i.min=t.min-e.min),t.max!==void 0&&(i.max=t.max-e.min),i}const l0=.35;function z8(e=l0){return e===!1?e=0:e===!0&&(e=l0),{x:TS(e,"left","right"),y:TS(e,"top","bottom")}}function TS(e,t,i){return{min:AS(e,t),max:AS(e,i)}}function AS(e,t){return typeof e=="number"?e:e[t]||0}function MS(e){let t="";for(const i of e.path){i.scroll=void 0,i.updateScroll();const{scroll:a}=i;i!==e.root&&a&&(t+=a.offset.x+","+a.offset.y+",")}return t}const P8=new WeakMap;class _8{constructor(t,i=()=>t.getProps()){this.openDragLock=null,this.isDragging=!1,this.currentDirection=null,this.originPoint={x:0,y:0},this.constraints=!1,this.hasMutatedConstraints=!1,this.elastic=Hn(),this.latestPointerEvent=null,this.latestPanInfo=null,this.visualElement=t,this.readProps=i}start(t,i={}){if(this.visualElement.presenceContext?.isPresent===!1)return;const a=m=>{i.snapToCursor&&this.snapToCursor(m),this.stopAnimation()},o=(m,g)=>{const{drag:v,dragConstraints:S,dragPropagation:x,onDragStart:E}=this.getProps();if(v&&!x&&(this.openDragLock?.(),this.openDragLock=j8(v),!this.openDragLock))return;this.latestPointerEvent=m,this.latestPanInfo=g,this.isDragging=!0,this.currentDirection=null,this.resolveConstraints();const{projection:w}=this.visualElement;w&&(w.isAnimationBlocked=!0,w.target=void 0),Oi(R=>{let T=this.getAxisMotionValue(R).get()||0;if(rh(T)&&(T=hy(T,this.visualElement.current)||0),Ve.test(T))T=parseFloat(T);else if(Zi.test(T)){const O=w?.layout?.layoutBox[R];O&&(T=Dr(O)*(parseFloat(T)/100))}this.originPoint[R]=T}),this.point=typeof S=="function"&&S(this),E&&Xt.update(()=>E(m,g),!1,!0),r0(this.visualElement,"transform"),this.visualElement.animationState?.setActive("whileDrag",!0)},c=(m,g)=>{this.latestPointerEvent=m,this.latestPanInfo=g;const{dragPropagation:v,dragDirectionLock:S,onDirectionLock:x,onDrag:E}=this.getProps();if(!v&&!this.openDragLock)return;const{offset:w}=g;if(S&&this.currentDirection===null){if(this.currentDirection=U8(w),this.currentDirection===null)return;x&&x(this.currentDirection)}this.updateAxis("x",w),this.updateAxis("y",w),this.point&&this.point.move(),this.visualElement.render(),E&&Xt.update(()=>E(m,g),!1,!0)},u=(m,g)=>{this.latestPointerEvent=m,this.latestPanInfo=g,this.stop(m,g),this.latestPointerEvent=null,this.latestPanInfo=null},f=()=>{const{dragSnapToOrigin:m}=this.getProps();(m||this.constraints||this.point)&&this.startAnimation({x:0,y:0})},{dragSnapToOrigin:d}=this.getProps();this.panSession=new xC(t,{onSessionStart:a,onStart:o,onMove:c,onSessionEnd:u,resumeAnimation:f},{...i,transformPagePoint:this.visualElement.getTransformPagePoint(),dragSnapToOrigin:d,contextWindow:this.visualElement.current?.ownerDocument.defaultView,element:this.visualElement.current})}stop(t,i,a){const o=t||this.latestPointerEvent,c=i||this.latestPanInfo,u=this.isDragging;if(this.cancel(),!u||!c||!o)return;const{velocity:f}=c;this.startAnimation(f,a);const{onDragEnd:d}=this.getProps();d&&Xt.postRender(()=>d(o,c))}cancel(){this.isDragging=!1;const{projection:t,animationState:i}=this.visualElement;t&&(t.isAnimationBlocked=!1),this.endPanSession(),!this.getProps().dragPropagation&&this.openDragLock&&(this.openDragLock(),this.openDragLock=null),i?.setActive("whileDrag",!1)}endPanSession(){this.panSession?.end(),this.panSession=void 0}updateAxis(t,i){const{drag:a}=this.readProps();if(!i||!Uo(t,a,this.currentDirection))return;const o=this.getAxisMotionValue(t);let c=this.originPoint[t]+i[t];const u=this.constraints&&this.constraints[t];u&&(c=O8(c,u,this.elastic[t])),this.point?this.point[t]=c:o.set(c)}resolveConstraints(){const{dragConstraints:t,dragElastic:i}=this.getProps(),{projection:a}=this.visualElement,o=a&&(a.layout||a.measure(!1)),c=this.constraints;pc(t)?(!this.constraints||this.scroll!==MS(a))&&(this.constraints=this.resolveRefConstraints()):t&&o&&typeof t=="object"?this.constraints=D8(o.layoutBox,t):this.constraints=!1,this.elastic=z8(i),c!==this.constraints&&!pc(t)&&o&&this.constraints&&!this.hasMutatedConstraints&&Oi(u=>{this.constraints!==!1&&this.getAxisMotionValue(u)&&(this.constraints[u]=k8(o.layoutBox[u],this.constraints[u]))})}resolveRefConstraints(){const{dragConstraints:t,onMeasureDragConstraints:i}=this.getProps();if(!pc(t))return!1;const a=jS(t),{projection:o}=this.visualElement;if(!o||!o.layout)return!1;this.scroll=MS(o);const c=hj(a,o.root,this.visualElement.getTransformPagePoint());let u=N8(o.layout.layoutBox,o.removeElementScroll(c));if(i){const f=i(uj(u));this.hasMutatedConstraints=!!f,f&&(u=QR(f))}return u}startAnimation(t,i){const{drag:a,dragMomentum:o,dragElastic:c,dragTransition:u,dragSnapToOrigin:f,onDragTransitionEnd:d}=this.getProps(),m={bounceStiffness:c?200:1e6,bounceDamping:c?40:1e7,timeConstant:750,restDelta:1,restSpeed:10,...u},g=x=>o&&!(this.point&&f)&&Uo(x,i||a,this.currentDirection)?t[x]:0;if(this.point&&!f)return this.point.release({x:g("x"),y:g("y")},m).then(d);const v=this.constraints||{},S=Oi(x=>{if(!Uo(x,i||a,this.currentDirection))return;let E=v[x]||{};(f===!0||f===x)&&(E={min:0,max:0});const w={type:"inertia",velocity:g(x),...m,...E};return this.startAxisValueAnimation(x,w)});return Promise.all(S).then(d)}startAxisValueAnimation(t,i){const a=this.getAxisMotionValue(t);return r0(this.visualElement,t),a.start(dy(t,a,0,i,this.visualElement,!1))}stopAnimation(){Oi(t=>this.getAxisMotionValue(t).stop())}getAxisMotionValue(t){const i=`_drag${t.toUpperCase()}`,o=this.readProps()[i];return o||this.visualElement.getValue(t,this.visualElement.latestValues[t]??0)}snapToCursor({clientX:t,clientY:i}){const{drag:a}=this.getProps(),o={x:t,y:i},c=this.visualElement.getTransformPagePoint()?.(o)||o,u=this.visualElement.measureViewportBox();Oi(f=>{if(!Uo(f,a,this.currentDirection))return;const d=this.getAxisMotionValue(f),{min:m,max:g}=u[f];d.set((d.get()||0)+c[f]-rn(m,g,.5))})}scalePositionWithinConstraints(){if(!this.visualElement.current)return;const{drag:t,dragConstraints:i}=this.getProps(),{projection:a}=this.visualElement;if(!pc(i)||!a||!this.constraints)return;this.stopAnimation();const o=this.constraints,c={x:0,y:0};Oi(f=>{const d=this.getAxisMotionValue(f).get();c[f]=L8({min:d,max:d},o[f])});const{transformTemplate:u}=this.visualElement.getProps();this.visualElement.current.style.transform=u?u({},""):"none",a.root?.updateScroll(),a.updateLayout(),this.constraints=!1,this.resolveConstraints(),Oi(f=>{const d=this.getAxisMotionValue(f);if(!Uo(f,t,null)||!d.get())return;const{min:m,max:g}=this.constraints[f];d.set(rn(m,g,c[f]))}),this.visualElement.render()}addListeners(){if(!this.visualElement.current)return;P8.set(this.visualElement,this);const t=this.visualElement.current,i=Pc(t,"pointerdown",m=>{const{drag:g,dragListener:v=!0}=this.getProps(),S=m.target,x=S!==t&&M8(S);g&&v&&!x&&this.start(m)});let a;const o=()=>{const{dragConstraints:m}=this.getProps(),g=pc(m)&&jS(m);g&&(this.constraints=this.resolveRefConstraints(),a||(a=V8(t,g,()=>this.scalePositionWithinConstraints())))},{projection:c}=this.visualElement,u=c.addEventListener("measure",o);c.layout||(c.root?.updateScroll(),c.updateLayout()),Xt.read(o);const f=Js(window,"resize",()=>this.scalePositionWithinConstraints()),d=c.addEventListener("didUpdate",(({delta:m,hasLayoutChanged:g})=>{this.isDragging&&g&&(Oi(v=>{if(!Uo(v,this.getProps().drag,this.currentDirection))return;const S=this.getAxisMotionValue(v);this.originPoint[v]+=m[v].translate,S.set(S.get()+m[v].translate)}),this.visualElement.render())}));return()=>{f(),i(),u(),d(),a?.()}}getProps(){const t=this.readProps(),{dragElastic:i=l0,dragMomentum:a=!0}=t;return{...t,dragElastic:i,dragMomentum:a}}}function pc(e){return!!e&&typeof e=="object"&&("current"in e||"nodeType"in e)}const jS=e=>"current"in e?e.current:e;function OS(e){let t=!0;return()=>{if(t){t=!1;return}e()}}function V8(e,t,i){const a=xS(e,OS(i)),o=xS(t,OS(i));return()=>{a(),o()}}function Uo(e,t,i){return(t===!0||t===e)&&(i===null||i===e)}function U8(e,t=10){let i=null;return Math.abs(e.y)>t?i="y":Math.abs(e.x)>t&&(i="x"),i}function wC(e,t){const i=XR(e),a=new AbortController,o={passive:!0,...t,signal:a.signal},c=gy(()=>a.abort());return[i,o,c]}function B8(e){return!(e.pointerType==="touch"||Pd())}function I8(e,t,i={}){t=yy(t);const[a,o,c]=wC(e,i);return a.forEach(u=>{let f=!1,d=!1,m;const g=()=>{u.removeEventListener("pointerleave",E)},v=R=>{m&&(m(R),m=void 0),g()},S=R=>{f=!1,window.removeEventListener("pointerup",S),window.removeEventListener("pointercancel",S),d&&(d=!1,v(R))},x=()=>{f=!0,window.addEventListener("pointerup",S,o),window.addEventListener("pointercancel",S,o)},E=R=>{if(R.pointerType!=="touch"){if(f){d=!0;return}v(R)}},w=R=>{if(!B8(R))return;d=!1;const T=t(u,R);typeof T=="function"&&(m=T,u.addEventListener("pointerleave",E,o))};u.addEventListener("pointerenter",w,o),u.addEventListener("pointerdown",x,o)}),c}const EC=(e,t)=>t?e===t?!0:EC(e,t.parentElement):!1,c0=new WeakSet;function DS(e){return t=>{t.key==="Enter"&&e(t)}}function tg(e,t){e.dispatchEvent(new PointerEvent("pointer"+t,{isPrimary:!0,bubbles:!0}))}const H8=(e,t)=>{let i=!1;const a=DS(()=>{i||c0.has(e)||(i=!0,tg(e,"down"))}),o=DS(()=>{i&&(i=!1,tg(e,"up"))});e.addEventListener("keydown",a,t),e.addEventListener("keyup",o,t),e.addEventListener("blur",()=>{e.removeEventListener("keydown",a),e.removeEventListener("keyup",o),i&&tg(e,"cancel")},{...t,once:!0})};function F8(e){return Qc(e)&&!Pd()}const NS=new WeakSet,Y8=100,q8=8,LS=(e,t,i)=>Math.hypot(e.clientX-t.clientX,e.clientY-t.clientY)>i,kS=e=>e.preventDefault();function G8(e,t,i={}){t=yy(t);const[a,o,c]=wC(e,i),u=new WeakMap,f=d=>{const m=d.currentTarget;if(!F8(d)||NS.has(d))return;i.stopPropagation&&NS.add(d);const{count:g=1,countTimeout:v=.3,hold:S=0,repeat:x}=i,E=Ut.now(),w=Sr(S),R=Sr(v);let T=u.get(m);T?.expire(LS(T.event,d,Y8))?T=void 0:T&&(Xr(T.expire),u.delete(m));const O=T?T.count+1:1,N=O>=g,j=N&&(S||x);let L=!S,P=0,D;if(c0.add(m),T)D=T.handlers;else{const Z=t(m,d);D=typeof Z=="function"?{onComplete:Z}:Z||{}}N&&L&&D.onActive?.();const A=Sr(x);let F=w||A,H=E+F,X=!0;const J=()=>{if(o.signal.aborted)return Xr(J);let Z=Math.min(1-(H-Ut.now())/F,1);X&&Z<1&&(Z=0),X=!1,D.onHold?.(Z),!(Z<1)&&(L?D.onRepeat?.(++P):(L=!0,D.onActive?.()),x?(X=!0,H+=F=A):Xr(J))},$={...o,capture:!0},ee=(Z,Y)=>{if(window.removeEventListener("pointerup",re,$),window.removeEventListener("pointercancel",V,$),window.removeEventListener("pointermove",K,$),m.removeEventListener("contextmenu",kS),Xr(J),c0.delete(m),!!Qc(Z))if(Pd()&&(Y=!1),Y&&!N){const _=Ut.now(),M=z=>{const B=o.signal.aborted;if(B||z===!0||Ut.now()-_>R)return Xr(M),u.delete(m),B||D.onComplete?.(Z,{success:!1}),!0};u.set(m,{count:O,event:d,handlers:D,expire:M}),Xt.update(M,!0)}else D.onComplete?.(Z,{success:Y&&L})},re=Z=>{ee(Z,m===window||m===document||i.useGlobalTarget||EC(m,Z.target))},V=Z=>{ee(Z,!1)},K=Z=>{Qc(Z)&&((x||!L)&&LS(d,Z,q8)||g>1&&Pd())&&V(Z)};window.addEventListener("pointerup",re,$),window.addEventListener("pointercancel",V,$),(j||g>1)&&window.addEventListener("pointermove",K,$),j&&(Xt.update(J,!0),m.addEventListener("contextmenu",kS,{...o,passive:!1}))};return a.forEach(d=>{(i.useGlobalTarget?window:d).addEventListener("pointerdown",f,o),sd(d)&&(d.addEventListener("focus",()=>H8(d,o),o),!T8(d)&&!d.hasAttribute("tabindex")&&(d.tabIndex=0))}),c}class bs{constructor(t){this.isMounted=!1,this.node=t}update(){}}const RC=new Set(["baseFrequency","diffuseConstant","kernelMatrix","kernelUnitLength","keySplines","keyTimes","limitingConeAngle","markerHeight","markerWidth","numOctaves","targetX","targetY","surfaceScale","specularConstant","specularExponent","stdDeviation","tableValues","viewBox","gradientTransform","pathLength","startOffset","textLength","lengthAdjust"]),CC=e=>typeof e=="string"&&e.toLowerCase()==="svg";function K8(e,t,i,a){yC(e,t,void 0,a);for(const o in t.attrs)e.setAttribute(RC.has(o)?o:$R(o),t.attrs[o])}function TC(e,t,i){const a=xy(e,t,i);for(const o in e)if(o!=="children"&&(ar(e[o])||ar(t[o]))){const c=Ta.indexOf(o)!==-1?"attr"+o.charAt(0).toUpperCase()+o.substring(1):o;a[c]=e[o]}return a}class X8 extends gC{constructor(){super(...arguments),this.type="svg",this.isSVGTag=!1,this.measureInstanceViewportBox=Hn}getBaseTargetFromProps(t,i){return fs.has(i)?super.getBaseTargetFromProps(t,i)??$c(i):t[i]}getDefaultValue(t){return fs.has(t)?this.latestValues[t]??$c(t):void 0}readValueFromInstance(t,i){if(fs.has(i)){const a=jR(i);return a&&a.default||0}if(WR.includes(i)){const o=getComputedStyle(t)[i];if(typeof o=="string"&&o)return o.trim()}return i=RC.has(i)?i:$R(i),t.getAttribute(i)}scrapeMotionValuesFromProps(t,i,a){return TC(t,i,a)}build(t,i,a){ZR(t,i,this.isSVGTag,a.transformTemplate,a.style)}renderInstance(t,i,a,o){K8(t,i,a,o)}mount(t){this.isSVGTag=CC(t.tagName),super.mount(t)}}function AC(e,t){if(!Array.isArray(t))return!1;const i=t.length;if(i!==e.length)return!1;for(let a=0;ae?.out===!0?e:e?.out;function W8(e){let t=f=>Promise.all(f.map(({animation:d,options:m})=>J6(e,d,m))),i=PS(),a=!0,o=!1;function c(f){const{props:d,parent:m,manuallyAnimateOnMount:g}=e,{initial:v}=d,S=a||o,x=[],E=(L=v)=>typeof L!="boolean"&&Ws(e,Array.isArray(L)?L[0]:L,e.presenceContext?.custom)||void 0,w=new Map;let R={},T=1/0,O=e;do O=O.props.inherit!==!1&&O.parent;while(O&&!O.isControllingVariants);const N=S&&zS(E(v??(O&&O.props.initial))?.transition);if($8.forEach((L,P)=>{const D=i[L],A=d[L],F=O&&O.props[L],H=A!==void 0?A:Zc(F)||F===!1?F:void 0,X=Zc(H),J=L===f?D.isActive:null,$=X&&A===void 0&&!(S&&g);if(D.protectedKeys={...R},!D.isActive&&J===null||!H&&!D.prevProp||ih(H)||typeof H=="boolean")return;if(J===!1&&(T=P),L==="exit"&&D.isActive&&J!==!0){R={...R,...D.prevResolvedValues};return}const ee=Z8(D.prevProp,H);let re=ee||X&&(J&&!$||P>T),V=!1;const K=Array.isArray(H)?H:[H];let Z={},Y;if(J!==!1)for(const M of K){const{transition:z,transitionEnd:B,...I}=Ws(e,M,FR(e,L))||{};Z={...Z,...I,...B},Y=zS(z)||Y}const{prevResolvedValues:_}=D;for(const M in{..._,...Z}){if(M in R)continue;const z=Z[M],B=_[M],I=Array.isArray(z)&&Array.isArray(B)?!AC(z,B)||ee:z!==B;let W;if(I&&z==null)w.has(M)||w.set(M,D.prevOut);else if(I||z!==void 0&&w.has(M)){re=!0,W=w.get(M)||N,w.delete(M)&&(V=!0),D.needsAnimating[M]=!0;const ie=e.getValue(M);ie&&(ie.liveStyle=!1)}else D.protectedKeys[M]=!0;D.out[M]=W}if(D.prevProp=H,D.prevResolvedValues=Z,D.prevOut=Y,D.isActive&&(R={...R,...Z}),re&&(!($&&ee)||V))for(const M of K){const z={type:L};if(typeof M=="string"&&S&&g&&m?.enteringChildren){const B=Ws(m,M)?.transition?.delayChildren;z.delay=IR(m.enteringChildren,e,B)}x.push({animation:M,options:z})}}),w.size){const L={},P=E();let D=P?.transition;w.forEach((A,F)=>{A&&(D={...D||e.getDefaultTransition(),[F]:A});const H=e.getValue(F);H&&(H.liveStyle=!0);const X=P&&!Array.isArray(v)?P[F]:void 0,J=e.getBaseTargetFromProps(d,F);L[F]=(X!==void 0?X:J!==void 0&&!ar(J)?J:e.initialValues[F]===void 0?e.baseTarget[F]:void 0)??null}),D&&(L.transition=D),x.push({animation:L})}const j=S&&e.blockInitialAnimation||a&&!g&&(d.initial===!1||d.initial===d.animate);return a=o=!1,!j&&x.length?t(x):Promise.resolve()}function u(f,d){if(i[f].isActive===d)return Promise.resolve();e.variantChildren?.forEach(g=>g.animationState?.setActive(f,d)),i[f].isActive=d;const m=c(f);for(const g in i)i[g].protectedKeys={};return m}return{animateChanges:c,setActive:u,setAnimateFunction:f=>{t=f(e)},getState:()=>i,reset:()=>{i=PS(),o=!0}}}function Z8(e,t){return typeof t=="string"?t!==e:Array.isArray(t)?!AC(t,e):!1}function PS(){const e={};for(const t of ah)e[t]={isActive:t==="animate",protectedKeys:{},needsAnimating:{},prevResolvedValues:{},out:{}};return e}const Jc=b.createContext({transformPagePoint:e=>e,isStatic:!1,reducedMotion:"never"});function _S(e,t){if(typeof e=="function")return e(t);e!=null&&(e.current=t)}function Q8(...e){return t=>{let i=!1;const a=e.map(o=>{const c=_S(o,t);return!i&&typeof c=="function"&&(i=!0),c});if(i)return()=>{for(let o=0;o{const{width:t,height:i}=e?.getBoundingClientRect()||{};return[t/e?.offsetWidth||1,i/e?.offsetHeight||1]},MC=e=>{let{left:t,top:i}=e.getBoundingClientRect(),a=e;for(;a=a.parentElement||a.parentNode?.host;){const{scrollLeft:u,scrollTop:f}=a;if(u||f){const[d,m]=VS(a);t+=u*d,i+=f*m}if(getComputedStyle(a).position==="fixed")break}const[o,c]=VS(e.offsetParent);return[t/o,i/c]};class eO extends b.Component{getSnapshotBeforeUpdate(t){const i=this.props.getElement();if(sd(i)&&t.isPresent&&!this.props.isPresent&&this.props.pop!==!1){const a=i.offsetParent,o=sd(a)&&a.offsetWidth||0,c=sd(a)&&a.offsetHeight||0,u=getComputedStyle(i),f=this.props.sizeRef.current;f.height=parseFloat(u.height),f.width=parseFloat(u.width),f.top=i.offsetTop,f.left=i.offsetLeft,f.right=o-f.width-f.left,f.bottom=c-f.height-f.top,f.direction=u.direction,f.point=MC(i)}return null}componentDidUpdate(){}render(){return this.props.children}}function tO({children:e,isPresent:t,anchorX:i,anchorY:a,root:o,pop:c,popNode:u}){const f=b.useId(),d=b.useRef(null),m=b.useRef({width:0,height:0,top:0,left:0,right:0,bottom:0,direction:"ltr"}),{nonce:g}=b.useContext(Jc),v=c!==!1?e.props?.ref??e?.ref:void 0,S=J8(d,v),x=()=>d.current||u?.current?.current,E=w=>{const{width:R,height:T,top:O,left:N,right:j,bottom:L,direction:P}=m.current,D=P==="rtl",A=i==="left"?D?`right:${j}`:`left:${N}`:D?`left:${N}`:`right:${j}`,F=a==="bottom"?`bottom:${L}`:`top:${O}`;w?.insertRule(`[data-motion-pop-id="${f}"]{position:absolute!important;width:${R}px!important;height:${T}px!important;${A}px!important;${F}px!important}`)};return b.useInsertionEffect(()=>{const{width:w,height:R}=m.current,T=x();if(t||c===!1||!T||!w||!R)return;T.dataset.motionPopId=f;const O=T.ownerDocument,N=O.createElement("style");g&&(N.nonce=g);const j=o??O.head;j.appendChild(N),E(N.sheet);let L=0,P=0;return Wc.setup(()=>{const[D,A]=MC(T);L=m.current.point[0]-D,P=m.current.point[1]-A}),Wc.read(()=>{const{sheet:D}=N;if(!D||!L&&!P)return;const A=m.current;A.left+=L,A.right-=L,A.top+=P,A.bottom-=P,D.deleteRule(0),E(D)}),()=>{T.removeAttribute("data-motion-pop-id"),j.contains(N)&&j.removeChild(N)}},[t]),y.jsx(eO,{isPresent:t,getElement:x,sizeRef:m,pop:c,children:c===!1?e:b.cloneElement(e,{ref:S})})}const nO=({children:e,initial:t,isPresent:i,onExitComplete:a,custom:o,presenceAffectsLayout:c,mode:u,anchorX:f,anchorY:d,root:m})=>{const g=gu(rO),v=b.useId(),S=b.useRef(),x=b.useRef(i),E=b.useRef(a);Fc(()=>{x.current=i,E.current=a});let w=!0,R=b.useMemo(()=>(w=!1,{id:v,initial:t,isPresent:i,custom:o,onExitComplete:T=>{g.set(T,!0);for(const O of g.values())if(!O)return;a&&a()},register:(T,O)=>(g.set(T,!1),O&&O.parent?.presenceContext?.id!==v&&(S.current=O),()=>{g.delete(T),!x.current&&!g.size&&E.current?.()})}),[i,g,a]);return c&&w&&(R={...R}),b.useMemo(()=>{g.forEach((T,O)=>g.set(O,!1))},[i]),b.useEffect(()=>{!i&&!g.size&&a&&a()},[i]),e=y.jsx(tO,{pop:u==="popLayout",isPresent:i,anchorX:f,anchorY:d,root:m,popNode:S,children:e}),y.jsx(nh.Provider,{value:R,children:e})};function rO(){return new Map}function jC(e=!0){const t=b.useContext(nh);if(t===null)return[!0,null];const{isPresent:i,onExitComplete:a,register:o}=t,c=b.useId();b.useEffect(()=>{if(e)return o(c)},[e]);const u=b.useCallback(()=>e&&a&&a(c),[c,a,e]);return!i&&a?[!1,u]:[!0]}const gc=e=>e.key||"";function US(e){const t=[];return b.Children.forEach(e,i=>{b.isValidElement(i)&&t.push(i)}),t}const OC=({children:e,custom:t,initial:i=!0,onExitComplete:a,presenceAffectsLayout:o=!0,mode:c="sync",propagate:u=!1,anchorX:f="left",anchorY:d="top",root:m})=>{const[g,v]=jC(u),S=b.useMemo(()=>US(e),[e]),x=u&&!g?[]:S.map(gc),E=b.useRef(!0),w=gu(()=>new Map),R=b.useRef(new Set),[T,O]=b.useState(S),[N,j]=b.useState(S);Fc(()=>{u&&!g&&!N.length&&v?.()},[g,u,N.length,v]);const L=b.useRef();b.useEffect(()=>()=>{const A=L.current;L.current=void 0,A?.()},[N]),Fc(()=>{E.current=!1;for(let A=0;Aw.get(gc(H)))?A=S:c==="wait"&&(A=P),j(US(A)),O(S),null}const{forceRender:D}=b.useContext(I0);return y.jsx(y.Fragment,{children:N.map(A=>{const F=gc(A),H=u&&!g?!1:S===N||x.includes(F),X=()=>{if(R.current.has(F))return;if(w.has(F))R.current.add(F),w.set(F,!0);else return;let J=!0;w.forEach($=>{$||(J=!1)}),J&&(D?.(),O([]),u&&v?.(),L.current=a)};return y.jsx(nO,{isPresent:H,initial:!E.current||i?void 0:!1,custom:t,presenceAffectsLayout:o,mode:c,root:m,onExitComplete:H?void 0:X,anchorX:f,anchorY:d,children:A},F)})})},DC=b.createContext({strict:!1}),BS={animation:["variants",...ah],exit:["exit"],drag:["drag","dragControls"],focus:["whileFocus"],hover:["whileHover","onHoverStart","onHoverEnd"],tap:["whileTap","onTap","onTapStart","onTapCancel"],pan:["onPan","onPanStart","onPanSessionStart","onPanEnd"],inView:["whileInView","onViewportEnter","onViewportLeave"],layout:["layout","layoutId"]};let IS=!1;function iO(){if(IS)return;const e={};for(const t in BS)e[t]={isEnabled:i=>BS[t].some(a=>!!i[a])};pC(e),IS=!0}function NC(){return iO(),c8()}function aO(e){const t=NC();for(const i in e)t[i]={...t[i],...e[i]};pC(t)}function sO({children:e,...t}){const i=b.useContext(Jc);t={...i,...t},t.transition=uy(t.transition,i.transition),t.isStatic=gu(()=>t.isStatic);const a=b.useMemo(()=>t,[JSON.stringify(t.transition),t.transformPagePoint,t.reducedMotion,t.skipAnimations,t.isValidProp]);return y.jsx(Jc.Provider,{value:a,children:e})}const oh=b.createContext({});function oO(e,t){if(sh(e)){const{initial:i,animate:a}=e;return{initial:i===!1||Zc(i)?i:void 0,animate:Zc(a)?a:void 0}}return e.inherit!==!1?t:{}}function lO(e){const{initial:t,animate:i}=oO(e,b.useContext(oh));return b.useMemo(()=>({initial:t,animate:i}),[HS(t),HS(i)])}function HS(e){return Array.isArray(e)?e.join(" "):e}const wy=()=>({style:{},transform:{},transformOrigin:{},vars:{}});function LC(e,t,i){for(const a in t)!ar(t[a])&&!vC(a,i)&&(e[a]=t[a])}function cO({transformTemplate:e},t){return b.useMemo(()=>{const i=wy();return vy(i,t,e),Object.assign({},i.vars,i.style)},[t])}function uO(e,t){const i=e.style||{},a={};return LC(a,i,e),Object.assign(a,cO(e,t)),a}function fO(e,t){const i={},a=uO(e,t);return e.drag&&e.dragListener!==!1&&(i.draggable=!1,a.userSelect=a.WebkitUserSelect=a.WebkitTouchCallout="none",a.touchAction=e.drag===!0?"none":`pan-${e.drag==="x"?"y":"x"}`),e.tabIndex===void 0&&(e.onTap||e.onTapStart||e.whileTap)&&(i.tabIndex=0),i.style=a,i}const kC=()=>({...wy(),attrs:{}});function dO(e,t,i,a){const o=b.useMemo(()=>{const c=kC();return ZR(c,t,CC(a),e.transformTemplate,e.style),{...c.attrs,style:{...c.style}}},[t]);if(e.style){const c={};return LC(c,e.style,e),{...o,style:{...c,...o.style}}}return o}const hO=new Set(["animate","exit","variants","initial","style","values","transition","transformTemplate","custom","inherit","onBeforeLayoutMeasure","onAnimationStart","onAnimationComplete","onUpdate","onDragStart","onDrag","onDragEnd","onMeasureDragConstraints","onDirectionLock","onDragTransitionEnd","_dragX","_dragY","onHoverStart","onHoverEnd","onViewportEnter","onViewportLeave","globalTapTarget","tap","propagate","ignoreStrict","viewport"]);function _d(e){return e.startsWith("while")||e.startsWith("drag")&&e!=="draggable"||e.startsWith("layout")||e.startsWith("onTap")||e.startsWith("onPan")||e.startsWith("onLayout")||hO.has(e)}function mO(e,t){return e.startsWith("on")?!_d(e):t?.(e)??!_d(e)}function pO(e,t,i,a){const o={};for(const c in e)c==="values"&&typeof e.values=="object"||ar(e[c])||(mO(c,a)||i===!0&&_d(c)||!t&&!_d(c)||e.draggable&&c.startsWith("onDrag"))&&(o[c]=e[c]);return o}const gO=["animate","circle","defs","desc","ellipse","g","image","line","filter","marker","mask","metadata","path","pattern","polygon","polyline","rect","stop","switch","symbol","svg","text","tspan","use","view"];function Ey(e){return typeof e!="string"||e.includes("-")?!1:!!(gO.indexOf(e)>-1||/[A-Z]/u.test(e))}function yO(e,t,i,{latestValues:a},o,c=!1,u,f){const m=(u??Ey(e)?dO:fO)(t,a,o,e),g=pO(t,typeof e=="string",c,f),v=e!==b.Fragment?{...g,...m,ref:i}:{},{children:S}=t,x=b.useMemo(()=>ar(S)?S.get():S,[S]);return b.createElement(e,{...v,children:x})}function vO({scrapeMotionValuesFromProps:e,createRenderState:t},i,a,o){return{latestValues:bO(i,a,o,e),renderState:t()}}function bO(e,t,i,a){const o={},c=a(e,{});for(const S in c)o[S]=ld(c[S]);let{initial:u,animate:f}=e;const d=sh(e),m=hC(e);t&&m&&!d&&e.inherit!==!1&&(u===void 0&&(u=t.initial),f===void 0&&(f=t.animate));let g=i?i.initial===!1:!1;g=g||u===!1;const v=g?f:u;if(v&&typeof v!="boolean"&&!ih(v)){const S=Array.isArray(v)?v:[v];for(let x=0;x(t,i)=>{const a=b.useContext(oh),o=b.useContext(nh),c=()=>vO(e,t,a,o);return i?c():gu(c)},xO=zC({scrapeMotionValuesFromProps:xy,createRenderState:wy}),SO=zC({scrapeMotionValuesFromProps:TC,createRenderState:kC}),wO=Symbol.for("motionComponentSymbol");function EO(e,t,i){const a=b.useRef(i);b.useInsertionEffect(()=>{a.current=i});const o=b.useRef(null);return b.useCallback(c=>{c&&e.onMount?.(c),t&&(c?t.mount(c):t.unmount());const u=a.current;if(typeof u=="function")if(c){const f=u(c);typeof f=="function"&&(o.current=f)}else o.current?(o.current(),o.current=null):u(c);else u&&(u.current=c)},[t])}const PC=b.createContext({});function RO(e,t,i,a,o,c){const{visualElement:u}=b.useContext(oh),f=b.useContext(DC),d=b.useContext(nh),m=b.useContext(Jc),g=m.reducedMotion,v=m.skipAnimations,S=b.useRef(null),x=b.useRef(!1);a=a||f.renderer,!S.current&&a&&(S.current=a(e,{visualState:t,parent:u,props:i,presenceContext:d,blockInitialAnimation:d?d.initial===!1:!1,reducedMotionConfig:g,skipAnimations:v,isSVG:c}),x.current&&S.current&&(S.current.manuallyAnimateOnMount=!0));const E=S.current,w=b.useContext(PC);E&&!E.projection&&o&&(E.type==="html"||E.type==="svg")&&o.create(E,i,w),b.useInsertionEffect(()=>{E&&E.props!==i&&E.update(i,d)});const R=i[qR],T=b.useRef(!!R&&typeof window<"u"&&!window.MotionHandoffIsComplete?.(R)&&window.MotionHasOptimisedAnimation?.(R));return Fc(()=>{!x.current||!E||(E.animationState?.animateChanges(),E.enteringChildren=void 0)},[]),Fc(()=>{x.current=!0,E&&(window.MotionIsMounted=!0,E.updateFeatures(),E.scheduleRenderMicrotask(),T.current&&E.animationState&&E.animationState.animateChanges())}),b.useEffect(()=>{E&&(!T.current&&E.animationState&&E.animationState.animateChanges(),T.current&&(queueMicrotask(()=>{window.MotionHandoffMarkAsComplete?.(R)}),T.current=!1),E.enteringChildren=void 0)}),E}function ng(e,{forwardMotionProps:t=!1,type:i}={},a,o){a&&aO(a);const c=i?i==="svg":Ey(e),u=c?SO:xO;function f(m,g){let v;const S=CO(m);gu(()=>!!ud.current?.sharedNodes.get(S)?.lead&&m.initial)&&(m={...m,initial:!1});const x={...b.useContext(Jc),...m,layoutId:S},{isStatic:E,isValidProp:w}=x,R=lO(m),T=u(m,E);if(!E&&typeof window<"u"){TO();const O=AO(x);R.visualElement=RO(e,T,x,o,O.ProjectionNode,c),(O.isEnabled||R.visualElement?.projection?.options.layoutId)&&(v=O.MeasureLayout)}return y.jsxs(oh.Provider,{value:R,children:[v&&R.visualElement?y.jsx(v,{visualElement:R.visualElement,...x}):null,yO(e,m,EO(T,R.visualElement,g),T,E,t,c,w)]})}f.displayName=`motion.${typeof e=="string"?e:`create(${e.displayName??e.name??""})`}`;const d=b.forwardRef(f);return d[wO]=e,d}function CO({layoutId:e}){const t=b.useContext(I0).id;return t&&e!==void 0?t+"-"+e:e}function TO(e,t){b.useContext(DC).strict}function AO(e){const t=NC(),{drag:i,layout:a}=t;if(!i&&!a)return{};const o={...i,...a};return{MeasureLayout:o.MeasureLayout,isEnabled:i?.isEnabled(e)||a?.isEnabled(e),ProjectionNode:o.ProjectionNode}}function MO(e,t){if(typeof Proxy>"u")return ng;const i=new Map,a=(c,u)=>ng(c,u,e,t),o=(c,u)=>a(c,u);return new Proxy(o,{get:(c,u)=>u==="create"?a:(i.has(u)||i.set(u,ng(u,void 0,e,t)),i.get(u))})}const jO=(e,t)=>t.isSVG??Ey(e)?new X8(t):new d8(t,{allowProjection:e!==b.Fragment});class OO extends bs{constructor(t){super(t),t.animationState||(t.animationState=W8(t))}updateAnimationControlsSubscription(){const{animate:t}=this.node.getProps();ih(t)&&(this.unmountControls=t.subscribe(this.node))}mount(){this.updateAnimationControlsSubscription()}update(){this.node.getProps().animate!==this.node.prevProps?.animate&&this.updateAnimationControlsSubscription()}unmount(){this.node.animationState.reset(),this.unmountControls?.()}}let DO=0;class NO extends bs{constructor(){super(...arguments),this.id=DO++}update(){const{presenceContext:t,animationState:i}=this.node;if(!t||!i)return;const{isPresent:a,onExitComplete:o}=t;if(a===!this.exit)return;if(a){if(this.exit===!0){const{initial:u}=this.node.getProps();if(u&&!Array.isArray(u)){const{transition:f,transitionEnd:d,...m}=Ws(this.node,u)||{};for(const g in m)this.node.getValue(g)?.jump(m[g])}this.node.blockInitialAnimation=!1,i.reset(),i.animateChanges()}else i.setActive("exit",!1);this.exit=void 0;return}const c=this.exit=i.setActive("exit",!0);o&&c.then(()=>{this.exit===c&&(this.exit=!0,o(this.id))})}mount(){const{register:t}=this.node.presenceContext||{};t&&(this.unmount=t(this.id,this.node)),this.update()}unmount(){}}const LO={animation:{Feature:OO},exit:{Feature:NO}};class kO extends bs{constructor(t){super(t),this.removeGroupControls=Li,this.removeListeners=Li,this.controls=new _8(t)}mount(){const{dragControls:t}=this.node.getProps();t&&(this.removeGroupControls=t.subscribe(this.controls)),this.removeListeners=this.controls.addListeners()||Li}update(){const{dragControls:t,drag:i}=this.node.getProps(),{dragControls:a,drag:o}=this.node.prevProps||{};t!==a&&(this.removeGroupControls(),t&&(this.removeGroupControls=t.subscribe(this.controls))),o&&!i&&this.controls.stop(void 0,void 0,o)}unmount(){this.removeGroupControls(),this.removeListeners(),this.controls.isDragging||this.controls.endPanSession()}}const rg=e=>(t,i)=>{e&&Xt.update(()=>e(t,i),!1,!0)};class zO extends bs{constructor(){super(...arguments),this.removePointerDownListener=Li}onPointerDown(t){this.session=new xC(t,this.createPanHandlers(),{transformPagePoint:this.node.getTransformPagePoint(),contextWindow:this.node.current?.ownerDocument.defaultView})}createPanHandlers(){const{onPanSessionStart:t,onPanStart:i,onPan:a,onPanEnd:o}=this.node.getProps();return{onSessionStart:rg(t),onStart:rg(i),onMove:rg(a),onEnd:(c,u)=>{delete this.session,o&&Xt.postRender(()=>o(c,u))}}}mount(){this.removePointerDownListener=Pc(this.node.current,"pointerdown",t=>this.onPointerDown(t))}update(){this.session?.updateHandlers(this.createPanHandlers())}unmount(){this.removePointerDownListener(),this.session?.end()}}let ig=!1;const FS=({layout:e,layoutDependency:t,layoutAnchor:i})=>({layout:e,layoutDependency:t,layoutAnchor:i,animationType:typeof e=="string"?e:"both"}),YS=(e,t)=>{const{snapshot:i}=e,a=e.getStack();a?.remove(e);const o=a?.lead;if(a?.prevLead===e&&o.resumeFrom===e&&(o.resumeFrom=o.currentAnimation=e.resumingFrom=void 0),e.options.layoutId=t,!t){e.needsShow=!0;return}return e.root.registerSharedNode(t,e),()=>{const{resumeFrom:c}=e;c?.isPresent!==!1&&e.getStack().members.includes(c)&&(c.hide(),e.resumeFrom=void 0,e.snapshot=i)}};class PO extends b.Component{componentDidMount(){const{visualElement:t,layoutGroup:i,switchLayoutGroup:a,layoutId:o}=this.props,{projection:c}=t;c&&(i.group?.add(c),o&&a?.register?.(c),ig&&c.root.didUpdate(),c.options.layoutId!==o&&YS(c,o)?.(),c.addEventListener("animationComplete",()=>this.safeToRemove()),c.setOptions({...c.options,...FS(this.props),onExitComplete:()=>this.safeToRemove()})),cd.hasEverUpdated=!0}getSnapshotBeforeUpdate(t){const{layoutDependency:i,layoutId:a,visualElement:o,drag:c,isPresent:u}=this.props,{projection:f}=o;return f&&(f.isPresent=u,this.takeOver=t.layoutId!==a?(f.willUpdate(),YS(f,a)):void 0,f.setOptions({...f.options,...FS(this.props)}),ig=!0,c||t.layoutDependency!==i||i===void 0||t.isPresent!==u?f.willUpdate():this.safeToRemove(),t.isPresent!==u&&(u?f.promote():f.relegate()||Xt.postRender(()=>{f.getStack()?.members.length||this.safeToRemove()}))),null}componentDidUpdate(){const{projection:t}=this.props.visualElement;t&&(this.takeOver?.(),t.root.didUpdate(),Wc.postRender(()=>{!t.currentAnimation&&t.isLead()&&this.safeToRemove()}))}componentWillUnmount(){const{visualElement:t,layoutGroup:i,switchLayoutGroup:a}=this.props,{projection:o}=t;ig=!0,o&&(o.scheduleCheckAfterUnmount(),i.group?.remove(o),a?.deregister?.(o))}safeToRemove(){this.props.safeToRemove?.()}render(){return null}}function _C(e){const[t,i]=jC(),a=b.useContext(I0);return y.jsx(PO,{...e,layoutGroup:a,switchLayoutGroup:b.useContext(PC),isPresent:t,safeToRemove:i})}const _O={pan:{Feature:zO},drag:{Feature:kO,ProjectionNode:dC,MeasureLayout:_C}};function u0(e,t,i,a,o){const{props:c}=e,u="while"+i;!o&&e.animationState&&c[u]&&e.animationState.setActive(u,a==="Start");const f=c["on"+i+a];f&&Xt.postRender(()=>f(t,Sy(t)))}class VO extends bs{mount(){const{current:t}=this.node;t&&(this.unmount=I8(t,(i,a)=>(u0(this.node,a,"Hover","Start"),o=>u0(this.node,o,"Hover","End"))))}unmount(){}}class UO extends bs{constructor(){super(...arguments),this.isActive=!1}onFocus(){let t=!1;try{t=this.node.current.matches(":focus-visible")}catch{t=!0}!t||!this.node.animationState||(this.node.animationState.setActive("whileFocus",!0),this.isActive=!0)}onBlur(){!this.isActive||!this.node.animationState||(this.node.animationState.setActive("whileFocus",!1),this.isActive=!1)}mount(){this.unmount=al(Js(this.node.current,"focus",()=>this.onFocus()),Js(this.node.current,"blur",()=>this.onBlur()))}unmount(){}}function ag(e,t,i,a){e.current instanceof HTMLButtonElement&&e.current.disabled||u0(e,t,"Tap",i,a)}class BO extends bs{constructor(){super(...arguments),this.options={}}mount(){const{current:t}=this.node;t&&(this.update(),this.unmount=G8(t,(i,a)=>(ag(this.node,a,"Start"),{onComplete:(o,{success:c})=>ag(this.node,o,c?"":"Cancel"),onRepeat:()=>ag(this.node,a,"",!0)}),this.options))}update(){const{options:t,node:i}=this,{globalTapTarget:a,propagate:o,tap:c}=i.props;for(const u in t)delete t[u];Object.assign(t,c,{useGlobalTarget:a,stopPropagation:o?.tap===!1})}unmount(){}}const f0=new WeakMap,sg=new WeakMap,IO=e=>{const t=f0.get(e.target);t&&t(e)},HO=e=>{e.forEach(IO)};function FO({root:e,...t}){const i=e||document;sg.has(i)||sg.set(i,{});const a=sg.get(i),o=JSON.stringify(t);return a[o]||(a[o]=new IntersectionObserver(HO,{root:e,...t})),a[o]}function YO(e,t,i){const a=FO(t);return f0.set(e,i),a.observe(e),()=>{f0.delete(e),a.unobserve(e)}}const qO={some:0,all:1};class GO extends bs{constructor(){super(...arguments),this.hasEnteredView=!1,this.isInView=!1}startObserver(){this.stopObserver?.();const{viewport:t={}}=this.node.getProps(),{root:i,margin:a,amount:o="some",once:c}=t,u={root:i?i.current:void 0,rootMargin:a,threshold:typeof o=="number"?o:qO[o]},f=d=>{const{isIntersecting:m}=d;if(this.isInView===m||(this.isInView=m,c&&!m&&this.hasEnteredView))return;m&&(this.hasEnteredView=!0),this.node.animationState&&this.node.animationState.setActive("whileInView",m);const{onViewportEnter:g,onViewportLeave:v}=this.node.getProps(),S=m?g:v;S&&S(d)};this.stopObserver=YO(this.node.current,u,f)}mount(){this.startObserver()}update(){if(typeof IntersectionObserver>"u")return;const{props:t,prevProps:i}=this.node;["amount","margin","root"].some(KO(t,i))&&this.startObserver()}unmount(){this.stopObserver?.(),this.hasEnteredView=!1,this.isInView=!1}}function KO({viewport:e={}},{viewport:t={}}={}){return i=>e[i]!==t[i]}const XO={inView:{Feature:GO},tap:{Feature:BO},focus:{Feature:UO},hover:{Feature:VO}},$O={layout:{ProjectionNode:dC,MeasureLayout:_C}},WO=Object.assign({},LO,XO,_O,$O),ZO=MO(WO,jO);function QO(){!by.current&&mC();const[e]=b.useState(kd.current);return e}const Vd=ZO;var VC=e=>{throw TypeError(e)},UC=(e,t,i)=>t.has(e)||VC("Cannot "+i),fi=(e,t,i)=>(UC(e,t,"read from private field"),i?i.call(e):t.get(e)),Oc=(e,t,i)=>t.has(e)?VC("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,i),Yi=(e,t,i,a)=>(UC(e,t,"write to private field"),t.set(e,i),i),lh=/^(?:[a-z][a-z0-9+.-]*:|[\\/]{2})/i,ch=/^[\\/]{2}/;function BC(e,t){return t+e.replace(/\\/g,"/")}var qS="popstate";function GS(e){return typeof e=="object"&&e!=null&&"pathname"in e&&"search"in e&&"hash"in e&&"state"in e&&"key"in e}function JO(e={}){function t(a,o){let c=o.state?.masked,{pathname:u,search:f,hash:d}=c||a.location;return eu("",{pathname:u,search:f,hash:d},o.state&&o.state.usr||null,o.state&&o.state.key||"default",c?{pathname:a.location.pathname,search:a.location.search,hash:a.location.hash}:void 0)}function i(a,o){return typeof o=="string"?o:wr(o)}return tD(t,i,null,e)}function pt(e,t){if(e===!1||e===null||typeof e>"u")throw new Error(t)}function wn(e,t){if(!e){typeof console<"u"&&console.warn(t);try{throw new Error(t)}catch{}}}function eD(){return Math.random().toString(36).substring(2,10)}function KS(e,t){return{usr:e.state,key:e.key,idx:t,masked:e.mask?{pathname:e.pathname,search:e.search,hash:e.hash}:void 0}}function eu(e,t,i=null,a,o){return{pathname:typeof e=="string"?e:e.pathname,search:"",hash:"",...typeof t=="string"?ea(t):t,state:i,key:t&&t.key||a||eD(),mask:o}}function wr({pathname:e="/",search:t="",hash:i=""}){return t&&t!=="?"&&(e+=t.charAt(0)==="?"?t:"?"+t),i&&i!=="#"&&(e+=i.charAt(0)==="#"?i:"#"+i),e}function ea(e){let t={};if(e){let i=e.indexOf("#");i>=0&&(t.hash=e.substring(i),e=e.substring(0,i));let a=e.indexOf("?");a>=0&&(t.search=e.substring(a),e=e.substring(0,a)),e&&(t.pathname=e)}return t}function tD(e,t,i,a={}){let{window:o=document.defaultView,v5Compat:c=!1}=a,u=o.history,f="POP",d=null,m=g();m==null&&(m=0,u.replaceState({...u.state,idx:m},""));function g(){return(u.state||{idx:null}).idx}function v(){f="POP";let R=g(),T=R==null?null:R-m;m=R,d&&d({action:f,location:w.location,delta:T})}function S(R,T){f="PUSH";let O=GS(R)?R:eu(w.location,R,T);m=g()+1;let N=KS(O,m),j=w.createHref(O.mask||O);try{u.pushState(N,"",j)}catch(L){if(L instanceof DOMException&&L.name==="DataCloneError")throw L;o.location.assign(j)}c&&d&&d({action:f,location:w.location,delta:1})}function x(R,T){f="REPLACE";let O=GS(R)?R:eu(w.location,R,T);m=g();let N=KS(O,m),j=w.createHref(O.mask||O);u.replaceState(N,"",j),c&&d&&d({action:f,location:w.location,delta:0})}function E(R){return IC(o,R)}let w={get action(){return f},get location(){return e(o,u)},listen(R){if(d)throw new Error("A history only accepts one active listener");return o.addEventListener(qS,v),d=R,()=>{o.removeEventListener(qS,v),d=null}},createHref(R){return t(o,R)},createURL:E,encodeLocation(R){let T=E(R);return{pathname:T.pathname,search:T.search,hash:T.hash}},push:S,replace:x,go(R){return u.go(R)}};return w}function IC(e,t,i=!1){let a="http://localhost";e&&(a=e.location.origin!=="null"?e.location.origin:e.location.href),pt(a,"No window.location.(origin|href) available to create URL");let o=typeof t=="string"?t:wr(t);return o=o.replace(/ $/,"%20"),!i&&ch.test(o)&&(o=a+o),new URL(o,a)}var Dc,XS=class{constructor(e){if(Oc(this,Dc,new Map),e)for(let[t,i]of e)this.set(t,i)}get(e){if(fi(this,Dc).has(e))return fi(this,Dc).get(e);if(e.defaultValue!==void 0)return e.defaultValue;throw new Error("No value found for context")}set(e,t){fi(this,Dc).set(e,t)}};Dc=new WeakMap;var nD=new Set(["lazy","caseSensitive","path","id","index","children"]);function rD(e){return nD.has(e)}var iD=new Set(["lazy","caseSensitive","path","id","index","middleware","children"]);function aD(e){return iD.has(e)}function sD(e){return e.index===!0}function tu(e,t,i=[],a={},o=!1){return e.map((c,u)=>{let f=[...i,String(u)],d=typeof c.id=="string"?c.id:f.join("-");if(pt(c.index!==!0||!c.children,"Cannot specify children on an index route"),pt(o||!a[d],`Found a route id collision on id "${d}". Route id's must be globally unique within Data Router usages`),sD(c)){let m={...c,id:d};return a[d]=$S(m,t(m)),m}else{let m={...c,id:d,children:void 0};return a[d]=$S(m,t(m)),c.children&&(m.children=tu(c.children,t,f,a,o)),m}})}function $S(e,t){return Object.assign(e,{...t,...typeof t.lazy=="object"&&t.lazy!=null?{lazy:{...e.lazy,...t.lazy}}:{}})}function HC(e,t,i="/"){return ji(e,t,i,!1)}function ji(e,t,i,a,o){let c=typeof t=="string"?ea(t):t,u=yi(c.pathname||"/",i);if(u==null)return null;let f=o??md(e),d=null,m=vD(u);for(let g=0;d==null&&g{let g={relativePath:m===void 0?u.path||"":m,caseSensitive:u.caseSensitive===!0,childrenIndex:f,route:u};if(g.relativePath.startsWith("/")){if(!g.relativePath.startsWith(a)&&d)return;pt(g.relativePath.startsWith(a),`Absolute route path "${g.relativePath}" nested under path "${a}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),g.relativePath=g.relativePath.slice(a.length)}let v=pi([a,g.relativePath]),S=i.concat(g);u.children&&u.children.length>0&&(pt(u.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${v}".`),FC(u.children,t,S,v,d)),!(u.path==null&&!u.index)&&t.push({path:v,score:pD(v,u.index),routesMeta:S.map((x,E)=>{let[w,R]=GC(x.relativePath,x.caseSensitive,E===S.length-1);return{...x,matcher:w,compiledParams:R}})})};return e.forEach((u,f)=>{if(u.path===""||!u.path?.includes("?"))c(u,f);else for(let d of YC(u.path))c(u,f,!0,d)}),t}function YC(e){let t=e.split("/");if(t.length===0)return[];let[i,...a]=t,o=i.endsWith("?"),c=i.replace(/\?$/,"");if(a.length===0)return o?[c,""]:[c];let u=YC(a.join("/")),f=[];return f.push(...u.map(d=>d===""?c:[c,d].join("/"))),o&&f.push(...u),f.map(d=>e.startsWith("/")&&d===""?"/":d)}function lD(e){e.sort((t,i)=>t.score!==i.score?i.score-t.score:gD(t.routesMeta.map(a=>a.childrenIndex),i.routesMeta.map(a=>a.childrenIndex)))}var cD=/^:[\w-]+$/,uD=3,fD=2,dD=1,hD=10,mD=-2,WS=e=>e==="*";function pD(e,t){let i=e.split("/"),a=i.length;return i.some(WS)&&(a+=mD),t&&(a+=fD),i.filter(o=>!WS(o)).reduce((o,c)=>o+(cD.test(c)?uD:c===""?dD:hD),a)}function gD(e,t){return e.length===t.length&&e.slice(0,-1).every((a,o)=>a===t[o])?e[e.length-1]-t[t.length-1]:0}function yD(e,t,i=!1){let{routesMeta:a}=e,o={},c="/",u=[];for(let f=0;f{if(g==="*"){let E=f[S]||"";u=ul(c.slice(0,c.length-E.length),1)}const x=f[S];return v&&!x?m[g]=void 0:m[g]=(x||"").replace(/%2F/g,"/"),m},{}),pathname:c,pathnameBase:u,pattern:e}}function GC(e,t=!1,i=!0){wn(e==="*"||!e.endsWith("*")||e.endsWith("/*"),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,"/*")}".`);let a=[],o="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(u,f,d,m,g)=>{if(a.push({paramName:f,isOptional:d!=null}),d){let v=g.charAt(m+u.length);return v&&v!=="/"?"/([^\\/]*)":"(?:/([^\\/]*))?"}return"/([^\\/]+)"}).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return e.endsWith("*")?(a.push({paramName:"*"}),o+=e==="*"||e==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):i?o+="\\/*$":e!==""&&e!=="/"&&(o+="(?:(?=\\/|$))"),[new RegExp(o,t?void 0:"i"),a]}function vD(e){try{return e.split("/").map(t=>decodeURIComponent(t).replace(/\//g,"%2F")).join("/")}catch(t){return wn(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function yi(e,t){if(t==="/")return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let i=t.endsWith("/")?t.length-1:t.length,a=e.charAt(i);return a&&a!=="/"?null:e.slice(i)||"/"}function bD({basename:e,pathname:t}){return t==="/"?e:pi([e,t])}var Ry=e=>lh.test(e);function xD(e,t="/"){let{pathname:i,search:a="",hash:o=""}=typeof e=="string"?ea(e):e,c;return i?(i=Cy(i),i.startsWith("/")||i.startsWith("\\")?c=ZS(i.substring(1),"/"):c=ZS(i,t)):c=t,{pathname:c,search:wD(a),hash:ED(o)}}function ZS(e,t){let i=ul(t).split("/");return e.split("/").forEach(o=>{o===".."?i.length>1&&i.pop():o!=="."&&i.push(o)}),i.length>1?i.join("/"):"/"}function og(e,t,i,a){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(a)}]. Please separate it out to the \`to.${i}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function KC(e){return e.filter((t,i)=>i===0||t.route.path&&t.route.path.length>0)}function uh(e){let t=KC(e);return t.map((i,a)=>a===t.length-1?i.pathname:i.pathnameBase)}function bu(e,t,i,a=!1){let o;typeof e=="string"?o=ea(e):(o={...e},pt(!o.pathname||!o.pathname.includes("?"),og("?","pathname","search",o)),pt(!o.pathname||!o.pathname.includes("#"),og("#","pathname","hash",o)),pt(!o.search||!o.search.includes("#"),og("#","search","hash",o)));let c=e===""||o.pathname==="",u=c?"/":o.pathname,f;if(u==null)f=i;else{let v=t.length-1;if(!a&&u.startsWith("..")){let S=u.split("/");for(;S[0]==="..";)S.shift(),v-=1;o.pathname=S.join("/")}f=v>=0?t[v]:"/"}let d=xD(o,f),m=u&&u!=="/"&&u.endsWith("/"),g=(c||u===".")&&i.endsWith("/");return!d.pathname.endsWith("/")&&(m||g)&&(d.pathname+="/"),d}var Cy=e=>e.replace(/[\\/]{2,}/g,"/"),pi=e=>Cy(e.join("/"));function ul(e,t=0){let i=e.length;for(;i>t&&e.charCodeAt(i-1)===47;)i--;return i===e.length?e:e.slice(0,i)}var SD=e=>ul(e).replace(/^\/*/,"/"),wD=e=>!e||e==="?"?"":e.startsWith("?")?e:"?"+e,ED=e=>!e||e==="#"?"":e.startsWith("#")?e:"#"+e,RD=["EvalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],xu=class{constructor(e,t,i,a=!1){this.status=e,this.statusText=t||"",this.internal=a,i instanceof Error?(this.data=i.toString(),this.error=i):this.data=i}};function nu(e){return e!=null&&typeof e.status=="number"&&typeof e.statusText=="string"&&typeof e.internal=="boolean"&&"data"in e}function Su(e){let t=e.map(i=>i.route.path).filter(Boolean);return pi(t)||"/"}var XC=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function $C(e,t){let i=e;if(typeof i!="string"||!lh.test(i))return{absoluteURL:void 0,isExternal:!1,to:i};let a=i,o=!1;if(XC)try{let c=new URL(window.location.href),u=ch.test(i)?new URL(BC(i,c.protocol)):new URL(i),f=yi(u.pathname,t);u.origin===c.origin&&f!=null?i=f+u.search+u.hash:o=!0}catch{wn(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:a,isExternal:o,to:i}}var ls=Symbol("Uninstrumented");function CD(e,t){let i={lazy:[],"lazy.loader":[],"lazy.action":[],"lazy.middleware":[],middleware:[],loader:[],action:[]};e.forEach(o=>o({id:t.id,index:t.index,path:t.path,instrument(c){let u=Object.keys(i);for(let f of u)c[f]&&i[f].push(c[f])}}));let a={};if(typeof t.lazy=="function"&&i.lazy.length>0){let o=$o(i.lazy,t.lazy,()=>{});o&&(a.lazy=o)}if(typeof t.lazy=="object"){let o=t.lazy;["middleware","loader","action"].forEach(c=>{let u=o[c],f=i[`lazy.${c}`];if(typeof u=="function"&&f.length>0){let d=$o(f,u,()=>{});d&&(a.lazy=Object.assign(a.lazy||{},{[c]:d}))}})}return["loader","action"].forEach(o=>{let c=t[o];if(typeof c=="function"&&i[o].length>0){let u=c[ls]??c,f=$o(i[o],u,(...d)=>QS(d[0]));f&&(o==="loader"&&u.hydrate===!0&&(f.hydrate=!0),f[ls]=u,a[o]=f)}}),t.middleware&&t.middleware.length>0&&i.middleware.length>0&&(a.middleware=t.middleware.map(o=>{let c=o[ls]??o,u=$o(i.middleware,c,(...f)=>QS(f[0]));return u?(u[ls]=c,u):o})),a}function TD(e,t){let i={navigate:[],fetch:[]};if(t.forEach(a=>a({instrument(o){let c=Object.keys(o);for(let u of c)o[u]&&i[u].push(o[u])}})),i.navigate.length>0){let a=e.navigate[ls]??e.navigate,o=$o(i.navigate,a,(...c)=>{let[u,f]=c;return{to:typeof u=="number"||typeof u=="string"?u:u?wr(u):".",...JS(e,f??{})}});o&&(o[ls]=a,e.navigate=o)}if(i.fetch.length>0){let a=e.fetch[ls]??e.fetch,o=$o(i.fetch,a,(...c)=>{let[u,,f,d]=c;return{href:f??".",fetcherKey:u,...JS(e,d??{})}});o&&(o[ls]=a,e.fetch=o)}return e}function $o(e,t,i){return e.length===0?null:async(...a)=>{let o=await WC(e,i(...a),()=>t(...a),e.length-1);if(o.type==="error")throw o.value;return o.value}}async function WC(e,t,i,a){let o=e[a],c;if(o){let u,f=async()=>(u?console.error("You cannot call instrumented handlers more than once"):u=WC(e,t,i,a-1),c=await u,pt(c,"Expected a result"),c.type==="error"&&c.value instanceof Error?{status:"error",error:c.value}:{status:"success",error:void 0});try{await o(f,t)}catch(d){console.error("An instrumentation function threw an error:",d)}u||await f(),await u}else try{c={type:"success",value:await i()}}catch(u){c={type:"error",value:u}}return c||{type:"error",value:new Error("No result assigned in instrumentation chain.")}}function QS(e){let{request:t,context:i,params:a,pattern:o}=e;return{request:AD(t),params:{...a},pattern:o,context:MD(i)}}function JS(e,t){return{currentUrl:wr(e.state.location),..."formMethod"in t?{formMethod:t.formMethod}:{},..."formEncType"in t?{formEncType:t.formEncType}:{},..."formData"in t?{formData:t.formData}:{},..."body"in t?{body:t.body}:{}}}function AD(e){return{method:e.method,url:e.url,headers:{get:(...t)=>e.headers.get(...t)}}}function MD(e){if(OD(e)){let t={...e};return Object.freeze(t),t}else return{get:t=>e.get(t)}}var jD=Object.getOwnPropertyNames(Object.prototype).sort().join("\0");function OD(e){if(e===null||typeof e!="object")return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||t===null||Object.getOwnPropertyNames(t).sort().join("\0")===jD}var ew=new URL("http://localhost");function Ty(e){if(e.createURL)return e.createURL("/");try{return new URL(e.createHref("/"),ew)}catch{return ew}}function lg(e,t){return e.origin===t.origin&&(e.origin!=="null"||e.protocol===t.protocol&&e.host===t.host)}function DD(e,t){if(e.startsWith("//"))return!0;let i=t.protocol.toLowerCase();return e.toLowerCase().startsWith(i)?t.host===""||e.slice(i.length).startsWith("//"):!1}function Qo(e,t,i,a){let o=null;try{o=e==null?null:new URL(e,i)}catch{}let c=new URL(t,i),u=o!=null&&!lg(o,i),f=!lg(c,i);if(a==="reject"){if(u||f)throw new Error("External navigation is not allowed")}else if(f&&(o==null||!DD(e,o)||!lg(o,c)))throw new Error("External navigation is not allowed")}var ZC=["POST","PUT","PATCH","DELETE"],ND=new Set(ZC),LD=["GET",...ZC],kD=new Set(LD),QC=new Set([301,302,303,307,308]),zD=new Set([307,308]),cg={state:"idle",location:void 0,matches:void 0,historyAction:void 0,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0},PD={state:"idle",data:void 0,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0},yc={state:"unblocked",proceed:void 0,reset:void 0,location:void 0},_D=e=>({hasErrorBoundary:!!e.hasErrorBoundary}),JC="remix-router-transitions",eT=Symbol("ResetLoaderData"),Ys,Bo,ss,Io,VD=class{constructor(e){Oc(this,Ys),Oc(this,Bo),Oc(this,ss),Oc(this,Io),Yi(this,Ys,e),Yi(this,Bo,md(e))}get stableRoutes(){return fi(this,Ys)}get activeRoutes(){return fi(this,ss)??fi(this,Ys)}get branches(){return fi(this,Io)??fi(this,Bo)}get hasHMRRoutes(){return fi(this,ss)!=null}setRoutes(e){Yi(this,Ys,e),Yi(this,Bo,md(e))}setHmrRoutes(e){Yi(this,ss,e),Yi(this,Io,md(e))}commitHmrRoutes(){fi(this,ss)&&(Yi(this,Ys,fi(this,ss)),Yi(this,Bo,fi(this,Io)),Yi(this,ss,void 0),Yi(this,Io,void 0))}};Ys=new WeakMap;Bo=new WeakMap;ss=new WeakMap;Io=new WeakMap;function UD(e){const t=e.window?e.window:typeof window<"u"?window:void 0,i=typeof t<"u"&&typeof t.document<"u"&&typeof t.document.createElement<"u";pt(e.routes.length>0,"You must provide a non-empty routes array to createRouter");let a=e.hydrationRouteProperties||[],o=e.mapRouteProperties||_D,c=o;if(e.instrumentations){let U=e.instrumentations;c=G=>({...o(G),...CD(U.map(te=>te.route).filter(Boolean),G)})}let u={},f=new VD(tu(e.routes,c,void 0,u)),d=e.basename||"/";d.startsWith("/")||(d=`/${d}`);let m=e.dataStrategy||YD,g={...e.future},v=null,S=new Set,x=null,E=null,w=null,R=null,T=e.hydrationData!=null,O=ji(f.activeRoutes,e.history.location,d,!1,f.branches),N=!1,j=null,L,P;if(O==null&&!e.patchRoutesOnNavigation){let U=di(404,{pathname:e.history.location.pathname}),{matches:G,route:te}=Vf(f.activeRoutes);L=!0,P=!L,O=G,j={[te.id]:U}}else if(O&&!e.hydrationData&&Jt(O,f.activeRoutes,e.history.location.pathname).active&&(O=null),O)if(O.some(U=>U.route.lazy))L=!1,P=!L;else if(!O.some(U=>Ay(U.route)))L=!0,P=!L;else{let U=e.hydrationData?e.hydrationData.loaderData:null,G=e.hydrationData?e.hydrationData.errors:null,te=O;if(G){let he=O.findIndex(ge=>G[ge.route.id]!==void 0);te=te.slice(0,he+1)}P=!1,L=!0,te.forEach(he=>{let ge=tT(he.route,U,G);P=P||ge.renderFallback,L=L&&!ge.shouldLoad})}else{L=!1,P=!L,O=[];let U=Jt(null,f.activeRoutes,e.history.location.pathname);U.active&&U.matches&&(N=!0,O=U.matches)}let D,A={historyAction:e.history.action,location:e.history.location,matches:O,initialized:L,renderFallback:P,navigation:cg,restoreScrollPosition:e.hydrationData!=null?!1:null,preventScrollReset:!1,revalidation:"idle",loaderData:e.hydrationData&&e.hydrationData.loaderData||{},actionData:e.hydrationData&&e.hydrationData.actionData||null,errors:e.hydrationData&&e.hydrationData.errors||j,fetchers:new Map,blockers:new Map},F="POP",H=null,X=!1,J,$=!1,ee=new Map,re=null,V=!1,K=!1,Z=new Set,Y=new Map,_=0,M=-1,z=new Map,B=new Set,I=new Map,W=new Map,ie=new Set,fe=new Map,pe,ce=null;function Ae(){if(v=e.history.listen(({action:U,location:G,delta:te})=>{if(pe){pe(),pe=void 0;return}wn(fe.size===0||te!=null,"You are trying to use a blocker on a POP navigation to a location that was not created by @remix-run/router. This will fail silently in production. This can happen if you are navigating outside the router via `window.history.pushState`/`window.location.hash` instead of using router navigation APIs. This can also happen if you are using createHashRouter and the user manually changes the URL.");let he=un({currentLocation:A.location,nextLocation:G,historyAction:U});if(he&&te!=null){let ge=new Promise(Le=>{pe=Le});e.history.go(te*-1),Rt(he,{state:"blocked",location:G,proceed(){Rt(he,{state:"proceeding",proceed:void 0,reset:void 0,location:G}),ge.then(()=>e.history.go(te))},reset(){let Le=new Map(A.blockers);Le.set(he,yc),Re({blockers:Le})}}),H?.resolve(),H=null;return}return Qe(U,G)}),i){cN(t,ee);let U=()=>uN(t,ee);t.addEventListener("pagehide",U),re=()=>t.removeEventListener("pagehide",U)}return A.initialized||Qe("POP",A.location,{initialHydration:!0}),D}function ke(){v&&v(),re&&re(),S.clear(),J&&J.abort(),A.fetchers.forEach((U,G)=>Ot(A.fetchers,G)),A.blockers.forEach((U,G)=>bn(G))}function we(U){if(S.add(U),x){let{newErrors:G}=x;x=null,U(A,{deletedFetchers:[],newErrors:G,viewTransitionOpts:void 0,flushSync:!1})}return()=>S.delete(U)}function Re(U,G={}){U.matches&&(U.matches=U.matches.map(ge=>{let Le=u[ge.route.id],Ce=ge.route;return Ce.element!==Le.element||Ce.errorElement!==Le.errorElement||Ce.hydrateFallbackElement!==Le.hydrateFallbackElement?{...ge,route:Le}:ge})),A={...A,...U};let te=[],he=[];A.fetchers.forEach((ge,Le)=>{ge.state==="idle"&&(ie.has(Le)?te.push(Le):he.push(Le))}),ie.forEach(ge=>{!A.fetchers.has(ge)&&!Y.has(ge)&&te.push(ge)}),S.size===0&&(x={newErrors:U.errors??null}),[...S].forEach(ge=>ge(A,{deletedFetchers:te,newErrors:U.errors??null,viewTransitionOpts:G.viewTransitionOpts,flushSync:G.flushSync===!0})),te.forEach(ge=>Ot(A.fetchers,ge)),he.forEach(ge=>A.fetchers.delete(ge))}function ye(U,G,{flushSync:te}={}){let he=A.actionData!=null&&A.navigation.formMethod!=null&&cr(A.navigation.formMethod)&&A.navigation.state==="loading"&&U.state?._isRedirect!==!0,ge;G.actionData?Object.keys(G.actionData).length>0?ge=G.actionData:ge=null:he?ge=A.actionData:ge=null;let Le=G.loaderData?uw(A.loaderData,G.loaderData,G.matches||[],G.errors):A.loaderData,Ce=A.blockers;Ce.size>0&&(Ce=new Map(Ce),Ce.forEach((Pe,tt)=>Ce.set(tt,yc)));let je=V?!1:sn(U,G.matches||A.matches),De=X===!0||A.navigation.formMethod!=null&&cr(A.navigation.formMethod)&&U.state?._isRedirect!==!0;f.commitHmrRoutes(),V||F==="POP"||(F==="PUSH"?e.history.push(U,U.state):F==="REPLACE"&&e.history.replace(U,U.state));let Ie;if(F==="POP"&&!V&&U!==A.location){let Pe=ee.get(A.location.pathname);Pe&&Pe.has(U.pathname)?Ie={currentLocation:A.location,nextLocation:U}:ee.has(U.pathname)&&(Ie={currentLocation:U,nextLocation:A.location})}else if($){let Pe=ee.get(A.location.pathname);Pe?Pe.add(U.pathname):(Pe=new Set([U.pathname]),ee.set(A.location.pathname,Pe)),Ie={currentLocation:A.location,nextLocation:U}}Re({...G,actionData:ge,loaderData:Le,historyAction:F,location:U,initialized:!0,renderFallback:!1,navigation:cg,revalidation:"idle",restoreScrollPosition:je,preventScrollReset:De,blockers:Ce},{viewTransitionOpts:Ie,flushSync:te===!0}),F="POP",X=!1,$=!1,V=!1,K=!1,H?.resolve(),H=null,ce?.resolve(),ce=null}async function ze(U,G){if(H?.resolve(),H=null,typeof U=="number"){H||(H=mw());let mt=H.promise;return e.history.go(U),mt}let te=d0(A.location,A.matches,d,U,G?.fromRouteId,G?.relative),{path:he,submission:ge,error:Le}=tw(!1,te,G),Ce;if(G?.mask){let mt=typeof G.mask=="string"?ea(G.mask):{...A.location.mask,...G.mask};if(Ce={pathname:mt.pathname??"",search:mt.search??"",hash:mt.hash??""},ch.test(Ce.pathname))throw new Error("External navigation is not allowed");Ce.pathname.startsWith("\\")&&(Ce.pathname=Ce.pathname.replace(/^\\+/,"/")),Qo(typeof G.mask=="string"?G.mask:wr(G.mask),wr(Ce),e.history.createURL("/"),"reject")}let je=A.location,De=eu(je,he,G&&G.state,void 0,Ce);De={...De,...e.history.encodeLocation(De)},Qo(U==null?e.history.createHref(A.location):typeof U=="string"?U:wr(U),e.history.createHref(De.mask||De),e.history.createURL("/"),"reject");let Ie=G&&G.replace!=null?G.replace:void 0,Pe="PUSH";Ie===!0?Pe="REPLACE":Ie===!1||ge!=null&&cr(ge.formMethod)&&ge.formAction===A.location.pathname+A.location.search&&(Pe="REPLACE");let tt=G&&"preventScrollReset"in G?G.preventScrollReset===!0:void 0,Ke=(G&&G.flushSync)===!0,ut=un({currentLocation:je,nextLocation:De,historyAction:Pe});if(ut){Rt(ut,{state:"blocked",location:De,proceed(){Rt(ut,{state:"proceeding",proceed:void 0,reset:void 0,location:De}),ze(U,G)},reset(){let mt=new Map(A.blockers);mt.set(ut,yc),Re({blockers:mt})}});return}await Qe(Pe,De,{submission:ge,pendingError:Le,preventScrollReset:tt,replace:G&&G.replace,enableViewTransition:G&&G.viewTransition,flushSync:Ke,callSiteDefaultShouldRevalidate:G&&G.defaultShouldRevalidate})}function Ye(){ce||(ce=mw()),Te(),Re({revalidation:"loading"});let U=ce.promise;return A.navigation.state==="submitting"?U:A.navigation.state==="idle"?(Qe(A.historyAction,A.location,{startUninterruptedRevalidation:!0}),U):(Qe(F||A.historyAction,A.navigation.location,{overrideNavigation:A.navigation,enableViewTransition:$===!0}),U)}async function Qe(U,G,te){J&&J.abort(),J=null,F=U,V=(te&&te.startUninterruptedRevalidation)===!0,ct(A.location,A.matches),X=(te&&te.preventScrollReset)===!0,$=(te&&te.enableViewTransition)===!0;let he=f.activeRoutes,ge=te?.initialHydration&&A.matches&&A.matches.length>0&&!N?A.matches:ji(he,G,d,!1,f.branches),Le=(te&&te.flushSync)===!0;if(ge&&A.initialized&&!K&&JD(A.location,G)&&!(te&&te.submission&&cr(te.submission.formMethod))){ye(G,{matches:ge},{flushSync:Le});return}let Ce=Jt(ge,he,G.pathname);if(Ce.active&&Ce.matches&&(ge=Ce.matches),!ge){let{error:ft,notFoundMatches:dt,route:Ht}=kt(G.pathname);ye(G,{matches:dt,loaderData:{},errors:{[Ht.id]:ft}},{flushSync:Le});return}let je=te&&te.overrideNavigation?{...te.overrideNavigation,matches:ge,historyAction:U}:void 0;J=new AbortController;let De=Ho(e.history,G,J.signal,te&&te.submission),Ie=e.getContext?await e.getContext():new XS,Pe;if(te&&te.pendingError)Pe=[os(ge).route.id,{type:"error",error:te.pendingError}];else if(te&&te.submission&&cr(te.submission.formMethod)){let ft=await nt(De,G,te.submission,ge,U,Ie,Ce.active,te&&te.initialHydration===!0,{replace:te.replace,flushSync:Le});if(ft.shortCircuited)return;if(ft.pendingActionResult){let[dt,Ht]=ft.pendingActionResult;if(Kr(Ht)&&nu(Ht.error)&&Ht.error.status===404){J=null,ye(G,{matches:ft.matches,loaderData:{},errors:{[dt]:Ht.error}});return}}ge=ft.matches||ge,Pe=ft.pendingActionResult,je=ug(G,ge,U,te.submission),Le=!1,Ce.active=!1,De=Ho(e.history,De.url,De.signal)}let{shortCircuited:tt,matches:Ke,loaderData:ut,errors:mt,workingFetchers:It}=await Ne(De,G,ge,U,Ie,Ce.active,je,te&&te.submission,te&&te.fetcherSubmission,te&&te.replace,te&&te.initialHydration===!0,Le,Pe,te&&te.callSiteDefaultShouldRevalidate);tt||(J=null,ye(G,{matches:Ke||ge,...fw(Pe),loaderData:ut,errors:mt,...It?{fetchers:It}:{}}))}async function nt(U,G,te,he,ge,Le,Ce,je,De={}){Te();let Ie=oN(G,he,ge,te);if(Re({navigation:Ie},{flushSync:De.flushSync===!0}),Ce){let Ke=await _t(he,G.pathname,U.signal);if(Ke.type==="aborted")return{shortCircuited:!0};if(Ke.type==="error"){if(Ke.partialMatches.length===0){let{matches:mt,route:It}=Vf(f.activeRoutes);return{matches:mt,pendingActionResult:[It.id,{type:"error",error:Ke.error}]}}let ut=os(Ke.partialMatches).route.id;return{matches:Ke.partialMatches,pendingActionResult:[ut,{type:"error",error:Ke.error}]}}else if(Ke.matches)he=Ke.matches;else{let{notFoundMatches:ut,error:mt,route:It}=kt(G.pathname);return{matches:ut,pendingActionResult:[It.id,{type:"error",error:mt}]}}}let Pe,tt=pd(he,G);if(!tt.route.action&&!tt.route.lazy)Pe={type:"error",error:di(405,{method:U.method,pathname:G.pathname,routeId:tt.route.id})};else{let Ke=Jo(c,u,U,G,he,tt,je?[]:a,Le),ut=await be(U,G,Ke,Le,null);if(Pe=ut[tt.route.id],!Pe){for(let mt of he)if(ut[mt.route.id]){Pe=ut[mt.route.id];break}}if(U.signal.aborted)return{shortCircuited:!0}}if(Xs(Pe)){let Ke;return De&&De.replace!=null?Ke=De.replace:Ke=ow(Pe.response.headers.get("Location"),new URL(U.url),d,e.history)===A.location.pathname+A.location.search,await ue(U,Pe,!0,{submission:te,replace:Ke}),{shortCircuited:!0}}if(Kr(Pe)){let Ke=os(he,tt.route.id);return(De&&De.replace)!==!0&&(F="PUSH"),{matches:he,pendingActionResult:[Ke.route.id,Pe,tt.route.id]}}return{matches:he,pendingActionResult:[tt.route.id,Pe]}}async function Ne(U,G,te,he,ge,Le,Ce,je,De,Ie,Pe,tt,Ke,ut){let mt=Ce||ug(G,te,he,je),It=je||De||hw(mt),ft=!V&&!Pe;if(Le){if(ft){let qt=Xe(Ke);Re({navigation:mt,...qt!==void 0?{actionData:qt}:{}},{flushSync:tt})}let rt=await _t(te,G.pathname,U.signal);if(rt.type==="aborted")return{shortCircuited:!0};if(rt.type==="error"){if(rt.partialMatches.length===0){let{matches:Zn,route:ei}=Vf(f.activeRoutes);return{matches:Zn,loaderData:{},errors:{[ei.id]:rt.error}}}let qt=os(rt.partialMatches).route.id;return{matches:rt.partialMatches,loaderData:{},errors:{[qt]:rt.error}}}else if(rt.matches)te=rt.matches;else{let{error:qt,notFoundMatches:Zn,route:ei}=kt(G.pathname);return{matches:Zn,loaderData:{},errors:{[ei.id]:qt}}}}let dt=f.activeRoutes,{dsMatches:Ht,revalidatingFetchers:st}=nw(U,ge,c,u,e.history,A,te,It,G,Pe?[]:a,Pe===!0,K,Z,ie,I,B,dt,d,e.patchRoutesOnNavigation!=null,f.branches,Ke,ut);if(M=++_,!e.dataStrategy&&!Ht.some(rt=>rt.shouldLoad)&&!Ht.some(rt=>rt.route.middleware&&rt.route.middleware.length>0)&&st.length===0){let rt=new Map(A.fetchers),qt=mn(rt);return ye(G,{matches:te,loaderData:{},errors:Ke&&Kr(Ke[1])?{[Ke[0]]:Ke[1].error}:null,...fw(Ke),...qt?{fetchers:rt}:{}},{flushSync:tt}),{shortCircuited:!0}}if(ft){let rt={};if(!Le){rt.navigation=mt;let qt=Xe(Ke);qt!==void 0&&(rt.actionData=qt)}st.length>0&&(rt.fetchers=Me(st)),Re(rt,{flushSync:tt})}st.forEach(rt=>{Ft(rt.key),rt.controller&&Y.set(rt.key,rt.controller)});let Nr=()=>st.forEach(rt=>Ft(rt.key));J&&J.signal.addEventListener("abort",Nr);let{loaderResults:pn,fetcherResults:On}=await $e(Ht,st,U,G,ge);if(U.signal.aborted)return{shortCircuited:!0};J&&J.signal.removeEventListener("abort",Nr),st.forEach(rt=>Y.delete(rt.key));let Xn=Uf(pn);if(Xn)return await ue(U,Xn.result,!0,{replace:Ie}),{shortCircuited:!0};if(Xn=Uf(On),Xn)return B.add(Xn.key),await ue(U,Xn.result,!0,{replace:Ie}),{shortCircuited:!0};let _n=new Map(A.fetchers),{loaderData:ra,errors:or}=cw(A,te,pn,Ke,st,On,_n);Pe&&A.errors&&(or={...A.errors,...or});let Si=mn(_n),dr=qn(M,_n),wi=Si||dr||st.length>0;return{matches:te,loaderData:ra,errors:or,...wi?{workingFetchers:_n}:{}}}function Xe(U){if(U&&!Kr(U[1]))return{[U[0]]:U[1].data};if(A.actionData)return Object.keys(A.actionData).length===0?null:A.actionData}function Me(U){let G=new Map(A.fetchers);return U.forEach(te=>{let he=G.get(te.key),ge=vc(void 0,he?he.data:void 0);G.set(te.key,ge)}),G}async function et(U,G,te,he){Ft(U);let ge=(he&&he.flushSync)===!0,Le=f.activeRoutes,Ce=d0(A.location,A.matches,d,te,G,he?.relative),je=ji(Le,Ce,d,!1,f.branches),De=Jt(je,Le,Ce);if(De.active&&De.matches&&(je=De.matches),!je){bt(U,G,di(404,{pathname:Ce}),{flushSync:ge});return}let{path:Ie,submission:Pe,error:tt}=tw(!0,Ce,he);if(tt){bt(U,G,tt,{flushSync:ge});return}let Ke=e.getContext?await e.getContext():new XS,ut=(he&&he.preventScrollReset)===!0;if(Pe&&cr(Pe.formMethod)){await Et(U,G,Ie,je,Ke,De.active,ge,ut,Pe,he&&he.defaultShouldRevalidate);return}I.set(U,{routeId:G,path:Ie}),await at(U,G,Ie,je,Ke,De.active,ge,ut,Pe)}async function Et(U,G,te,he,ge,Le,Ce,je,De,Ie){Te(),I.delete(U);let Pe=A.fetchers.get(U);Oe(U,lN(De,Pe),{flushSync:Ce});let tt=new AbortController,Ke=Ho(e.history,te,tt.signal,De);if(Le){let xe=await _t(he,new URL(Ke.url).pathname,Ke.signal,U);if(xe.type==="aborted")return;if(xe.type==="error"){bt(U,G,xe.error,{flushSync:Ce});return}else if(xe.matches)he=xe.matches;else{bt(U,G,di(404,{pathname:te}),{flushSync:Ce});return}}let ut=pd(he,te);if(!ut.route.action&&!ut.route.lazy){let xe=di(405,{method:De.formMethod,pathname:te,routeId:G});bt(U,G,xe,{flushSync:Ce});return}Y.set(U,tt);let mt=_,It=Jo(c,u,Ke,te,he,ut,a,ge),ft=await be(Ke,te,It,ge,U),dt=ft[ut.route.id];if(!dt){for(let xe of It)if(ft[xe.route.id]){dt=ft[xe.route.id];break}}if(Ke.signal.aborted){Y.get(U)===tt&&Y.delete(U);return}if(ie.has(U)){if(Xs(dt)||Kr(dt)){Oe(U,Gi(void 0));return}}else{if(Xs(dt))if(Y.delete(U),M>mt){Oe(U,Gi(void 0));return}else return B.add(U),Oe(U,vc(De)),ue(Ke,dt,!1,{fetcherSubmission:De,preventScrollReset:je});if(Kr(dt)){bt(U,G,dt.error);return}}let Ht=A.navigation.location||A.location,st=Ho(e.history,Ht,tt.signal),Nr=f.activeRoutes,pn=A.navigation.state!=="idle"?ji(Nr,A.navigation.location,d,!1,f.branches):A.matches;pt(pn,"Didn't find any matches after fetcher action");let On=++_;z.set(U,On);let{dsMatches:Xn,revalidatingFetchers:_n}=nw(st,ge,c,u,e.history,A,pn,De,Ht,a,!1,K,Z,ie,I,B,Nr,d,e.patchRoutesOnNavigation!=null,f.branches,[ut.route.id,dt],Ie),ra=vc(De,dt.data),or=new Map(A.fetchers);or.set(U,ra),_n.filter(xe=>xe.key!==U).forEach(xe=>{let Ue=xe.key,qe=or.get(Ue),Je=vc(void 0,qe?qe.data:void 0);or.set(Ue,Je),Ft(Ue),xe.controller&&Y.set(Ue,xe.controller)}),Re({fetchers:or});let Si=()=>_n.forEach(xe=>Ft(xe.key));tt.signal.addEventListener("abort",Si);let{loaderResults:dr,fetcherResults:wi}=await $e(Xn,_n,st,Ht,ge);if(tt.signal.aborted)return;tt.signal.removeEventListener("abort",Si),z.delete(U),Y.delete(U),_n.forEach(xe=>Y.delete(xe.key));let rt=A.fetchers.has(U),qt=xe=>{if(!rt)return xe;let Ue=new Map(xe.fetchers);return Ue.set(U,Gi(dt.data)),{...xe,fetchers:Ue}},Zn=Uf(dr);if(Zn)return A=qt(A),ue(st,Zn.result,!1,{preventScrollReset:je});if(Zn=Uf(wi),Zn)return B.add(Zn.key),A=qt(A),ue(st,Zn.result,!1,{preventScrollReset:je});let ei=new Map(A.fetchers);rt&&ei.set(U,Gi(dt.data));let{loaderData:oe,errors:Ee}=cw(A,pn,dr,void 0,_n,wi,ei);qn(On,ei),A.navigation.state==="loading"&&On>M?(pt(F,"Expected pending action"),J&&J.abort(),ye(A.navigation.location,{matches:pn,loaderData:oe,errors:Ee,fetchers:ei})):(Re({errors:Ee,loaderData:uw(A.loaderData,oe,pn,Ee),fetchers:ei}),K=!1)}async function at(U,G,te,he,ge,Le,Ce,je,De){let Ie=A.fetchers.get(U);Oe(U,vc(De,Ie?Ie.data:void 0),{flushSync:Ce});let Pe=new AbortController,tt=Ho(e.history,te,Pe.signal);if(Le){let dt=await _t(he,new URL(tt.url).pathname,tt.signal,U);if(dt.type==="aborted")return;if(dt.type==="error"){bt(U,G,dt.error,{flushSync:Ce});return}else if(dt.matches)he=dt.matches;else{bt(U,G,di(404,{pathname:te}),{flushSync:Ce});return}}let Ke=pd(he,te);Y.set(U,Pe);let ut=_,mt=Jo(c,u,tt,te,he,Ke,a,ge),It=await be(tt,te,mt,ge,U),ft=It[Ke.route.id];if(!ft){for(let dt of he)if(It[dt.route.id]){ft=It[dt.route.id];break}}if(Y.get(U)===Pe&&Y.delete(U),!tt.signal.aborted){if(ie.has(U)){Oe(U,Gi(void 0));return}if(Xs(ft))if(M>ut){Oe(U,Gi(void 0));return}else{B.add(U),await ue(tt,ft,!1,{preventScrollReset:je});return}if(Kr(ft)){bt(U,G,ft.error);return}Oe(U,Gi(ft.data))}}async function ue(U,G,te,{submission:he,fetcherSubmission:ge,preventScrollReset:Le,replace:Ce}={}){te||(H?.resolve(),H=null),G.response.headers.has("X-Remix-Revalidate")&&(K=!0);let je=G.response.headers.get("Location");pt(je,"Expected a Location header on the redirect Response");let De=je,Ie=new URL(U.url);je=ow(je,Ie,d,e.history),Qo(De,je,Ie,"allow-explicit");let Pe=eu(A.location,je,{_isRedirect:!0});if(i){let ft=!1;if(G.response.headers.has("X-Remix-Reload-Document"))ft=!0;else if(Ry(je)){const dt=IC(t,je,!0);ft=dt.origin!==t.location.origin||yi(dt.pathname,d)==null}if(ft){Ce?t.location.replace(je):t.location.assign(je);return}}J=null;let tt=Ce===!0||G.response.headers.has("X-Remix-Replace")?"REPLACE":"PUSH",{formMethod:Ke,formAction:ut,formEncType:mt}=A.navigation;!he&&!ge&&Ke&&ut&&mt&&(he=hw(A.navigation));let It=he||ge;if(zD.has(G.response.status)&&It&&cr(It.formMethod))await Qe(tt,Pe,{submission:{...It,formAction:je},preventScrollReset:Le||X,enableViewTransition:te?$:void 0});else{let ft=ug(Pe,[],tt,he);await Qe(tt,Pe,{overrideNavigation:ft,fetcherSubmission:ge,preventScrollReset:Le||X,enableViewTransition:te?$:void 0})}}async function be(U,G,te,he,ge){let Le,Ce={};try{Le=await GD(m,U,G,te,ge,he,!1)}catch(je){return te.filter(De=>De.shouldLoad).forEach(De=>{Ce[De.route.id]={type:"error",error:je}}),Ce}if(U.signal.aborted)return Ce;if(!cr(U.method))for(let je of te){if(Le[je.route.id]?.type==="error")break;!Le.hasOwnProperty(je.route.id)&&!A.loaderData.hasOwnProperty(je.route.id)&&(!A.errors||!A.errors.hasOwnProperty(je.route.id))&&je.shouldCallHandler()&&(Le[je.route.id]={type:"error",result:new Error(`No result returned from dataStrategy for route ${je.route.id}`)})}for(let[je,De]of Object.entries(Le))if(rN(De)){let Ie=De.result;Ce[je]={type:"redirect",response:WD(Ie,U,je,te,d)}}else Ce[je]=await $D(De);return Ce}async function $e(U,G,te,he,ge){let Le=be(te,he,U,ge,null),Ce=Promise.all(G.map(async Ie=>{if(Ie.matches&&Ie.match&&Ie.request&&Ie.controller){let tt=(await be(Ie.request,Ie.path,Ie.matches,ge,Ie.key))[Ie.match.route.id];return{[Ie.key]:tt}}else return Promise.resolve({[Ie.key]:{type:"error",error:di(404,{pathname:Ie.path})}})})),je=await Le,De=(await Ce).reduce((Ie,Pe)=>Object.assign(Ie,Pe),{});return{loaderResults:je,fetcherResults:De}}function Te(){K=!0,I.forEach((U,G)=>{Y.has(G)&&Z.add(G),Ft(G)})}function Oe(U,G,te={}){let he=new Map(A.fetchers);he.set(U,G),Re({fetchers:he},{flushSync:(te&&te.flushSync)===!0})}function bt(U,G,te,he={}){let ge=os(A.matches,G),Le=new Map(A.fetchers);Ot(Le,U),Re({errors:{[ge.route.id]:te},fetchers:Le},{flushSync:(he&&he.flushSync)===!0})}function Nt(U){return W.set(U,(W.get(U)||0)+1),ie.has(U)&&ie.delete(U),A.fetchers.get(U)||PD}function xt(U,G){Ft(U,G?.reason),Oe(U,Gi(null))}function Ot(U,G){let te=A.fetchers.get(G);Y.has(G)&&!(te&&te.state==="loading"&&z.has(G))&&Ft(G),I.delete(G),z.delete(G),B.delete(G),ie.delete(G),Z.delete(G),U.delete(G)}function Lt(U){let G=(W.get(U)||0)-1;G<=0?(W.delete(U),ie.add(U)):W.set(U,G),Re({fetchers:new Map(A.fetchers)})}function Ft(U,G){let te=Y.get(U);te&&(te.abort(G),Y.delete(U))}function Yt(U,G){for(let te of U){let he=G.get(te);pt(he,`Expected fetcher: ${te}`);let ge=Gi(he.data);G.set(te,ge)}}function mn(U){let G=[],te=!1;for(let he of B){let ge=U.get(he);pt(ge,`Expected fetcher: ${he}`),ge.state==="loading"&&(B.delete(he),G.push(he),te=!0)}return Yt(G,U),te}function qn(U,G){let te=[];for(let[he,ge]of z)if(ge0}function Gn(U,G){let te=A.blockers.get(U)||yc;return fe.get(U)!==G&&fe.set(U,G),te}function bn(U){A.blockers.delete(U),fe.delete(U)}function Rt(U,G){let te=A.blockers.get(U)||yc;pt(te.state==="unblocked"&&G.state==="blocked"||te.state==="blocked"&&G.state==="blocked"||te.state==="blocked"&&G.state==="proceeding"||te.state==="blocked"&&G.state==="unblocked"||te.state==="proceeding"&&G.state==="unblocked",`Invalid blocker state transition: ${te.state} -> ${G.state}`);let he=new Map(A.blockers);he.set(U,G),Re({blockers:he})}function un({currentLocation:U,nextLocation:G,historyAction:te}){if(fe.size===0)return;fe.size>1&&wn(!1,"A router only supports one blocker at a time");let he=Array.from(fe.entries()),[ge,Le]=he[he.length-1],Ce=A.blockers.get(ge);if(!(Ce&&Ce.state==="proceeding")&&Le({currentLocation:U,nextLocation:G,historyAction:te}))return ge}function kt(U){let G=di(404,{pathname:U}),te=f.activeRoutes,{matches:he,route:ge}=Vf(te);return{notFoundMatches:he,route:ge,error:G}}function jn(U,G,te){if(E=U,R=G,w=te||null,!T&&A.navigation===cg){T=!0;let he=sn(A.location,A.matches);he!=null&&Re({restoreScrollPosition:he})}return()=>{E=null,R=null,w=null}}function Pn(U,G){return w&&w(U,G.map(he=>oD(he,A.loaderData)))||U.key}function ct(U,G){if(E&&R){let te=Pn(U,G);E[te]=R()}}function sn(U,G){if(E){let te=Pn(U,G),he=E[te];if(typeof he=="number")return he}return null}function Jt(U,G,te){if(e.patchRoutesOnNavigation){let he=f.branches;if(U){if(Object.keys(U[0].params).length>0)return{active:!0,matches:ji(G,te,d,!0,he)}}else return{active:!0,matches:ji(G,te,d,!0,he)||[]}}return{active:!1,matches:null}}async function _t(U,G,te,he){if(!e.patchRoutesOnNavigation)return{type:"success",matches:U};let ge=U;for(;;){let Le=u;try{await e.patchRoutesOnNavigation({signal:te,path:G,matches:ge,fetcherKey:he,patch:(Ie,Pe)=>{te.aborted||rw(Ie,Pe,f,Le,c,!1)}})}catch(Ie){return{type:"error",error:Ie,partialMatches:ge}}if(te.aborted)return{type:"aborted"};let Ce=f.branches,je=ji(f.activeRoutes,G,d,!1,Ce),De=null;if(je){if(Object.keys(je[0].params).length===0)return{type:"success",matches:je};if(De=ji(f.activeRoutes,G,d,!0,Ce),!(De&&ge.lengthte.route.id===G[he].route.id)}function fn(U){u={},f.setHmrRoutes(tu(U,c,void 0,u))}function Kn(U,G,te=!1){rw(U,G,f,u,c,te),f.hasHMRRoutes||Re({})}return D={get basename(){return d},get future(){return g},get state(){return A},get routes(){return f.stableRoutes},get branches(){return f.branches},get manifest(){return u},get window(){return t},initialize:Ae,subscribe:we,enableScrollRestoration:jn,navigate:ze,fetch:et,revalidate:Ye,createHref:U=>e.history.createHref(U),createURL:U=>e.history.createURL(U),encodeLocation:U=>e.history.encodeLocation(U),getFetcher:Nt,resetFetcher:xt,deleteFetcher:Lt,dispose:ke,getBlocker:Gn,deleteBlocker:bn,patchRoutes:Kn,_internalFetchControllers:Y,_internalSetRoutes:fn,_internalSetStateDoNotUseOrYouWillBreakYourApp(U){Re(U)}},e.instrumentations&&(D=TD(D,e.instrumentations.map(U=>U.router).filter(Boolean))),D}function BD(e){return e!=null&&("formData"in e&&e.formData!=null||"body"in e&&e.body!==void 0)}function d0(e,t,i,a,o,c){let u,f;if(o){u=[];for(let m of t)if(u.push(m),m.route.id===o){f=m;break}}else u=t,f=t[t.length-1];let d=bu(a||".",uh(u),yi(e.pathname,i)||e.pathname,c==="path");if(a==null&&(d.search=e.search,d.hash=e.hash),(a==null||a===""||a===".")&&f){let m=jy(d.search);if(f.route.index&&!m)d.search=d.search?d.search.replace(/^\?/,"?index&"):"?index";else if(!f.route.index&&m){let g=new URLSearchParams(d.search),v=g.getAll("index");g.delete("index"),v.filter(x=>x).forEach(x=>g.append("index",x));let S=g.toString();d.search=S?`?${S}`:""}}return i!=="/"&&(d.pathname=bD({basename:i,pathname:d.pathname})),wr(d)}function tw(e,t,i){if(!i||!BD(i))return{path:t};if(i.formMethod&&!sN(i.formMethod))return{path:t,error:di(405,{method:i.formMethod})};let a=()=>({path:t,error:di(400,{type:"invalid-body"})}),c=(i.formMethod||"get").toUpperCase(),u=lT(t);if(i.body!==void 0){if(i.formEncType==="text/plain"){if(!cr(c))return a();let v=typeof i.body=="string"?i.body:i.body instanceof FormData||i.body instanceof URLSearchParams?Array.from(i.body.entries()).reduce((S,[x,E])=>`${S}${x}=${E} +`,""):String(i.body);return{path:t,submission:{formMethod:c,formAction:u,formEncType:i.formEncType,formData:void 0,json:void 0,text:v}}}else if(i.formEncType==="application/json"){if(!cr(c))return a();try{let v=typeof i.body=="string"?JSON.parse(i.body):i.body;return{path:t,submission:{formMethod:c,formAction:u,formEncType:i.formEncType,formData:void 0,json:v,text:void 0}}}catch{return a()}}}pt(typeof FormData=="function","FormData is not available in this environment");let f,d;if(i.formData)f=p0(i.formData),d=i.formData;else if(i.body instanceof FormData)f=p0(i.body),d=i.body;else if(i.body instanceof URLSearchParams)f=i.body,d=lw(f);else if(i.body==null)f=new URLSearchParams,d=new FormData;else try{f=new URLSearchParams(i.body),d=lw(f)}catch{return a()}let m={formMethod:c,formAction:u,formEncType:i&&i.formEncType||"application/x-www-form-urlencoded",formData:d,json:void 0,text:void 0};if(cr(m.formMethod))return{path:t,submission:m};let g=ea(t);return e&&g.search&&jy(g.search)&&f.append("index",""),g.search=`?${f}`,{path:wr(g),submission:m}}function nw(e,t,i,a,o,c,u,f,d,m,g,v,S,x,E,w,R,T,O,N,j,L){let P=j?Kr(j[1])?j[1].error:j[1].data:void 0,D=o.createURL(c.location),A=o.createURL(d),F;if(g&&c.errors){let V=Object.keys(c.errors)[0];F=u.findIndex(K=>K.route.id===V)}else if(j&&Kr(j[1])){let V=j[0];F=u.findIndex(K=>K.route.id===V)-1}let H=j?j[1].statusCode:void 0,X=H&&H>=400,J={currentUrl:D,currentParams:c.matches[0]?.params||{},nextUrl:A,nextParams:u[0].params,...f,actionResult:P,actionStatus:H},$=Su(u),ee=u.map((V,K)=>{let{route:Z}=V,Y=null;if(F!=null&&K>F)Y=!1;else if(Z.lazy)Y=!0;else if(!Ay(Z))Y=!1;else if(g){let{shouldLoad:B}=tT(Z,c.loaderData,c.errors);Y=B}else ID(c.loaderData,c.matches[K],V)&&(Y=!0);if(Y!==null)return h0(i,a,e,d,$,V,m,t,Y);let _=!1;typeof L=="boolean"?_=L:X?_=!1:(v||D.pathname+D.search===A.pathname+A.search||D.search!==A.search||HD(c.matches[K],V))&&(_=!0);let M={...J,defaultShouldRevalidate:_},z=_c(V,M);return h0(i,a,e,d,$,V,m,t,z,M,L)}),re=[];return E.forEach((V,K)=>{if(g||!u.some(W=>W.route.id===V.routeId)||x.has(K))return;let Z=c.fetchers.get(K),Y=Z&&Z.state!=="idle"&&Z.data===void 0,_=ji(R,V.path,T??"/",!1,N);if(!_){if(O&&Y)return;re.push({key:K,routeId:V.routeId,path:V.path,matches:null,match:null,request:null,controller:null});return}if(w.has(K))return;let M=pd(_,V.path),z=new AbortController,B=Ho(o,V.path,z.signal),I=null;if(S.has(K))S.delete(K),I=Jo(i,a,B,V.path,_,M,m,t);else if(Y)v&&(I=Jo(i,a,B,V.path,_,M,m,t));else{let W;typeof L=="boolean"?W=L:X?W=!1:W=v;let ie={...J,defaultShouldRevalidate:W};_c(M,ie)&&(I=Jo(i,a,B,V.path,_,M,m,t,ie))}I&&re.push({key:K,routeId:V.routeId,path:V.path,matches:I,match:M,request:B,controller:z})}),{dsMatches:ee,revalidatingFetchers:re}}function Ay(e){return e.loader!=null||e.middleware!=null&&e.middleware.length>0}function tT(e,t,i){if(e.lazy)return{shouldLoad:!0,renderFallback:!0};if(!Ay(e))return{shouldLoad:!1,renderFallback:!1};let a=t!=null&&e.id in t,o=i!=null&&i[e.id]!==void 0;if(!a&&o)return{shouldLoad:!1,renderFallback:!1};if(typeof e.loader=="function"&&e.loader.hydrate===!0)return{shouldLoad:!0,renderFallback:!a};let c=!a&&!o;return{shouldLoad:c,renderFallback:c}}function ID(e,t,i){let a=!t||i.route.id!==t.route.id,o=!e.hasOwnProperty(i.route.id);return a||o}function HD(e,t){let i=e.route.path;return e.pathname!==t.pathname||i!=null&&i.endsWith("*")&&e.params["*"]!==t.params["*"]}function _c(e,t){if(e.route.shouldRevalidate){let i=e.route.shouldRevalidate(t);if(typeof i=="boolean")return i}return t.defaultShouldRevalidate}function rw(e,t,i,a,o,c){let u;if(e){let m=a[e];pt(m,`No route found to patch children into: routeId = ${e}`),m.children||(m.children=[]),u=m.children}else u=i.activeRoutes;let f=[],d=[];if(t.forEach(m=>{let g=u.find(v=>nT(m,v));g?d.push({existingRoute:g,newRoute:m}):f.push(m)}),f.length>0){let m=tu(f,o,[e||"_","patch",String(u?.length||"0")],a);u.push(...m)}if(c&&d.length>0)for(let m=0;mt.children?.some(o=>nT(i,o)))??!1:!1}var iw=new WeakMap,rT=({key:e,route:t,manifest:i,mapRouteProperties:a})=>{let o=i[t.id];if(pt(o,"No route found in manifest"),!o.lazy||typeof o.lazy!="object")return;let c=o.lazy[e];if(!c)return;let u=iw.get(o);u||(u={},iw.set(o,u));let f=u[e];if(f)return f;let d=(async()=>{let m=rD(e),v=o[e]!==void 0&&e!=="hasErrorBoundary";if(m)wn(!m,"Route property "+e+" is not a supported lazy route property. This property will be ignored."),u[e]=Promise.resolve();else if(v)wn(!1,`Route "${o.id}" has a static property "${e}" defined. The lazy property will be ignored.`);else{let S=await c();S!=null&&(Object.assign(o,{[e]:S}),Object.assign(o,a(o)))}typeof o.lazy=="object"&&(o.lazy[e]=void 0,Object.values(o.lazy).every(S=>S===void 0)&&(o.lazy=void 0))})();return u[e]=d,d},aw=new WeakMap;function FD(e,t,i,a,o){let c=i[e.id];if(pt(c,"No route found in manifest"),!e.lazy)return{lazyRoutePromise:void 0,lazyHandlerPromise:void 0};if(typeof e.lazy=="function"){let g=aw.get(c);if(g)return{lazyRoutePromise:g,lazyHandlerPromise:g};let v=(async()=>{pt(typeof e.lazy=="function","No lazy route function found");let S=await e.lazy(),x={};for(let E in S){let w=S[E];if(w===void 0)continue;let R=aD(E),O=c[E]!==void 0&&E!=="hasErrorBoundary";R?wn(!R,"Route property "+E+" is not a supported property to be returned from a lazy route function. This property will be ignored."):O?wn(!O,`Route "${c.id}" has a static property "${E}" defined but its lazy function is also returning a value for this property. The lazy route property "${E}" will be ignored.`):x[E]=w}Object.assign(c,x),Object.assign(c,{...a(c),lazy:void 0})})();return aw.set(c,v),v.catch(()=>{}),{lazyRoutePromise:v,lazyHandlerPromise:v}}let u=Object.keys(e.lazy),f=[],d;for(let g of u){if(o&&o.includes(g))continue;let v=rT({key:g,route:e,manifest:i,mapRouteProperties:a});v&&(f.push(v),g===t&&(d=v))}let m=f.length>0?Promise.all(f).then(()=>{}):void 0;return m?.catch(()=>{}),d?.catch(()=>{}),{lazyRoutePromise:m,lazyHandlerPromise:d}}async function sw(e){let t=e.matches.filter(o=>o.shouldLoad),i={};return(await Promise.all(t.map(o=>o.resolve()))).forEach((o,c)=>{i[t[c].route.id]=o}),i}async function YD(e){return e.matches.some(t=>t.route.middleware)?iT(e,()=>sw(e)):sw(e)}function iT(e,t){return qD(e,t,a=>{if(aN(a))throw a;return a},tN,i);function i(a,o,c){if(c)return Promise.resolve(Object.assign(c.value,{[o]:{type:"error",result:a}}));{let{matches:u}=e,f=Math.min(Math.max(u.findIndex(m=>m.route.id===o),0),Math.max(u.findIndex(m=>m.shouldCallHandler()),0)),d=os(u,u[f].route.id).route.id;return Promise.resolve({[d]:{type:"error",result:a}})}}}async function qD(e,t,i,a,o){let{matches:c,...u}=e,f=c.flatMap(m=>m.route.middleware?m.route.middleware.map(g=>[m.route.id,g]):[]);return await aT(u,f,t,i,a,o)}async function aT(e,t,i,a,o,c,u=0){let{request:f}=e;if(f.signal.aborted)throw f.signal.reason??new Error(`Request aborted: ${f.method} ${f.url}`);let d=t[u];if(!d)return await i();let[m,g]=d,v,S=async()=>{if(v)throw new Error("You may only call `next()` once per middleware");try{return v={value:await aT(e,t,i,a,o,c,u+1)},v.value}catch(x){return v={value:await c(x,m,v)},v.value}};try{let x=await g(e,S),E=x!=null?a(x):void 0;return o(E)?E:v?E??v.value:(v={value:await S()},v.value)}catch(x){return await c(x,m,v)}}function sT(e,t,i,a,o){let c=rT({key:"middleware",route:a.route,manifest:t,mapRouteProperties:e}),u=FD(a.route,cr(i.method)?"action":"loader",t,e,o);return{middleware:c,route:u.lazyRoutePromise,handler:u.lazyHandlerPromise}}function h0(e,t,i,a,o,c,u,f,d,m=null,g){let v=!1,S=sT(e,t,i,c,u);return{...c,_lazyPromises:S,shouldLoad:d,shouldRevalidateArgs:m,shouldCallHandler(x){return v=!0,m?typeof g=="boolean"?_c(c,{...m,defaultShouldRevalidate:g}):typeof x=="boolean"?_c(c,{...m,defaultShouldRevalidate:x}):_c(c,m):d},resolve(x){let{lazy:E,loader:w,middleware:R}=c.route,T=v||d||x&&!cr(i.method)&&(E||w),O=R&&R.length>0&&!w&&!E;return T&&(cr(i.method)||!O)?KD({request:i,path:a,pattern:o,match:c,lazyHandlerPromise:S?.handler,lazyRoutePromise:S?.route,handlerOverride:x,scopedContext:f}):Promise.resolve({type:"data",result:void 0})}}}function Jo(e,t,i,a,o,c,u,f,d=null){return o.map(m=>m.route.id!==c.route.id?{...m,shouldLoad:!1,shouldRevalidateArgs:d,shouldCallHandler:()=>!1,_lazyPromises:sT(e,t,i,m,u),resolve:()=>Promise.resolve({type:"data",result:void 0})}:h0(e,t,i,a,Su(o),m,u,f,!0,d))}async function GD(e,t,i,a,o,c,u){a.some(g=>g._lazyPromises?.middleware)&&await Promise.all(a.map(g=>g._lazyPromises?.middleware));let f={request:t,url:oT(t,i),pattern:Su(a),params:a[0].params,context:c,matches:a},m=await e({...f,fetcherKey:o,runClientMiddleware:g=>{let v=f;return iT(v,()=>g({...v,fetcherKey:o,runClientMiddleware:()=>{throw new Error("Cannot call `runClientMiddleware()` from within an `runClientMiddleware` handler")}}))}});try{await Promise.all(a.flatMap(g=>[g._lazyPromises?.handler,g._lazyPromises?.route]))}catch{}return m}async function KD({request:e,path:t,pattern:i,match:a,lazyHandlerPromise:o,lazyRoutePromise:c,handlerOverride:u,scopedContext:f}){let d,m,g=cr(e.method),v=g?"action":"loader",S=x=>{let E,w=new Promise((O,N)=>E=N);m=()=>E(),e.signal.addEventListener("abort",m);let R=O=>typeof x!="function"?Promise.reject(new Error(`You cannot call the handler for a route which defines a boolean "${v}" [routeId: ${a.route.id}]`)):x({request:e,url:oT(e,t),pattern:i,params:a.params,context:f},...O!==void 0?[O]:[]),T=(async()=>{try{return{type:"data",result:await(u?u(N=>R(N)):R())}}catch(O){return{type:"error",result:O}}})();return Promise.race([T,w])};try{let x=g?a.route.action:a.route.loader;if(o||c)if(x){let E,[w]=await Promise.all([S(x).catch(R=>{E=R}),o,c]);if(E!==void 0)throw E;d=w}else{await o;let E=g?a.route.action:a.route.loader;if(E)[d]=await Promise.all([S(E),c]);else if(v==="action"){let w=new URL(e.url),R=w.pathname+w.search;throw di(405,{method:e.method,pathname:R,routeId:a.route.id})}else return{type:"data",result:void 0}}else if(x)d=await S(x);else{let E=new URL(e.url),w=E.pathname+E.search;throw di(404,{pathname:w})}}catch(x){return{type:"error",result:x}}finally{m&&e.signal.removeEventListener("abort",m)}return d}async function XD(e){let t=e.headers.get("Content-Type");return t&&/\bapplication\/json\b/.test(t)?e.body==null?null:e.json():e.text()}async function $D(e){let{result:t,type:i}=e;if(My(t)){let a;try{a=await XD(t)}catch(o){return{type:"error",error:o}}return i==="error"?{type:"error",error:new xu(t.status,t.statusText,a),statusCode:t.status,headers:t.headers}:{type:"data",data:a,statusCode:t.status,headers:t.headers}}return i==="error"?dw(t)?t.data instanceof Error?{type:"error",error:t.data,statusCode:t.init?.status,headers:t.init?.headers?new Headers(t.init.headers):void 0}:{type:"error",error:eN(t),statusCode:nu(t)?t.status:void 0,headers:t.init?.headers?new Headers(t.init.headers):void 0}:{type:"error",error:t,statusCode:nu(t)?t.status:void 0}:dw(t)?{type:"data",data:t.data,statusCode:t.init?.status,headers:t.init?.headers?new Headers(t.init.headers):void 0}:{type:"data",data:t}}function WD(e,t,i,a,o){let c=e.headers.get("Location");if(pt(c,"Redirects returned/thrown from loaders/actions must have a Location header"),!Ry(c)){let u=a.slice(0,a.findIndex(f=>f.route.id===i)+1);c=d0(new URL(t.url),u,o,c),e.headers.set("Location",c)}return e}var ZD=["about:","blob:","chrome:","chrome-untrusted:","content:","data:","devtools:","file:","filesystem:","javascript:"];function m0(e){try{return ZD.includes(new URL(e).protocol)}catch{return!1}}function ow(e,t,i,a){if(Ry(e)){let o=e,c=ch.test(o)?new URL(BC(o,t.protocol)):new URL(o);if(m0(c.toString()))throw new Error("Invalid redirect location");let u=yi(c.pathname,i)!=null;if(c.origin===t.origin&&u)return Cy(c.pathname)+c.search+c.hash}try{let o=a.createURL(e);if(m0(o.toString()))throw new Error("Invalid redirect location")}catch{}return e}function Ho(e,t,i,a){let o=e.createURL(lT(t)).toString(),c={signal:i};if(a&&cr(a.formMethod)){let{formMethod:u,formEncType:f}=a;c.method=u.toUpperCase(),f==="application/json"?(c.headers=new Headers({"Content-Type":f}),c.body=JSON.stringify(a.json)):f==="text/plain"?c.body=a.text:f==="application/x-www-form-urlencoded"&&a.formData?c.body=p0(a.formData):c.body=a.formData}return new Request(o,c)}function oT(e,t){let i=new URL(e.url),a=typeof t=="string"?ea(t):t;if(i.pathname=a.pathname||"/",a.search){let o=new URLSearchParams(a.search),c=o.getAll("index");o.delete("index");for(let u of c.filter(Boolean))o.append("index",u);i.search=o.size?`?${o.toString()}`:""}else i.search="";return i.hash=a.hash||"",i}function p0(e){let t=new URLSearchParams;for(let[i,a]of e.entries())t.append(i,typeof a=="string"?a:a.name);return t}function lw(e){let t=new FormData;for(let[i,a]of e.entries())t.append(i,a);return t}function QD(e,t,i,a=!1,o=!1){let c={},u=null,f,d=!1,m={},g=i&&Kr(i[1])?i[1].error:void 0;return e.forEach(v=>{if(!(v.route.id in t))return;let S=v.route.id,x=t[S];if(pt(!Xs(x),"Cannot handle redirect results in processLoaderData"),Kr(x)){let E=x.error;if(g!==void 0&&(E=g,g=void 0),u=u||{},o)u[S]=E;else{let w=os(e,S);u[w.route.id]==null&&(u[w.route.id]=E)}a||(c[S]=eT),d||(d=!0,f=nu(x.error)?x.error.status:500),x.headers&&(m[S]=x.headers)}else c[S]=x.data,x.statusCode&&x.statusCode!==200&&!d&&(f=x.statusCode),x.headers&&(m[S]=x.headers)}),g!==void 0&&i&&(u={[i[0]]:g},i[2]&&(c[i[2]]=void 0)),{loaderData:c,errors:u,statusCode:f||200,loaderHeaders:m}}function cw(e,t,i,a,o,c,u){let{loaderData:f,errors:d}=QD(t,i,a);return o.filter(m=>!m.matches||m.matches.some(g=>g.shouldLoad)).forEach(m=>{let{key:g,match:v,controller:S}=m;if(S&&S.signal.aborted)return;let x=c[g];if(pt(x,"Did not find corresponding fetcher result"),Kr(x)){let E=os(e.matches,v?.route.id);d&&d[E.route.id]||(d={...d,[E.route.id]:x.error}),u.delete(g)}else if(Xs(x))pt(!1,"Unhandled fetcher revalidation redirect");else{let E=Gi(x.data);u.set(g,E)}}),{loaderData:f,errors:d}}function uw(e,t,i,a){let o=Object.entries(t).filter(([,c])=>c!==eT).reduce((c,[u,f])=>(c[u]=f,c),{});for(let c of i){let u=c.route.id;if(!t.hasOwnProperty(u)&&e.hasOwnProperty(u)&&c.route.loader&&(o[u]=e[u]),a&&a.hasOwnProperty(u))break}return o}function fw(e){return e?Kr(e[1])?{actionData:{}}:{actionData:{[e[0]]:e[1].data}}:{}}function os(e,t){return(t?e.slice(0,e.findIndex(a=>a.route.id===t)+1):[...e]).reverse().find(a=>a.route.hasErrorBoundary===!0)||e[0]}function Vf(e){let t=e.length===1?e[0]:e.find(i=>i.index||!i.path||i.path==="/")||{id:"__shim-error-route__"};return{matches:[{params:{},pathname:"",pathnameBase:"",route:t}],route:t}}function di(e,{pathname:t,routeId:i,method:a,type:o,message:c}={}){let u="Unknown Server Error",f="Unknown @remix-run/router error";return e===400?(u="Bad Request",a&&t&&i?f=`You made a ${a} request to "${t}" but did not provide a \`loader\` for route "${i}", so there is no way to handle the request.`:o==="invalid-body"&&(f="Unable to encode submission body")):e===403?(u="Forbidden",f=`Route "${i}" does not match URL "${t}"`):e===404?(u="Not Found",f=`No route matches URL "${t}"`):e===405&&(u="Method Not Allowed",a&&t&&i?f=`You made a ${a.toUpperCase()} request to "${t}" but did not provide an \`action\` for route "${i}", so there is no way to handle the request.`:a&&(f=`Invalid request method "${a.toUpperCase()}"`)),new xu(e||500,u,new Error(f),!0)}function Uf(e){let t=Object.entries(e);for(let i=t.length-1;i>=0;i--){let[a,o]=t[i];if(Xs(o))return{key:a,result:o}}}function lT(e){let t=typeof e=="string"?ea(e):e;return wr({...t,hash:""})}function JD(e,t){return e.pathname!==t.pathname||e.search!==t.search?!1:e.hash===""?t.hash!=="":e.hash===t.hash?!0:t.hash!==""}function eN(e){return new xu(e.init?.status??500,e.init?.statusText??"Internal Server Error",e.data)}function tN(e){return e!=null&&typeof e=="object"&&Object.entries(e).every(([t,i])=>typeof t=="string"&&nN(i))}function nN(e){return e!=null&&typeof e=="object"&&"type"in e&&"result"in e&&(e.type==="data"||e.type==="error")}function rN(e){return My(e.result)&&QC.has(e.result.status)}function Kr(e){return e.type==="error"}function Xs(e){return(e&&e.type)==="redirect"}function dw(e){return typeof e=="object"&&e!=null&&"type"in e&&"data"in e&&"init"in e&&e.type==="DataWithResponseInit"}function My(e){return e!=null&&typeof e.status=="number"&&typeof e.statusText=="string"&&typeof e.headers=="object"&&typeof e.body<"u"}function iN(e){return QC.has(e)}function aN(e){return My(e)&&iN(e.status)&&e.headers.has("Location")}function sN(e){return kD.has(e.toUpperCase())}function cr(e){return ND.has(e.toUpperCase())}function jy(e){return new URLSearchParams(e).getAll("index").some(t=>t==="")}function pd(e,t){let i=typeof t=="string"?ea(t).search:t.search;if(e[e.length-1].route.index&&jy(i||""))return e[e.length-1];let a=KC(e);return a[a.length-1]}function hw(e){let{formMethod:t,formAction:i,formEncType:a,text:o,formData:c,json:u}=e;if(!(!t||!i||!a)){if(o!=null)return{formMethod:t,formAction:i,formEncType:a,formData:void 0,json:void 0,text:o};if(c!=null)return{formMethod:t,formAction:i,formEncType:a,formData:c,json:void 0,text:void 0};if(u!==void 0)return{formMethod:t,formAction:i,formEncType:a,formData:void 0,json:u,text:void 0}}}function ug(e,t,i,a){return a?{state:"loading",location:e,matches:t,historyAction:i,formMethod:a.formMethod,formAction:a.formAction,formEncType:a.formEncType,formData:a.formData,json:a.json,text:a.text}:{state:"loading",location:e,matches:t,historyAction:i,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0}}function oN(e,t,i,a){return{state:"submitting",location:e,matches:t,historyAction:i,formMethod:a.formMethod,formAction:a.formAction,formEncType:a.formEncType,formData:a.formData,json:a.json,text:a.text}}function vc(e,t){return e?{state:"loading",formMethod:e.formMethod,formAction:e.formAction,formEncType:e.formEncType,formData:e.formData,json:e.json,text:e.text,data:t}:{state:"loading",formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0,data:t}}function lN(e,t){return{state:"submitting",formMethod:e.formMethod,formAction:e.formAction,formEncType:e.formEncType,formData:e.formData,json:e.json,text:e.text,data:t?t.data:void 0}}function Gi(e){return{state:"idle",formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0,data:e}}function cN(e,t){try{let i=e.sessionStorage.getItem(JC);if(i){let a=JSON.parse(i);for(let[o,c]of Object.entries(a||{}))c&&Array.isArray(c)&&t.set(o,new Set(c||[]))}}catch{}}function uN(e,t){if(t.size>0){let i={};for(let[a,o]of t)i[a]=[...o];try{e.sessionStorage.setItem(JC,JSON.stringify(i))}catch(a){wn(!1,`Failed to save applied view transitions in sessionStorage (${a}).`)}}}function mw(){let e,t,i=new Promise((a,o)=>{e=async c=>{a(c);try{await i}catch{}},t=async c=>{o(c);try{await i}catch{}}});return{promise:i,resolve:e,reject:t}}var ao=b.createContext(null);ao.displayName="DataRouter";var wu=b.createContext(null);wu.displayName="DataRouterState";var cT=b.createContext(!1);function uT(){return b.useContext(cT)}var Oy=b.createContext({isTransitioning:!1});Oy.displayName="ViewTransition";var fT=b.createContext(new Map);fT.displayName="Fetchers";var fN=b.createContext(null);fN.displayName="Await";var Qr=b.createContext(null);Qr.displayName="Navigation";var fh=b.createContext(null);fh.displayName="Location";var bi=b.createContext({outlet:null,matches:[],isDataRoute:!1});bi.displayName="Route";var Dy=b.createContext(null);Dy.displayName="RouteError";var dT="REACT_ROUTER_ERROR",dN="REDIRECT",hN="ROUTE_ERROR_RESPONSE";function mN(e){if(e.startsWith(`${dT}:${dN}:{`))try{let t=JSON.parse(e.slice(28));if(typeof t=="object"&&t&&typeof t.status=="number"&&typeof t.statusText=="string"&&typeof t.location=="string"&&typeof t.reloadDocument=="boolean"&&typeof t.replace=="boolean")return t}catch{}}function pN(e){if(e.startsWith(`${dT}:${hN}:{`))try{let t=JSON.parse(e.slice(40));if(typeof t=="object"&&t&&typeof t.status=="number"&&typeof t.statusText=="string")return new xu(t.status,t.statusText,t.data)}catch{}}function gN(e,{relative:t}={}){pt(El(),"useHref() may be used only in the context of a component.");let{basename:i,navigator:a}=b.useContext(Qr),{hash:o,pathname:c,search:u}=Eu(e,{relative:t}),f=c;return i!=="/"&&(f=c==="/"?i:pi([i,c])),a.createHref({pathname:f,search:u,hash:o})}function El(){return b.useContext(fh)!=null}function Jr(){return pt(El(),"useLocation() may be used only in the context of a component."),b.useContext(fh).location}var hT="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function mT(e){b.useContext(Qr).static||b.useLayoutEffect(e)}function so(){let{isDataRoute:e}=b.useContext(bi);return e?NN():yN()}function yN(){pt(El(),"useNavigate() may be used only in the context of a component.");let e=b.useContext(ao),{basename:t,navigator:i}=b.useContext(Qr),{matches:a}=b.useContext(bi),{pathname:o}=Jr(),c=JSON.stringify(uh(a)),u=b.useRef(!1);return mT(()=>{u.current=!0}),b.useCallback((d,m={})=>{if(wn(u.current,hT),!u.current)return;if(typeof d=="number"){i.go(d);return}let g=bu(d,JSON.parse(c),o,m.relative==="path");e==null&&t!=="/"&&(g.pathname=g.pathname==="/"?t:pi([t,g.pathname])),Qo(typeof d=="string"?d:wr(d),i.createHref(g),Ty(i),"reject"),(m.replace?i.replace:i.push)(g,m.state,m)},[t,i,c,o,e])}var vN=b.createContext(null);function bN(e){let t=b.useContext(bi).outlet;return b.useMemo(()=>t&&b.createElement(vN.Provider,{value:e},t),[t,e])}function xN(){let{matches:e}=b.useContext(bi);return e[e.length-1]?.params??{}}function Eu(e,{relative:t}={}){let{matches:i}=b.useContext(bi),{pathname:a}=Jr(),o=JSON.stringify(uh(i));return b.useMemo(()=>bu(e,JSON.parse(o),a,t==="path"),[e,o,a,t])}function SN(e,t,i){pt(El(),"useRoutes() may be used only in the context of a component.");let{navigator:a}=b.useContext(Qr),{matches:o}=b.useContext(bi),c=o[o.length-1],u=c?c.params:{},f=c?c.pathname:"/",d=c?c.pathnameBase:"/",m=c&&c.route;{let R=m&&m.path||"";gT(f,!m||R.endsWith("*")||R.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${f}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. + +Please change the parent to .`)}let g=Jr(),v;v=g;let S=v.pathname||"/",x=S;if(d!=="/"){let R=d.replace(/^\//,"").split("/");x="/"+S.replace(/^\//,"").split("/").slice(R.length).join("/")}let E=i&&i.state.matches.length?i.state.matches.map(R=>Object.assign(R,{route:i.manifest[R.route.id]||R.route})):HC(e,{pathname:x});return wn(m||E!=null,`No routes matched location "${v.pathname}${v.search}${v.hash}" `),wn(E==null||E[E.length-1].route.element!==void 0||E[E.length-1].route.Component!==void 0||E[E.length-1].route.lazy!==void 0,`Matched leaf route at location "${v.pathname}${v.search}${v.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`),TN(E&&E.map(R=>Object.assign({},R,{params:Object.assign({},u,R.params),pathname:pi([d,a.encodeLocation?a.encodeLocation(R.pathname.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:R.pathname]),pathnameBase:R.pathnameBase==="/"?d:pi([d,a.encodeLocation?a.encodeLocation(R.pathnameBase.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:R.pathnameBase])})),o,i)}function wN(){let e=DN(),t=nu(e)?`${e.status} ${e.statusText}`:e instanceof Error?e.message:JSON.stringify(e),i=e instanceof Error?e.stack:null,a="rgba(200,200,200, 0.5)",o={padding:"0.5rem",backgroundColor:a},c={padding:"2px 4px",backgroundColor:a},u=null;return console.error("Error handled by React Router default ErrorBoundary:",e),u=b.createElement(b.Fragment,null,b.createElement("p",null,"💿 Hey developer 👋"),b.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",b.createElement("code",{style:c},"ErrorBoundary")," or"," ",b.createElement("code",{style:c},"errorElement")," prop on your route.")),b.createElement(b.Fragment,null,b.createElement("h2",null,"Unexpected Application Error!"),b.createElement("h3",{style:{fontStyle:"italic"}},t),i?b.createElement("pre",{style:o},i):null,u)}var EN=b.createElement(wN,null),pT=class extends b.Component{constructor(e){super(e),this.state={location:e.location,revalidation:e.revalidation,error:e.error}}static getDerivedStateFromError(e){return{error:e}}static getDerivedStateFromProps(e,t){return t.location!==e.location||t.revalidation!=="idle"&&e.revalidation==="idle"?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:e.error!==void 0?e.error:t.error,location:t.location,revalidation:e.revalidation||t.revalidation}}componentDidCatch(e,t){this.props.onError?this.props.onError(e,t):console.error("React Router caught the following error during render",e)}render(){let e=this.state.error;if(this.context&&typeof e=="object"&&e&&"digest"in e&&typeof e.digest=="string"){const i=pN(e.digest);i&&(e=i)}let t=e!==void 0?b.createElement(bi.Provider,{value:this.props.routeContext},b.createElement(Dy.Provider,{value:e,children:this.props.component})):this.props.children;return this.context?b.createElement(RN,{error:e},t):t}};pT.contextType=cT;var fg=new WeakMap;function RN({children:e,error:t}){let{basename:i,navigator:a}=b.useContext(Qr);if(typeof t=="object"&&t&&"digest"in t&&typeof t.digest=="string"){let o=mN(t.digest);if(o){let c=fg.get(t);if(c)throw c;let u=$C(o.location,i),f=u.absoluteURL||u.to;if(Qo(o.location,f,Ty(a),"allow-explicit"),m0(f))throw new Error("Invalid redirect location");if(XC&&!fg.get(t))if(u.isExternal||o.reloadDocument)window.location.href=f;else{const d=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(u.to,{replace:o.replace}));throw fg.set(t,d),d}return b.createElement("meta",{httpEquiv:"refresh",content:`0;url=${f}`})}}return e}function CN({routeContext:e,match:t,children:i}){let a=b.useContext(ao);return a&&a.static&&a.staticContext&&(t.route.errorElement||t.route.ErrorBoundary)&&(a.staticContext._deepestRenderedBoundaryId=t.route.id),b.createElement(bi.Provider,{value:e},i)}function TN(e,t=[],i){let a=i?.state;if(e==null){if(!a)return null;if(a.errors)e=a.matches;else if(t.length===0&&!a.initialized&&a.matches.length>0)e=a.matches;else return null}let o=e,c=a?.errors;if(c!=null){let g=o.findIndex(v=>v.route.id&&c?.[v.route.id]!==void 0);pt(g>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(c).join(",")}`),o=o.slice(0,Math.min(o.length,g+1))}let u=!1,f=-1;if(i&&a){u=a.renderFallback;for(let g=0;g=0?o=o.slice(0,f+1):o=[o[0]];break}}}}let d=i?.onError,m=a&&d?(g,v)=>{d(g,{location:a.location,params:a.matches?.[0]?.params??{},pattern:Su(a.matches),errorInfo:v})}:void 0;return o.reduceRight((g,v,S)=>{let x,E=!1,w=null,R=null;a&&(x=c&&v.route.id?c[v.route.id]:void 0,w=v.route.errorElement||EN,u&&(f<0&&S===0?(gT("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),E=!0,R=null):f===S&&(E=!0,R=v.route.hydrateFallbackElement||null)));let T=t.concat(o.slice(0,S+1)),O=()=>{let N;return x?N=w:E?N=R:v.route.Component?N=b.createElement(v.route.Component,null):v.route.element?N=v.route.element:N=g,b.createElement(CN,{match:v,routeContext:{outlet:g,matches:T,isDataRoute:a!=null},children:N})};return a&&(v.route.ErrorBoundary||v.route.errorElement||S===0)?b.createElement(pT,{location:a.location,revalidation:a.revalidation,component:w,error:x,children:O(),routeContext:{outlet:null,matches:T,isDataRoute:!0},onError:m}):O()},null)}function Ny(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function AN(e){let t=b.useContext(ao);return pt(t,Ny(e)),t}function MN(e){let t=b.useContext(wu);return pt(t,Ny(e)),t}function jN(e){let t=b.useContext(bi);return pt(t,Ny(e)),t}function Ly(e){let t=jN(e),i=t.matches[t.matches.length-1];return pt(i.route.id,`${e} can only be used on routes that contain a unique "id"`),i.route.id}function ON(){return Ly("useRouteId")}function DN(){let e=b.useContext(Dy),t=MN("useRouteError"),i=Ly("useRouteError");return e!==void 0?e:t.errors?.[i]}function NN(){let{router:e}=AN("useNavigate"),t=Ly("useNavigate"),i=b.useRef(!1);return mT(()=>{i.current=!0}),b.useCallback(async(o,c={})=>{wn(i.current,hT),i.current&&(typeof o=="number"?await e.navigate(o):await e.navigate(o,{fromRouteId:t,...c}))},[e,t])}var pw={};function gT(e,t,i){!t&&!pw[e]&&(pw[e]=!0,wn(!1,i))}var gw={};function yw(e,t){!e&&!gw[t]&&(gw[t]=!0,console.warn(t))}var LN="useOptimistic",vw=ZE[LN],kN=()=>{};function zN(e){return vw?vw(e):[e,kN]}function PN(e){let t={hasErrorBoundary:e.hasErrorBoundary||e.ErrorBoundary!=null||e.errorElement!=null};return e.Component&&(e.element&&wn(!1,"You should not include both `Component` and `element` on your route - `Component` will be used."),Object.assign(t,{element:b.createElement(e.Component),Component:void 0})),e.HydrateFallback&&(e.hydrateFallbackElement&&wn(!1,"You should not include both `HydrateFallback` and `hydrateFallbackElement` on your route - `HydrateFallback` will be used."),Object.assign(t,{hydrateFallbackElement:b.createElement(e.HydrateFallback),HydrateFallback:void 0})),e.ErrorBoundary&&(e.errorElement&&wn(!1,"You should not include both `ErrorBoundary` and `errorElement` on your route - `ErrorBoundary` will be used."),Object.assign(t,{errorElement:b.createElement(e.ErrorBoundary),ErrorBoundary:void 0})),t}var _N=["HydrateFallback","hydrateFallbackElement"],VN=class{constructor(){this.status="pending",this.promise=new Promise((e,t)=>{this.resolve=i=>{this.status==="pending"&&(this.status="resolved",e(i))},this.reject=i=>{this.status==="pending"&&(this.status="rejected",t(i))}})}};function UN({router:e,flushSync:t,onError:i,useTransitions:a}){a=uT()||a;let[c,u]=b.useState(e.state),[f,d]=zN(c),[m,g]=b.useState(),[v,S]=b.useState({isTransitioning:!1}),[x,E]=b.useState(),[w,R]=b.useState(),[T,O]=b.useState(),N=b.useRef(new Map),j=b.useCallback((A,{deletedFetchers:F,newErrors:H,flushSync:X,viewTransitionOpts:J})=>{H&&i&&Object.values(H).forEach(ee=>i(ee,{location:A.location,params:A.matches[0]?.params??{},pattern:Su(A.matches)})),A.fetchers.forEach((ee,re)=>{ee.data!==void 0&&N.current.set(re,ee.data)}),F.forEach(ee=>N.current.delete(ee)),yw(X===!1||t!=null,'You provided the `flushSync` option to a router update, but you are not using the `` from `react-router/dom` so `ReactDOM.flushSync()` is unavailable. Please update your app to `import { RouterProvider } from "react-router/dom"` and ensure you have `react-dom` installed as a dependency to use the `flushSync` option.');let $=e.window!=null&&e.window.document!=null&&typeof e.window.document.startViewTransition=="function";if(yw(J==null||$,"You provided the `viewTransition` option to a router update, but you do not appear to be running in a DOM environment as `window.startViewTransition` is not available."),!J||!$){t&&X?t(()=>u(A)):a===!1?u(A):b.startTransition(()=>{a===!0&&d(ee=>bw(ee,A)),u(A)});return}if(t&&X){t(()=>{w&&(x?.resolve(),w.skipTransition()),S({isTransitioning:!0,flushSync:!0,currentLocation:J.currentLocation,nextLocation:J.nextLocation})});let ee=e.window.document.startViewTransition(()=>{t(()=>u(A))});ee.finished.finally(()=>{t(()=>{E(void 0),R(void 0),g(void 0),S({isTransitioning:!1})})}),t(()=>R(ee));return}w?(x?.resolve(),w.skipTransition(),O({state:A,currentLocation:J.currentLocation,nextLocation:J.nextLocation})):(g(A),S({isTransitioning:!0,flushSync:!1,currentLocation:J.currentLocation,nextLocation:J.nextLocation}))},[e.window,t,w,x,a,d,i]);b.useLayoutEffect(()=>e.subscribe(j),[e,j]),b.useEffect(()=>{v.isTransitioning&&!v.flushSync&&E(new VN)},[v]),b.useEffect(()=>{if(x&&m&&e.window){let A=m,F=x.promise,H=e.window.document.startViewTransition(async()=>{a===!1?u(A):b.startTransition(()=>{a===!0&&d(X=>bw(X,A)),u(A)}),await F});H.finished.finally(()=>{E(void 0),R(void 0),g(void 0),S({isTransitioning:!1})}),R(H)}},[m,x,e.window,a,d]),b.useEffect(()=>{x&&m&&f.location.key===m.location.key&&x.resolve()},[x,w,f.location,m]),b.useEffect(()=>{!v.isTransitioning&&T&&(g(T.state),S({isTransitioning:!0,flushSync:!1,currentLocation:T.currentLocation,nextLocation:T.nextLocation}),O(void 0))},[v.isTransitioning,T]);let L=b.useMemo(()=>({createHref:e.createHref,createURL:e.createURL,encodeLocation:e.encodeLocation,go:A=>e.navigate(A),push:(A,F,H)=>e.navigate(A,{state:F,preventScrollReset:H?.preventScrollReset}),replace:(A,F,H)=>e.navigate(A,{replace:!0,state:F,preventScrollReset:H?.preventScrollReset})}),[e]),P=e.basename||"/",D=b.useMemo(()=>({router:e,navigator:L,static:!1,basename:P,onError:i}),[e,L,P,i]);return b.createElement(b.Fragment,null,b.createElement(ao.Provider,{value:D},b.createElement(wu.Provider,{value:f},b.createElement(fT.Provider,{value:N.current},b.createElement(Oy.Provider,{value:v},b.createElement(HN,{basename:P,location:f.location,navigationType:f.historyAction,navigator:L,useTransitions:a},b.createElement(BN,{routes:e.routes,manifest:e.manifest,future:e.future,state:f,isStatic:!1,onError:i})))))),null)}function bw(e,t){return{...e,navigation:t.navigation.state!=="idle"?t.navigation:e.navigation,revalidation:t.revalidation!=="idle"?t.revalidation:e.revalidation,actionData:t.navigation.state!=="submitting"?t.actionData:e.actionData,fetchers:t.fetchers}}var BN=b.memo(IN);function IN({routes:e,manifest:t,future:i,state:a,isStatic:o,onError:c}){return SN(e,void 0,{manifest:t,state:a,isStatic:o,onError:c})}function Aa({to:e,replace:t,state:i,relative:a}){pt(El()," may be used only in the context of a component.");let{static:o,navigator:c}=b.useContext(Qr);wn(!o," must not be used on the initial render in a . This is a no-op, but you should modify your code so the is only ever rendered in response to some user interaction or state change.");let{matches:u}=b.useContext(bi),{pathname:f}=Jr(),d=so(),m=bu(e,uh(u),f,a==="path");Qo(typeof e=="string"?e:wr(e),c.createHref(m),Ty(c),"reject");let g=JSON.stringify(m);return b.useEffect(()=>{d(JSON.parse(g),{replace:t,state:i,relative:a})},[d,g,a,t,i]),null}function yT(e){return bN(e.context)}function HN({basename:e="/",children:t=null,location:i,navigationType:a="POP",navigator:o,static:c=!1,useTransitions:u}){pt(!El(),"You cannot render a inside another . You should never have more than one in your app.");let f=e.replace(/^\/*/,"/"),d=b.useMemo(()=>({basename:f,navigator:o,static:c,useTransitions:u,future:{}}),[f,o,c,u]);typeof i=="string"&&(i=ea(i));let{pathname:m="/",search:g="",hash:v="",state:S=null,key:x="default",mask:E}=i,w=b.useMemo(()=>{let R=yi(m,f);return R==null?null:{location:{pathname:R,search:g,hash:v,state:S,key:x,mask:E},navigationType:a}},[f,m,g,v,S,x,a,E]);return wn(w!=null,` is not able to match the URL "${m}${g}${v}" because it does not start with the basename, so the won't render anything.`),w==null?null:b.createElement(Qr.Provider,{value:d},b.createElement(fh.Provider,{children:t,value:w}))}var gd="get",yd="application/x-www-form-urlencoded";function dh(e){return typeof HTMLElement<"u"&&e instanceof HTMLElement}function FN(e){return dh(e)&&e.tagName.toLowerCase()==="button"}function YN(e){return dh(e)&&e.tagName.toLowerCase()==="form"}function qN(e){return dh(e)&&e.tagName.toLowerCase()==="input"}function GN(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function KN(e,t){return e.button===0&&(!t||t==="_self")&&!GN(e)}function g0(e=""){return new URLSearchParams(typeof e=="string"||Array.isArray(e)||e instanceof URLSearchParams?e:Object.keys(e).reduce((t,i)=>{let a=e[i];return t.concat(Array.isArray(a)?a.map(o=>[i,o]):[[i,a]])},[]))}function XN(e,t){let i=g0(e);return t&&t.forEach((a,o)=>{i.has(o)||t.getAll(o).forEach(c=>{i.append(o,c)})}),i}var Bf=null;function $N(){if(Bf===null)try{new FormData(document.createElement("form"),0),Bf=!1}catch{Bf=!0}return Bf}var WN=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function dg(e){return e!=null&&!WN.has(e)?(wn(!1,`"${e}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${yd}"`),null):e}function ZN(e,t){let i,a,o,c,u;if(YN(e)){let f=e.getAttribute("action");a=f?yi(f,t):null,i=e.getAttribute("method")||gd,o=dg(e.getAttribute("enctype"))||yd,c=new FormData(e)}else if(FN(e)||qN(e)&&(e.type==="submit"||e.type==="image")){let f=e.form;if(f==null)throw new Error('Cannot submit a RoadmapPricingWaitlistView the Crate

When agents flood production, hold the line.

Floodwall meters agent-generated infrastructure changes, verifies each intent at a policy gate, and records every admit, defer, and reject in a tamper-evident ledger.

The processing line

Every intent gets a verdict. Production only sees the admitted ones.

On hold
0Deferred intents wait here
shipped
0.1
dependencies
0
tests
267

  1. Intents
  2. Admission
  3. Scheduler
  4. Gate
  5. Ledger
  6. Production

Hold: deferred intents wait for human release or expiry. The ledger records every verdict and outcome. Green boxes show checked, recorded changes in production.

The model

Agents submit intents. Floodwall governs.

Admission

Per-agent token buckets and a bounded priority queue keep one loop from taking the whole lane.

Scheduler

Wide changes run alone, narrow ones run in parallel per resource, and a waiting change is never overtaken by lower-priority work.

Gate

A deny-overrides policy stack and a conflict check rule on every intent. Deferred changes wait on hold for a human.

Ledger

Every verdict is appended to a hash chain so retroactive edits break verification.

Policy gate

Many policies. One verdict.

Reference policies cover global destructive actions, blast-radius urgency, and resource allowlists. The policy trait stays small so teams can add rules that match their own release discipline. A deferred change is held, not dropped, until a human releases or expires it.

Reference policiesHarshest verdict wins
  • no-global-destroy

    Destructive global changes need human sign-off.

    reject
  • blast-needs-priority

    The wider the blast radius, the more urgent a change must be.

    reject
  • resource-allowlist

    Resources off the list wait on hold for a human.

    defer
Add your ownimpl Policy for YourRule

Tamper-evident ledger

Chained records. Independent proof.

Every decision, release, expiry, and outcome is appended with its evidence: the action, the reason, and each policy’s verdict. A retroactive edit anywhere in history breaks the chain.

  • SHA-256 hash chain: each record folds in the previous digest.
  • With a keyring, Ed25519 signatures prove which agent asked for what.
  • verify() replays the chain; verify_signatures() checks every signer.
Recent recordsValid chain
  1. admitreconciler-7scale web
  2. deferdeployerbilling off allowlist
  3. rejectchaos-loopglobal destroy
  4. admitautoscalercache replicas
  5. rejectcost-botbulk region drain
  6. admitmigratorapi schema v12
Head digest189f5d55…0f84c3ca

Roadmap

Ledger on disk. Replay comes next.

  1. 0.1

    The wall

    Intent model, admission control, policy gate, ledger, and demo.

  2. 0.2

    Scheduler

    Wide changes serialize, narrow work runs in parallel per resource, and contradictions wait for a human.

  3. 0.3

    Trustworthy ledger

    SHA-256 chain, signed records, and Merkle checkpoints.

  4. 0.4

    Replay

    Durable append-only state that rebuilds the plane after restart.

Early access

Gate your agents. Join the waitlist.

Sign up with your email, and we will let you in as early access opens.

Join the waitlist

Already have an account? Sign in.

+

When agents flood production, hold the line.

Floodwall meters agent-generated infrastructure changes, verifies each intent at a policy gate, and records every admit, defer, and reject in a tamper-evident ledger.

The processing line

Every intent gets a verdict. Production only sees the admitted ones.

On hold
0Deferred intents wait here
shipped
0.1
dependencies
0
tests
267

  1. Intents
  2. Admission
  3. Scheduler
  4. Gate
  5. Ledger
  6. Production

Hold: deferred intents wait for human release or expiry. The ledger records every verdict and outcome. Green boxes show checked, recorded changes in production.

The model

Agents submit intents. Floodwall governs.

Admission

Per-agent token buckets and a bounded priority queue keep one loop from taking the whole lane.

Scheduler

Wide changes run alone, narrow ones run in parallel per resource, and a waiting change is never overtaken by lower-priority work.

Gate

A deny-overrides policy stack and a conflict check rule on every intent. Deferred changes wait on hold for a human.

Ledger

Every verdict is appended to a hash chain so retroactive edits break verification.

Policy gate

Many policies. One verdict.

Reference policies cover global destructive actions, blast-radius urgency, and resource allowlists. The policy trait stays small so teams can add rules that match their own release discipline. A deferred change is held, not dropped, until a human releases or expires it.

Reference policiesHarshest verdict wins
  • no-global-destroy

    Destructive global changes need human sign-off.

    reject
  • blast-needs-priority

    The wider the blast radius, the more urgent a change must be.

    reject
  • resource-allowlist

    Resources off the list wait on hold for a human.

    defer
Add your ownimpl Policy for YourRule

Tamper-evident ledger

Chained records. Independent proof.

Every decision, release, expiry, and outcome is appended with its evidence: the action, the reason, and each policy’s verdict. A retroactive edit anywhere in history breaks the chain.

  • SHA-256 hash chain: each record folds in the previous digest.
  • With a keyring, Ed25519 signatures prove which agent asked for what.
  • verify() replays the chain; verify_signatures() checks every signer.
Recent recordsValid chain
  1. admitreconciler-7scale web
  2. deferdeployerbilling off allowlist
  3. rejectchaos-loopglobal destroy
  4. admitautoscalercache replicas
  5. rejectcost-botbulk region drain
  6. admitmigratorapi schema v12
Head digest189f5d55…0f84c3ca

Roadmap

Ledger on disk. Replay comes next.

  1. 0.1

    The wall

    Intent model, admission control, policy gate, ledger, and demo.

  2. 0.2

    Scheduler

    Wide changes serialize, narrow work runs in parallel per resource, and contradictions wait for a human.

  3. 0.3

    Trustworthy ledger

    SHA-256 chain, signed records, and Merkle checkpoints.

  4. 0.4

    Replay

    Durable append-only state that rebuilds the plane after restart.

Pricing

Free to self-host. Simple plans on Floodwall Cloud.

  1. Self-host

    Freeforever, MIT licensed

    The open-source crate. Run the wall inside your own control plane.

    • Admission, scheduler and policy gate
    • Hold queue with human release
    • Signed, hash-chained ledger
    • Independent ledger verifier
  2. Free

    $0per month

    Floodwall Cloud for a team's first agents.

    • 1 plane
    • 25,000 decisions a month
    • 7-day hosted ledger
    • Up to 3 approvers
    • Community support
  3. Team

    Most teams

    $49per month, or $490 a year

    For teams putting agents on production changes.

    250,000 decisions included, then $0.30 per 1,000

    • Up to 5 planes
    • 90-day hosted ledger
    • Unlimited approvers
    • Approvals and alerts in Slack
    • Email support
  4. Business

    $399per month, or $3,990 a year

    For fleets where every change needs an audit trail.

    2.5M decisions included, then $0.20 per 1,000

    • Unlimited planes
    • 1-year hosted ledger, exported to your bucket
    • SSO and approver roles
    • Signed checkpoints, verified for you
    • 99.9% uptime SLA and priority support

Enterprise

Support for self-hosted planes, compliance evidence, custom retention and contracts.

Compare every plan

Early access

Gate your agents. Join the waitlist.

Sign up with your email, and we will let you in as early access opens.

Join the waitlist

Already have an account? Sign in.

diff --git a/docs/pricing/index.html b/docs/pricing/index.html new file mode 100644 index 0000000..2d9eb32 --- /dev/null +++ b/docs/pricing/index.html @@ -0,0 +1,69 @@ + + + + + + + + Floodwall | Policy Gates for Agent-Driven DevOps + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + diff --git a/docs/sitemap.xml b/docs/sitemap.xml index e2bf83d..5d42f7c 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -1,4 +1,5 @@ https://floodwall.ai/ + https://floodwall.ai/pricing diff --git a/site/public/sitemap.xml b/site/public/sitemap.xml index e2bf83d..5d42f7c 100644 --- a/site/public/sitemap.xml +++ b/site/public/sitemap.xml @@ -1,4 +1,5 @@ https://floodwall.ai/ + https://floodwall.ai/pricing diff --git a/site/scripts/build.mjs b/site/scripts/build.mjs index b957272..2a1f113 100644 --- a/site/scripts/build.mjs +++ b/site/scripts/build.mjs @@ -6,6 +6,8 @@ // - 404.html, the same page with #root left empty. GitHub Pages serves it for every other path // (/pricing, /login, /app/...), which the app then renders in the browser without first showing // the landing page. +// - pricing/index.html, that same shell, so /pricing answers 200 rather than GitHub Pages' 404 +// and search engines index it. import fs from "node:fs"; import path from "node:path"; import { parseArgs } from "node:util"; @@ -27,6 +29,8 @@ if (html.split(empty).length !== 2) throw new Error(`${page} must contain exactl const { render } = await import(pathToFileURL(path.join(ssrDir, "entry-server.js")).href); fs.writeFileSync(path.join(outDir, "404.html"), html); +fs.mkdirSync(path.join(outDir, "pricing"), { recursive: true }); +fs.writeFileSync(path.join(outDir, "pricing", "index.html"), html); // A replacer function, so `$&`-style patterns in the rendered page are written literally. fs.writeFileSync(page, html.replace(empty, () => `
${render()}
`)); fs.rmSync(ssrDir, { recursive: true, force: true }); diff --git a/site/src/App.tsx b/site/src/App.tsx index e7905e2..c01433d 100644 --- a/site/src/App.tsx +++ b/site/src/App.tsx @@ -3,6 +3,7 @@ import { LandingHero } from "./components/landing/LandingHero"; import { LandingLedgerSection } from "./components/landing/LandingLedgerSection"; import { LandingLineSection } from "./components/landing/LandingLineSection"; import { LandingModelSection } from "./components/landing/LandingModelSection"; +import { LandingPricingSection } from "./components/landing/LandingPricingSection"; import { LandingRoadmapSection } from "./components/landing/LandingRoadmapSection"; import { LandingWaitlistSection } from "./components/landing/LandingWaitlistSection"; import { SiteFooter } from "./components/shared/SiteFooter"; @@ -28,6 +29,7 @@ export default function App() { + diff --git a/site/src/components/billing/BillingCard.tsx b/site/src/components/billing/BillingCard.tsx new file mode 100644 index 0000000..884035f --- /dev/null +++ b/site/src/components/billing/BillingCard.tsx @@ -0,0 +1,92 @@ +import { useEffect, useState } from "react"; +import { BILLING_COPY, BILLING_RETURN_PARAM, PLAN_NAMES } from "../../constants/billing"; +import { PRICING_PATH } from "../../constants/pricing"; +import { billingAvailable } from "../../helpers/billing"; +import { useBilling } from "../../hooks/useBilling"; +import { authCard, monoLabel, pillOutline, pillSolid } from "../../styles/classes"; +import { Button } from "../ui/button"; +import { Card } from "../ui/card"; + +const dateFormat = new Intl.DateTimeFormat(undefined, { dateStyle: "medium" }); + +/** + * The account's plan, with the way to upgrade on Free, and Paygate's billing page (invoices, card, + * cancelling) on a paid plan. Coming back from Stripe Checkout (?billing=success) it asks Paygate + * for the plan, since the webhook may not have landed yet. + */ +export function BillingCard() { + const [returning] = useState( + () => typeof window !== "undefined" && new URLSearchParams(window.location.search).get(BILLING_RETURN_PARAM) === "success", + ); + const billing = useBilling(billingAvailable, { refreshFirst: returning }); + const [notice, setNotice] = useState(returning ? BILLING_COPY.checking : ""); + + useEffect(() => { + if (!returning || !billing.plan) return; + setNotice(billing.plan.plan === "free" ? BILLING_COPY.stillProcessing : BILLING_COPY.thanks); + // Drop the parameter so a reload doesn't say it again. + const url = new URL(window.location.href); + url.searchParams.delete(BILLING_RETURN_PARAM); + window.history.replaceState(window.history.state, "", url); + }, [returning, billing.plan]); + + if (!billingAvailable) { + return ( + +

{BILLING_COPY.title}

+

{BILLING_COPY.demo}

+
+ ); + } + + const plan = billing.plan; + const paid = !!plan && plan.plan !== "free"; + + return ( + +

{BILLING_COPY.title}

+ {plan && ( + <> +

+ {BILLING_COPY.plan} {PLAN_NAMES[plan.plan] ?? plan.plan} + {paid && plan.periodEnd && ( + + {" · "} + {plan.cancelAtPeriodEnd ? BILLING_COPY.ends : BILLING_COPY.renews} {dateFormat.format(plan.periodEnd)} + + )} +

+ {plan.status === "past_due" &&

{BILLING_COPY.pastDue}

} + {!paid &&

{BILLING_COPY.free}

} +
+ {paid ? ( + + ) : ( + <> + + + + )} + + {BILLING_COPY.compare} + +
+ + )} +

+ {billing.error || notice} +

+
+ ); +} diff --git a/site/src/components/landing/LandingPricingSection.tsx b/site/src/components/landing/LandingPricingSection.tsx new file mode 100644 index 0000000..35bd120 --- /dev/null +++ b/site/src/components/landing/LandingPricingSection.tsx @@ -0,0 +1,36 @@ +import { ArrowRight02Icon } from "@hugeicons/core-free-icons"; +import { PRICING_PATH } from "../../constants/links"; +import { ENTERPRISE_PLAN, PRICING_PLANS } from "../../constants/pricing"; +import { PricingPlanCard } from "../pricing/PricingPlanCard"; +import { Icon } from "../shared/Icon"; +import { LandingSectionHeading } from "./LandingSectionHeading"; + +/** + * The plans on the landing page: the same rail as /pricing, with plain links (the landing page is + * prerendered and has no session), and the way to the full comparison and FAQ. + */ +export function LandingPricingSection() { + return ( +
+
+ + Free to self-host. Simple plans on Floodwall Cloud. + +
    + {PRICING_PLANS.map((plan) => ( + + ))} +
+
+
+

{ENTERPRISE_PLAN.name}

+

{ENTERPRISE_PLAN.copy}

+
+ + Compare every plan + +
+
+
+ ); +} diff --git a/site/src/components/pricing/PricingHero.tsx b/site/src/components/pricing/PricingHero.tsx index 26d25a1..5dbba4d 100644 --- a/site/src/components/pricing/PricingHero.tsx +++ b/site/src/components/pricing/PricingHero.tsx @@ -3,10 +3,36 @@ import { EARLY_ACCESS_URL, REPO_URL } from "../../constants/links"; import { ENTERPRISE_PLAN, PRICING_PLANS } from "../../constants/pricing"; import { LandingSectionHeading } from "../landing/LandingSectionHeading"; import { Icon } from "../shared/Icon"; -import { PricingPlanCard } from "./PricingPlanCard"; +import { AUTH_PATHS } from "../../constants/auth"; +import { BILLING_COPY } from "../../constants/billing"; +import { billingAvailable } from "../../helpers/billing"; +import { useBilling } from "../../hooks/useBilling"; +import { useSession } from "../../hooks/useSession"; +import type { PricingPlan } from "../../constants/pricing"; +import { type PlanAction, PricingPlanCard } from "./PricingPlanCard"; /** The opening sheet: the offer, the four plans in one ruled rail, and Enterprise across their foot. */ export function PricingHero() { + const { session } = useSession(); + const member = session.status === "signedIn" && !session.user.waiting; + const billing = useBilling(member && billingAvailable); + + // Signed out, or in the demo, every card keeps its link (Get started opens sign-up). A + // signed-in account sees its own plan marked and can buy the others. + function actionFor(plan: PricingPlan): PlanAction { + if (!member || !billing.plan) return { kind: "link" }; + const current = billing.plan.plan; + if (plan.planKey === current || (plan.name === "Free" && current === "free")) return { kind: "current" }; + // Already paying: changing plan goes through the account page. + if (current !== "free") { + const sold = plan.planKey || plan.name === "Free"; + return sold ? { kind: "link", cta: { label: BILLING_COPY.manage, href: AUTH_PATHS.account } } : { kind: "link" }; + } + if (!plan.planKey) return { kind: "link" }; + const key = plan.planKey; + return { kind: "buy", busy: billing.busy === `${key}:month`, onBuy: () => void billing.checkout(key) }; + } + return (
@@ -16,7 +42,8 @@ export function PricingHero() {

The crate is open source and always free to run yourself. Floodwall Cloud hosts the ledger, approvals - and console for you, billed by the decisions your agents’ changes need. + and console for you: a monthly price that includes a generous number of decisions, then a small + charge for each thousand more.

Hosted plans by invitation during early access

@@ -32,9 +59,12 @@ export function PricingHero() {
    {PRICING_PLANS.map((plan) => ( - + ))}
+

+ {billing.error} +

{ENTERPRISE_PLAN.name}

diff --git a/site/src/components/pricing/PricingPlanCard.tsx b/site/src/components/pricing/PricingPlanCard.tsx index a2f6c2e..0b4ee76 100644 --- a/site/src/components/pricing/PricingPlanCard.tsx +++ b/site/src/components/pricing/PricingPlanCard.tsx @@ -1,13 +1,24 @@ import { ArrowRight02Icon } from "@hugeicons/core-free-icons"; +import { BILLING_COPY } from "../../constants/billing"; import type { PricingPlan } from "../../constants/pricing"; import { Icon } from "../shared/Icon"; +/** + * What the card's button does for this reader: a link (signed out, or a plan that isn't sold), the + * reader's own plan, or checkout for a signed-in account. + */ +export type PlanAction = + | { kind: "link"; cta?: { label: string; href: string } } + | { kind: "current" } + | { kind: "buy"; busy: boolean; onBuy: () => void }; + /** * One plan in the rail: its price, who it's for, what it includes, and how to start. The plan most * teams start on is marked in its title band and carries the one filled button. */ -export function PricingPlanCard({ plan }: { plan: PricingPlan }) { - const { name, price, priceNote, summary, typical, features, cta, featured } = plan; +export function PricingPlanCard({ plan, action = { kind: "link" } }: { plan: PricingPlan; action?: PlanAction }) { + const { name, price, priceNote, summary, typical, features, featured } = plan; + const cta = (action.kind === "link" && action.cta) || plan.cta; return (
  • @@ -23,7 +34,7 @@ export function PricingPlanCard({ plan }: { plan: PricingPlan }) {

    {summary}

    {typical && (

    - Typical spend {typical.spend}/mo for {typical.basis} + {typical.spend}, {typical.basis}

    )}
  • @@ -33,7 +44,19 @@ export function PricingPlanCard({ plan }: { plan: PricingPlan }) { ))}
    - {featured ? ( + {action.kind === "current" ? ( +

    {BILLING_COPY.current}

    + ) : action.kind === "buy" ? ( + + ) : featured ? ( {cta.label} diff --git a/site/src/components/shared/SiteHeader.tsx b/site/src/components/shared/SiteHeader.tsx index 99a8e43..efc6932 100644 --- a/site/src/components/shared/SiteHeader.tsx +++ b/site/src/components/shared/SiteHeader.tsx @@ -207,7 +207,7 @@ export function SiteHeader({ onLanding = true }: { onLanding?: boolean }) { href={href.startsWith("#") ? `${base}${href}` : href} data-section={id} data-current={isCurrent || undefined} - aria-current={isCurrent ? (id === "pricing" ? "page" : "location") : undefined} + aria-current={isCurrent ? (id === "pricing" && !onLanding ? "page" : "location") : undefined} > diff --git a/site/src/constants/billing.ts b/site/src/constants/billing.ts new file mode 100644 index 0000000..84f6c93 --- /dev/null +++ b/site/src/constants/billing.ts @@ -0,0 +1,32 @@ +// What the account page and the pricing page say about plans and payments. +// Payments run through Paygate, which runs Stripe; the sign-in service (api/) +// asks it for checkout and billing pages. + +import type { PaidPlanKey } from "./pricing"; + +export const PLAN_NAMES: Record = { free: "Free", team: "Team", business: "Business" }; + +/** The query parameter Stripe Checkout comes back to /account with. */ +export const BILLING_RETURN_PARAM = "billing"; + +export const BILLING_COPY = { + title: "Plan and billing", + plan: "Plan", + renews: "Renews", + ends: "Ends", + pastDue: "Your last payment didn't go through. Update your card to keep your plan.", + free: "You're on Free: one plane and 25,000 decisions a month.", + upgrade: (plan: PaidPlanKey) => `Move to ${PLAN_NAMES[plan]}`, + upgradeYearly: "Pay yearly, two months free", + manage: "Invoices, card and cancelling", + compare: "Compare plans", + opening: "Opening checkout…", + openingBilling: "Opening billing…", + checking: "Confirming your payment…", + thanks: "Thanks, your plan is active.", + stillProcessing: "Your payment is being processed. Your plan will show here in a minute.", + failed: "Billing could not be loaded. Please try again.", + demo: "Billing needs the sign-in service; this is the in-browser demo.", + current: "Your plan", + signInToBuy: "Sign in to upgrade", +}; diff --git a/site/src/constants/links.ts b/site/src/constants/links.ts index 6a7d063..70f1e78 100644 --- a/site/src/constants/links.ts +++ b/site/src/constants/links.ts @@ -38,7 +38,7 @@ export const NAV_LINKS = [ ] as const; /** Every landing section the header tracks, in page order; Home is the logo's. */ -export const NAV_SECTION_IDS = ["home", "line", "model", "gate", "ledger", "roadmap", "waitlist"] as const; +export const NAV_SECTION_IDS = ["home", "line", "model", "gate", "ledger", "roadmap", "pricing", "waitlist"] as const; export const FOOTER_GROUPS: { title: string; links: Link[] }[] = [ { @@ -48,6 +48,7 @@ export const FOOTER_GROUPS: { title: string; links: Link[] }[] = [ { label: "Model", href: "#model" }, { label: "Gate", href: "#gate" }, { label: "Ledger", href: "#ledger" }, + { label: "Pricing", href: PRICING_PATH }, { label: "Waitlist", href: "#waitlist" }, ], }, diff --git a/site/src/constants/pricing.ts b/site/src/constants/pricing.ts index e9cec7e..275b319 100644 --- a/site/src/constants/pricing.ts +++ b/site/src/constants/pricing.ts @@ -1,25 +1,32 @@ // Plans, prices and copy for the /pricing page. The prices are the working // proposal for Floodwall Cloud; they live here so they change in one place. +import { AUTH_PATHS } from "./auth"; import { EARLY_ACCESS_URL, PRICING_PATH, REPO_URL } from "./links"; export { PRICING_PATH }; +/** The plans Floodwall Cloud sells through Paygate; the keys match the plans set up there. */ +export type PaidPlanKey = "team" | "business"; +export type BillingInterval = "month" | "year"; + export type PricingPlan = { name: string; price: string; /** What the price is per, shown under it. */ priceNote: string; summary: string; - /** A worked month's bill, for the usage-based plans. */ + /** What the base price includes and what more costs, for the plans with a base fee. */ typical?: { spend: string; basis: string }; features: string[]; cta: { label: string; href: string }; + /** A plan that can be bought: the page offers checkout for it to a signed-in account. */ + planKey?: PaidPlanKey; /** The plan most teams start on, set apart from the others. */ featured?: boolean; }; -const EARLY_ACCESS = { label: "Request early access", href: EARLY_ACCESS_URL }; +const GET_STARTED = { label: "Get started", href: AUTH_PATHS.signup }; export const PRICING_PLANS: PricingPlan[] = [ { @@ -41,14 +48,14 @@ export const PRICING_PLANS: PricingPlan[] = [ priceNote: "per month", summary: "Floodwall Cloud for a team's first agents.", features: ["1 plane", "25,000 decisions a month", "7-day hosted ledger", "Up to 3 approvers", "Community support"], - cta: EARLY_ACCESS, + cta: GET_STARTED, }, { - name: "Launch", - price: "$0.40", - priceNote: "per 1,000 decisions", + name: "Team", + price: "$49", + priceNote: "per month, or $490 a year", summary: "For teams putting agents on production changes.", - typical: { spend: "$20", basis: "50,000 decisions" }, + typical: { spend: "250,000 decisions included", basis: "then $0.30 per 1,000" }, features: [ "Up to 5 planes", "90-day hosted ledger", @@ -56,15 +63,16 @@ export const PRICING_PLANS: PricingPlan[] = [ "Approvals and alerts in Slack", "Email support", ], - cta: EARLY_ACCESS, + cta: GET_STARTED, + planKey: "team", featured: true, }, { - name: "Scale", - price: "$0.60", - priceNote: "per 1,000 decisions", + name: "Business", + price: "$399", + priceNote: "per month, or $3,990 a year", summary: "For fleets where every change needs an audit trail.", - typical: { spend: "$600", basis: "1M decisions" }, + typical: { spend: "2.5M decisions included", basis: "then $0.20 per 1,000" }, features: [ "Unlimited planes", "1-year hosted ledger, exported to your bucket", @@ -72,7 +80,8 @@ export const PRICING_PLANS: PricingPlan[] = [ "Signed checkpoints, verified for you", "99.9% uptime SLA and priority support", ], - cta: EARLY_ACCESS, + cta: GET_STARTED, + planKey: "business", }, ]; @@ -104,8 +113,9 @@ export const INCLUDED_EVERYWHERE = [ /** One row per feature, one value per plan in PRICING_PLANS order. */ export const PRICING_COMPARISON: { feature: string; values: string[] }[] = [ - { feature: "Price", values: ["Free", "$0", "$0.40 per 1k decisions", "$0.60 per 1k decisions"] }, - { feature: "Decisions", values: ["Unlimited, on your hardware", "25,000 a month", "Usage-based", "Usage-based"] }, + { feature: "Price", values: ["Free", "$0", "$49 a month", "$399 a month"] }, + { feature: "Decisions included", values: ["Unlimited, on your hardware", "25,000 a month", "250,000 a month", "2.5M a month"] }, + { feature: "More decisions", values: ["—", "—", "$0.30 per 1k", "$0.20 per 1k"] }, { feature: "Planes", values: ["Unlimited", "1", "Up to 5", "Unlimited"] }, { feature: "Hosted ledger", values: ["You keep it", "7 days", "90 days", "1 year, plus export"] }, { feature: "Approvers", values: ["Unlimited", "Up to 3", "Unlimited", "Unlimited"] }, @@ -146,7 +156,7 @@ export const PRICING_FAQ = [ { question: "How do I estimate my bill?", answer: - "Count the changes your agents propose in a month. A fleet proposing 2,000 changes a day makes about 60,000 decisions, which is $24 on Launch.", + "Count the changes your agents propose in a month. A fleet proposing 2,000 changes a day makes about 60,000 decisions, which fits in Team's $49. At 15,000 a day, about 450,000 decisions, Team is $49 plus $60 for the 200,000 over.", }, { question: "What does Floodwall Cloud store?", @@ -156,6 +166,6 @@ export const PRICING_FAQ = [ { question: "When can I sign up?", answer: - "Hosted plans open by invitation during early access. The prices here are for planning and may change before general availability.", + "Create a free account now; during the beta, new accounts are let in a few at a time. Once you're in, you can move to Team or Business from this page or your account. Paying a year ahead gets two months free.", }, ]; diff --git a/site/src/helpers/billing.ts b/site/src/helpers/billing.ts new file mode 100644 index 0000000..62e1d60 --- /dev/null +++ b/site/src/helpers/billing.ts @@ -0,0 +1,35 @@ +// Plans and payments, through the sign-in service's /billing calls (api/src/billing.ts). The +// service asks Paygate for Stripe Checkout and the hosted billing page, so the site never sees a +// card or a key. In the in-browser demo, there is no billing. + +import { BILLING_COPY } from "../constants/billing"; +import type { BillingInterval, PaidPlanKey } from "../constants/pricing"; +import type { AccountPlan } from "../types/billing"; +import { callService } from "./auth"; +import { AUTH_API_URL } from "../constants/auth"; + +export const billingAvailable = !!AUTH_API_URL; + +function requireService() { + if (!billingAvailable) throw new Error(BILLING_COPY.demo); +} + +/** The signed-in account's plan. `refresh` asks Paygate first, e.g. straight after checkout. */ +export async function getPlan(refresh = false) { + requireService(); + return callService(refresh ? "/billing?refresh=1" : "/billing"); +} + +/** Sends the browser to Stripe Checkout for `plan`. Throws the service's sentence if it can't. */ +export async function startCheckout(plan: PaidPlanKey, interval: BillingInterval = "month") { + requireService(); + const { url } = await callService<{ url: string }>("/billing/checkout", { plan, interval }); + window.location.assign(url); +} + +/** Sends the browser to Paygate's billing page: invoices, card, cancel. */ +export async function openBilling() { + requireService(); + const { url } = await callService<{ url: string }>("/billing/manage", {}); + window.location.assign(url); +} diff --git a/site/src/hooks/useBilling.ts b/site/src/hooks/useBilling.ts new file mode 100644 index 0000000..d00a09f --- /dev/null +++ b/site/src/hooks/useBilling.ts @@ -0,0 +1,52 @@ +import { useCallback, useEffect, useState } from "react"; +import { billingAvailable, getPlan, openBilling, startCheckout } from "../helpers/billing"; +import type { BillingInterval, PaidPlanKey } from "../constants/pricing"; +import type { AccountPlan } from "../types/billing"; + +/** + * The signed-in account's plan, and the two ways out to pay: checkout and the billing page. Only + * asks the service when `enabled` (a signed-in account past the waitlist). + */ +export function useBilling(enabled: boolean, { refreshFirst = false } = {}) { + const [plan, setPlan] = useState(null); + const [error, setError] = useState(""); + const [busy, setBusy] = useState(null); + + const load = useCallback(async (refresh: boolean) => { + setError(""); + try { + const next = await getPlan(refresh); + setPlan(next); + return next; + } catch (e) { + setError((e as Error).message); + return null; + } + }, []); + + useEffect(() => { + if (enabled && billingAvailable) void load(refreshFirst); + }, [enabled, refreshFirst, load]); + + async function run(label: string, action: () => Promise) { + setBusy(label); + setError(""); + try { + await action(); + // The page is on its way to Stripe or Paygate: stay busy until it leaves. + } catch (e) { + setError((e as Error).message); + setBusy(null); + } + } + + return { + plan, + error, + busy, + reload: load, + checkout: (key: PaidPlanKey, interval: BillingInterval = "month") => + run(`${key}:${interval}`, () => startCheckout(key, interval)), + manage: () => run("manage", openBilling), + }; +} diff --git a/site/src/pages/AccountPage.tsx b/site/src/pages/AccountPage.tsx index 29009a6..2359932 100644 --- a/site/src/pages/AccountPage.tsx +++ b/site/src/pages/AccountPage.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { Navigate, useNavigate } from "react-router"; import { AuthPage } from "../components/auth/AuthPage"; import { SessionUnavailable } from "../components/auth/SessionUnavailable"; +import { BillingCard } from "../components/billing/BillingCard"; import { ButtonLink } from "../components/shared/ButtonLink"; import { Button } from "../components/ui/button"; import { Card } from "../components/ui/card"; @@ -56,6 +57,7 @@ export function AccountPage() { {status}

    + {session.status === "signedIn" && } ); } diff --git a/site/src/pages/PricingPage.tsx b/site/src/pages/PricingPage.tsx index 9c4e893..e3552a6 100644 --- a/site/src/pages/PricingPage.tsx +++ b/site/src/pages/PricingPage.tsx @@ -4,13 +4,10 @@ import { PricingHero } from "../components/pricing/PricingHero"; import { PricingIncludedSection } from "../components/pricing/PricingIncludedSection"; import { PricingProgramsSection } from "../components/pricing/PricingProgramsSection"; -/** Floodwall's plans: free to self-host, usage-based on Floodwall Cloud. Reachable by URL only. */ +/** Floodwall's plans: free to self-host, a base price plus overage on Floodwall Cloud. */ export function PricingPage() { return ( <> - {/* Kept out of search, like the console, until the page goes public: - * then drop this tag and list /pricing in public/sitemap.xml. */} - diff --git a/site/src/types/billing.ts b/site/src/types/billing.ts new file mode 100644 index 0000000..a155633 --- /dev/null +++ b/site/src/types/billing.ts @@ -0,0 +1,12 @@ +/** An account's plan, as the sign-in service keeps it (GET /billing). */ +export type AccountPlan = { + /** "free", "team" or "business". */ + plan: string; + /** Paygate's subscription status: active, trialing, past_due, canceled; null on Free. */ + status: string | null; + /** The plan's limits, from Paygate: planes, decisions_included, retention_days, … */ + features: Record | null; + /** When the period ends, in ms since the epoch. */ + periodEnd: number | null; + cancelAtPeriodEnd: boolean; +};