diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f2a9244..1061fc7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,28 +37,13 @@ jobs: - name: Build production bundle run: npm run build - # The test:ui and test:accessibility scripts land with the milestone - # branches; until they do, npm exits "Missing script" and fails the - # required check, so these steps only run when the scripts exist. - - name: Check for browser test suites - id: browser-tests - run: | - node -e ' - const s = require("./package.json").scripts; - require("fs").appendFileSync(process.env.GITHUB_OUTPUT, - `ui=${s["test:ui"] ? "yes" : "no"}\naccessibility=${s["test:accessibility"] ? "yes" : "no"}\n`); - ' - - name: Install Playwright Chromium - if: steps.browser-tests.outputs.ui == 'yes' || steps.browser-tests.outputs.accessibility == 'yes' run: npx playwright install chromium --with-deps - name: Run browser tests - if: steps.browser-tests.outputs.ui == 'yes' run: npm run test:ui - name: Run accessibility modal tests - if: steps.browser-tests.outputs.accessibility == 'yes' run: npm run test:accessibility - name: Run deploy guard diff --git a/.gitignore b/.gitignore index 507b2da..459486c 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,6 @@ BUILDSHIP_REVIEW_SYSTEM_PROMPT.txt BUILDSHIP_REVIEW_SYSTEM_PROMPT_UPDATED.txt /graphify-out /.playwright-mcp + +# Playwright run artifacts +test-results/ diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 8e8dbd8..3947986 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -92,15 +92,10 @@ reported rather than silently dropped: * It imports something FlutterFlow only generates once the app is built - `/backend/schema/structs/index.dart`, `../flutter_flow/lat_lng.dart`. Those files do not exist until after the deploy. -* The project declares a dependency from a source this manifest cannot - express - a `git:` or `path:` source, a private `hosted:` block, or a - `dependency_overrides` entry written that way - and the class resolves - packages at all. `pubspec.lock`, the only document recording which packages - that source brings in, never leaves the project, so the unreproducible - package can sit anywhere in the class's transitive closure and an override - can rewrite any name in the graph. The scratch package would resolve - different code, and a check against the wrong version reports a result that - does not describe what ships. +* It imports a package the project declares from a source this manifest cannot + express: a `git:` or `path:` source, or a nested `hosted:` block. The scratch + package would resolve different code, and a check against the wrong version + reports a result that does not describe what ships. The second case is decided once per deploy, not per class, because a project-level source can alter resolution for a class that never names it. A @@ -111,11 +106,14 @@ nothing through pub and is still compiled. **Which packages the Flutter SDK supplies is read from the project's own pubspec** - a dependency written in block form under `sdk:` is an SDK package by -definition. Nothing keeps a list of SDK package names, because a list goes stale -the moment the SDK ships one it has not heard of, and a stale list reads a -perfectly valid package as unreproducible. That is not hypothetical: a list -missing `flutter_web_plugins` refused whole deploys for projects that declared -it. +definition. A small name list still exists, but only for names the pubspec does +not declare at all: a package the code imports and the project lacks is written +as `sdk: flutter` when the SDK supplies it, so discovery never emits a hosted +constraint pub.dev cannot resolve. A name the list has not heard of degrades to +the ordinary hosted lookup, not a wrong answer. For declared dependencies the +list plays no part - the pubspec's own keys are the authority, because a stale +list read a perfectly valid `flutter_web_plugins` declaration as +unreproducible and refused whole deploys over it. The manifest is sent as package names and version constraints, never as pubspec.yaml text, and the runner builds the document itself - it runs @@ -151,6 +149,10 @@ https://ccc-ffai-runner-y5cyj3473a-uw.a.run.app/deployCustomClasses Override it at build time with `VITE_FLUTTERFLOW_CLASS_PROVISION_ENDPOINT`. `VITE_FLUTTERFLOW_DSL_DEPLOY_ENDPOINT` remains accepted for compatibility. +Under `npm run dev` the app instead calls the same-origin path +`/api/ffai-runner/deployCustomClasses`, which the Vite dev server proxies to +the runner — its CORS allowlist admits only the production origin, so a direct +browser call from localhost is rejected before the request reaches it. Deploy the runner with: ```bash diff --git a/app.js b/app.js index ac24de8..2a520a6 100644 --- a/app.js +++ b/app.js @@ -1,4 +1,16 @@ import posthog from "posthog-js"; +import { + closeModal, + hasActiveModal, + initializeModalShells, + openModal, + setModalPending, +} from "./src/sharedControls.js"; +import { + PLAN_LABELS as planLabels, + PLAN_LIMITS as planLimits, + PLAN_FEATURES as planFeatures, +} from "./src/plansSurface.js"; import { getPrimaryArtifact, normalizeArtifactBundle, @@ -32,9 +44,36 @@ import { } from "./src/flutterFlowCodeSanitizer.js"; import { formatFlutterFlowFileError } from "./src/flutterFlowFileErrors.js"; import { extractPackageImports } from "./src/dartPackageImports.js"; +import { + explainPlusAliasRule, + getMagicLinkResultMessage, + isKnownProviderPlusAlias, + isMagicLinkSuccess, + trimEmail, +} from "./src/authMagicLink.js"; +import { + clearDisposableUiCaches, + createSendLinkController, + isDeleteAccountSupported, + performSignOut, +} from "./src/accountAccess.js"; import { planCustomCodeVerification } from "./src/customCodeVerification.js"; -import { readProvisionResponse } from "./src/provisionStream.js"; +import { + deployOutcomeOfStreamResult, + isPreWriteRunnerFailure, + readProvisionResponse, +} from "./src/provisionStream.js"; +import { + classifyDeployResult, + DeployOutcome, + DEPLOY_UI_TIMEOUT_MS, + exhaustedPushError, + PUSH_BODY_READ_TIMEOUT_MS, + UnconfirmedDeployError, +} from "./src/deployOutcome.js"; import { buildFlutterFlowSyncMetadata } from "./src/flutterFlowSyncMetadata.js"; +import { initHeroMarkField } from "./src/heroMarkField.js"; +import { createPipelineLogoLoop } from "./src/logoMotion.js"; import { applyDependencyOverrides, mergeDependenciesIntoYaml, @@ -42,19 +81,26 @@ import { } from "./src/pubspecSync.js"; import { planDependencyChanges } from "./src/dependencyResolution.js"; import { escapeAttr, escapeHtml, escapeHtmlText } from "./src/htmlEscape.js"; -import { resolvePipelineErrorStep } from "./src/pipelineErrors.js"; +import { resolvePipelineErrorStep, classifyPipelineError } from "./src/pipelineErrors.js"; import { extractCodeFromMarkdown, highlightCode, renderMarkdownAudit, } from "./src/auditRenderer.js"; +import { initComposer } from "./src/composerAdapter.js"; +import { cancelSurfaceMotion, currentSurfaceRect, morphSurface, exitHero } from "./src/surfaceMotion.js"; // --- CONFIGURATION --- const IS_DEV = import.meta.env.DEV +// The runner's CORS allowlist admits only the production origin, so a dev +// server must reach it through Vite's same-origin /api/ffai-runner proxy +// rather than calling the runner directly. const FLUTTERFLOW_CLASS_PROVISION_ENDPOINT = import.meta.env.VITE_FLUTTERFLOW_CLASS_PROVISION_ENDPOINT || import.meta.env.VITE_FLUTTERFLOW_DSL_DEPLOY_ENDPOINT || - "https://ccc-ffai-runner-y5cyj3473a-uw.a.run.app/deployCustomClasses"; + (IS_DEV + ? "/api/ffai-runner/deployCustomClasses" + : "https://ccc-ffai-runner-y5cyj3473a-uw.a.run.app/deployCustomClasses"); // --- ANALYTICS --- const POSTHOG_KEY = import.meta.env.VITE_PUBLIC_POSTHOG_KEY; @@ -85,6 +131,11 @@ const STRIPE_PRICE_IDS = { } const AUTH_SESSION_STORAGE_KEY = 'ccc_auth_session' +// Where the user asked to sign in from (composer, plans, billing…), so a +// magic-link round trip — which reloads the page with no memory of the DOM — +// can return them to that surface instead of always landing on home. +const SIGNIN_RETURN_STORAGE_KEY = 'ccc_signin_return' +const SIGNIN_RETURN_TTL_MS = 30 * 60 * 1000 const proGateAttachedSet = new WeakSet() @@ -108,6 +159,11 @@ function createSubscriptionState(overrides = {}) { let subscriptionState = createSubscriptionState({ isResolved: true }) +// Settles once startup auth + subscription fetches finish. The composer binds +// before they complete, so a submission that lands early waits on this rather +// than checking entitlements against free-tier defaults. +let sessionReadiness = Promise.resolve() + // --- PIPELINE --- const PIPELINE_ENDPOINT = `${BUILDSHIP_BASE_URL}/service/runpipeline` @@ -125,11 +181,9 @@ let identityState = { } // --- TIER LIMITS --- -const TIER_LIMITS = { - free: 2, - professional: 50, - power: 2000, -} +// Single source of truth in src/plansSurface.js so the plans page, the +// paywall and generation gating agree (STU-382 criterion 1). +const TIER_LIMITS = planLimits; const SUBSCRIPTION_CACHE_KEY = 'ccc_subscription' const SUBSCRIPTION_CACHE_VERSION = 3 @@ -188,23 +242,51 @@ const PIPELINE_IMAGE_ENDPOINT = // what actually gets sent to the pipeline. let promptImages = [] // Array of { dataUrl, name, url } -function readAsDataUrl(file) { +// In-flight attachment uploads, one entry per file: { slot, controller, job }. +// A submission that lands mid-upload waits on these before snapshotting +// promptImages, and the composer gates Send/Enter while any are pending. +// Ordering and cap claims live on the reserved slots in promptImages itself +// (url === null while a slot is pending); removing a slot aborts its entry. +const pendingImageUploads = [] + +// An unresponsive upload endpoint must not gate the composer forever. +const PROMPT_IMAGE_UPLOAD_TIMEOUT_MS = 30000 + +// Handle returned by initComposer; lets attachment state gate the Send button. +let composerControls = null + +function readAsDataUrl(file, signal) { return new Promise((resolve) => { const reader = new FileReader() - reader.onload = () => resolve(reader.result) - reader.onerror = () => resolve(null) + const done = (value) => { + signal?.removeEventListener("abort", onAbort) + resolve(value) + } + const onAbort = () => { + reader.abort() + done(null) + } + reader.onload = () => done(reader.result) + reader.onerror = () => done(null) + // The upload timeout aborts this too: a FileReader that never settles + // must not hold its slot (and the send gate) forever. + if (signal) { + if (signal.aborted) { resolve(null); return } + signal.addEventListener("abort", onAbort, { once: true }) + } reader.readAsDataURL(file) }) } // Uploads one image file to the BuildShip image endpoint. The endpoint is // called separately from the pipeline so we pass real URLs, not base64. -async function uploadPromptImage(file) { +async function uploadPromptImage(file, signal) { const formData = new FormData() formData.append("file", file) const res = await fetch(PIPELINE_IMAGE_ENDPOINT, { method: "POST", body: formData, + signal, }) return res.json() } @@ -245,9 +327,78 @@ function uploadedFileUrl(uploaded) { return "" } +// Uploads one selected file into its reserved promptImages slot. The slot +// fixes the file's position and its claim on the cap at selection time; on +// failure the slot is removed, on user removal the commit is skipped. +// Resolves "added", "failed" (no usable upload URL, including a timeout), +// or "dropped" (the slot was removed while the upload was in flight). +async function addPromptImage(file, slot, signal) { + const dataUrl = await readAsDataUrl(file, signal) + if (dataUrl && promptImages.includes(slot)) { + // Fast local preview while the upload is still in flight. + slot.dataUrl = dataUrl + renderPromptImages() + } + let url = "" + if (dataUrl) { + try { + url = uploadedFileUrl(await uploadPromptImage(file, signal)) + } catch (e) { + url = "" + } + } + // The slot may have been removed while the upload was in flight (remove + // button, or a non-vision model switch clearing attachments) — commit + // nothing then. discardImageUpload has already released the pending gate. + if (!promptImages.includes(slot)) return "dropped" + // A file that never produced an upload URL is reported by the caller and + // its slot removed — keeping it would render a thumbnail the pipeline + // silently filters out of the payload. + if (!dataUrl || !url) { + promptImages.splice(promptImages.indexOf(slot), 1) + renderPromptImages() + return "failed" + } + slot.url = url + renderPromptImages() + return "added" +} + +function releaseImageUpload(entry) { + const i = pendingImageUploads.indexOf(entry) + if (i >= 0) pendingImageUploads.splice(i, 1) + updateAttachmentPending() +} + +// Drop a pending upload: abort its request, free the send gate immediately, +// and pull the slot if it is still attached. A settled upload is already out +// of pendingImageUploads and can't reach this path. +function discardImageUpload(entry) { + entry.controller.abort() + releaseImageUpload(entry) + const i = promptImages.indexOf(entry.slot) + if (i >= 0) { + promptImages.splice(i, 1) + renderPromptImages() + } +} + +function updateAttachmentPending() { + composerControls?.setAttachmentsPending(pendingImageUploads.length > 0) +} + async function handlePromptImageSelect(event) { const files = Array.from(event.target.files || []) if (!files.length) return + // Clear immediately so picking the same files again fires a change event. + event.target.value = "" + + // A run already in flight has snapshotted its attachments; refuse new + // selections so an upload can't appear to belong to a run that omitted it. + if (pipelineState.isRunning) { + showToast("Wait for the current generation to finish before attaching images.", "info") + return + } // Drop oversized files up front rather than uploading/reading them. const oversized = files.filter((f) => f.size > MAX_PROMPT_IMAGE_BYTES) @@ -258,46 +409,61 @@ async function handlePromptImageSelect(event) { ) } const validFiles = files.filter((f) => f.size <= MAX_PROMPT_IMAGE_BYTES) - if (!validFiles.length) { - event.target.value = "" - return - } + if (!validFiles.length) return + // Reserved slots already count toward the cap, so a second selection can't + // claim slots the first one is still filling. const remaining = MAX_PROMPT_IMAGES - promptImages.length const toAdd = validFiles.slice(0, remaining) - - const jobs = toAdd.map(async (file) => { - const dataUrl = await readAsDataUrl(file) - if (!dataUrl) return null - let url = "" - try { - url = uploadedFileUrl(await uploadPromptImage(file)) - } catch (e) { - url = "" - } - return { dataUrl, name: file.name, url } - }) - - const added = (await Promise.all(jobs)).filter(Boolean) - event.target.value = "" - // A non-vision model may have been selected while uploading; don't restore - // images that the model-change handler cleared. - if ( - added.length && - !modelSupportsImages( - document.getElementById("code-generator-model")?.value, - ) - ) { - return - } - promptImages.push(...added) if (validFiles.length > remaining) { showToast(`You can attach up to ${MAX_PROMPT_IMAGES} images.`, "info") } + if (!toAdd.length) return + + const jobs = toAdd.map((file) => { + // Reserve the ordered slot synchronously: thumbnails and the payload keep + // selection order even when uploads finish out of order. + const slot = { dataUrl: null, name: file.name, url: null } + promptImages.push(slot) + const entry = { slot, controller: new AbortController() } + const timeoutId = setTimeout( + () => entry.controller.abort(), + PROMPT_IMAGE_UPLOAD_TIMEOUT_MS, + ) + entry.job = addPromptImage(file, slot, entry.controller.signal) + pendingImageUploads.push(entry) + entry.job.finally(() => { + clearTimeout(timeoutId) + releaseImageUpload(entry) + }) + return entry.job + }) renderPromptImages() + updateAttachmentPending() + + const results = await Promise.all(jobs) + const failed = results.filter((r) => r === "failed").length + if (failed) { + showToast(`${failed} image(s) could not be uploaded and were not attached.`, "error") + } } function removePromptImage(index) { + // A run already in flight snapshotted its attachments: removing a slot now + // would abort the upload that slot was promised, silently dropping a + // submitted image from the run's payload. + if (pipelineState.isRunning) { + showToast("Wait for the current generation to finish before removing images.", "info") + return + } + const slot = promptImages[index] + const entry = pendingImageUploads.find((e) => e.slot === slot) + // Removing a pending thumbnail aborts its upload and frees the send gate + // right away instead of waiting on the abandoned request. + if (entry) { + discardImageUpload(entry) + return + } promptImages.splice(index, 1) renderPromptImages() } @@ -310,9 +476,11 @@ function renderPromptImages() { container.innerHTML = "" promptImages.forEach((img, i) => { const el = document.createElement("div") - el.className = "prompt-img-thumb" + // A slot whose upload is still in flight (url === null) renders dimmed + // with a spinner; it can already carry a local dataUrl preview. + el.className = "prompt-img-thumb" + (img.url ? "" : " is-pending") el.innerHTML = - `Prompt image` + + (img.dataUrl ? `Prompt image` : "") + `` container.appendChild(el) }) @@ -329,8 +497,13 @@ function updatePromptImageAvailability() { const select = document.getElementById("code-generator-model") const supports = modelSupportsImages(select?.value) section.classList.toggle("hidden", !supports) - // Non-vision models have no way to consume images: drop any already attached. - if (!supports && promptImages.length) { + // Non-vision models have no way to consume images: drop any already + // attached. A run already in flight snapshotted its attachments — dropping + // them now would abort uploads the run's frozen slice still expects to + // commit, silently stripping the images it was started with. + if (!supports && promptImages.length && !pipelineState.isRunning) { + // Abort uploads still in flight so they release the send gate now. + pendingImageUploads.slice().forEach(discardImageUpload) promptImages = [] renderPromptImages() } @@ -894,6 +1067,7 @@ function getFlutterFlowEndpoint() { function setFlutterFlowEndpoint(endpoint) { localStorage.setItem("flutterflow_api_endpoint", endpoint); + invalidateStaleProjectSelection(); return true; } @@ -918,6 +1092,158 @@ let commitTargetProjectId = null; // modal's dropdown when the modal is closed/reopened before the fetch returns. let confirmProjectToken = 0; +// Canonical account-connection state for the account connection card. It is +// derived from the outcome of a real FlutterFlow projects fetch — never from +// the presence of stored bytes alone and never from the placeholder token +// "set". 'connected' is only reachable from an actual listProjects response +// that returned at least one project. +// kind: 'not-configured' | 'validating' | 'connected' | 'no-projects' +// | 'unauthorized' | 'network-error' +let ffConnectionState = "not-configured"; + +// Monotonic generation of the configured FlutterFlow endpoint. Every project +// fetch and connection check captures it when it starts and discards its +// outcome if the generation moved on, so a late response from a previous +// endpoint can never overwrite the current endpoint's status or project list. +let ffEndpointGeneration = 0; + +// Monotonic sequences of started projects requests. The dropdown fetch and the +// connection check are independent consumers of the same endpoint, so each kind +// keeps its own sequence: a check starting while a fetch is pending must not +// discard the fetch's response (which would strand the dropdown on +// "Loading projects..." forever), and a newer fetch must not discard a pending +// check. Within one kind only the newest request may apply its outcome, so a +// late response for a key that has since been replaced — or one superseded by a +// newer same-kind request — can never overwrite the new key's project list or +// status, even when the endpoint did not change. +let ffProjectFetchSeq = 0; +let ffConnectionCheckSeq = 0; + +// Issue order across BOTH request kinds. The dropdown fetch and the +// connection check are superseded independently within their kind, but they +// write shared state — the account connection status and the stored +// project's confirmation. Ordering is split by what a request writes: an +// applied CONNECTION outcome (the account status card) may only be written by +// a request that actually produces one, so a list response that updates the +// deploy dialog never leaves a pending check unable to settle the card; an +// applied CONFIRMATION (the stored target's binding) is ordered separately so +// the newest list response always wins the stored selection. A request may +// write a domain only while no newer request already applied that domain. +let ffRequestOrderSeq = 0; +let ffAppliedOutcomeOrder = 0; +let ffAppliedConfirmationOrder = 0; + +// Identity binding for project selections. A selection is only usable as a +// deploy target while it is confirmed for the key + endpoint generation it was +// made under. This binding is the one thing every read of a selection checks, +// so a key replacement or endpoint change makes every previously confirmed +// selection unusable until a completed listProjects response re-confirms it or +// it is cleared. See isProjectSelectionConfirmed. +let projectSelectionIdentity = null; // { projectId, key, generation } | null + +// Identity of the list currently populating the API-key editor's project +// dropdown: the key + endpoint generation whose completed fetch produced the +// options on screen. Starting a fetch clears it (the options are replaced by +// the loading placeholder); only an applied response sets it. +let projectListIdentity = null; // { key, generation } | null + +// Identity of the list currently populating the deploy confirmation modal's +// project dropdown. A target may only be read from that dropdown while this +// identity still matches the current key + endpoint generation. +let confirmProjectListIdentity = null; // { key, generation } | null + +function beginProjectFetch() { + ffProjectFetchSeq += 1; + return ffProjectFetchSeq; +} + +function beginConnectionCheck() { + ffConnectionCheckSeq += 1; + return ffConnectionCheckSeq; +} + +/** + * Binds a project selection to the identity that produced it. The selection is + * an option of a completed fetch's list, so the binding copies that list's + * identity (the key it was fetched with and the endpoint generation it ran in). + * Called from the dropdown's change handler (a user choice) and when a + * completed response lists the stored selection (a re-confirmation). + */ +function bindProjectSelection(projectId, key, generation) { + projectSelectionIdentity = projectId ? { projectId, key, generation } : null; +} + +/** + * The single gate every read of a project selection goes through. A selection + * may be used as the deploy target only while the binding names the same + * project and was confirmed under the key + endpoint generation being checked. + * A key replacement or endpoint change moves one of them, so the selection + * stops matching and cannot be read as a target until a completed fetch + * re-confirms it. The key is a parameter so the save path can check the key it + * is saving before that key has been loaded into memory. + */ +function isProjectSelectionConfirmed(projectId, key = flutterflowApiKey) { + if (!projectId) return false; + const identity = projectSelectionIdentity; + if (!identity) return false; + return ( + identity.projectId === projectId && + identity.key === key && + identity.generation === ffEndpointGeneration + ); +} + +/** + * Reconciles the stored selection against a completed listProjects response + * for the current key + endpoint. A response that lists the stored project + * re-confirms it; one that does not strips its confirmation, so no later read + * can deploy to a project this key's completed response did not offer. + * Storage is left alone — the account card keeps mirroring the stored + * configuration; only the deploy gate changes. An in-flight explicit choice + * for a different project is never overwritten. + */ +function reconcileStoredProjectSelection(projects, key, generation) { + if (!flutterflowProjectId) return; + if ( + projectSelectionIdentity && + projectSelectionIdentity.projectId !== flutterflowProjectId + ) { + return; + } + const listed = (projects || []).some( + (project) => (project.id || project.projectId) === flutterflowProjectId, + ); + if (listed) { + bindProjectSelection(flutterflowProjectId, key, generation); + } else if (projectSelectionIdentity) { + bindProjectSelection("", null, null); + } +} + +/** + * Whether a projects request's outcome still describes the current connection + * identity and may be applied. Three things can move under an in-flight + * request: the endpoint (ffEndpointGeneration), the configured key (a + * replacement or a clear), and the newest request of the same kind (a newer + * fetch supersedes every older fetch; a newer check every older check). A + * response that lost any of them must not populate the current key's project + * list or connection status. A request made with the currently configured key + * stays valid even when it was issued before that key was saved — that is the + * editor's preview fetch. + */ +function isCurrentProjectRequest({ + seq, + currentSeq, + generation, + storedKeyAtStart, + requestKey, +}) { + if (seq !== currentSeq) return false; + if (generation !== ffEndpointGeneration) return false; + return storedKeyAtStart === flutterflowApiKey + || requestKey === flutterflowApiKey; +} + async function initializeApiKeys() { // Remove an exportable key left by an earlier version even if its encrypted // credentials were already cleared. @@ -928,13 +1254,30 @@ async function initializeApiKeys() { flutterflowProjectId = await getApiKey("flutterflow_project_id"); updateApiKeyStatusIndicators(); updateDeployButtonVisibility(); + + // If a FlutterFlow key is stored, confirm the real connection even before + // the settings modal is opened, so the account connection card is truthful + // on load. Non-blocking; runs once per initialize. + if (flutterflowApiKey) { + validateFlutterFlowConnection(); + } else { + ffConnectionState = "not-configured"; + renderApiKeyConnection(); + } } // --- API KEY UI FUNCTIONS --- -function openApiKeysModal() { +// Onboarding-scoped editor re-entry. The walkthrough's own "connect account" +// step sets this before opening the shared API-key editor so that closing it +// returns to (and advances) the tour. Settings opened from any other surface +// (account card, gear, commit flow) stays false, so closing those never +// launches or advances the walkthrough. +let walkthroughSettingsActive = false; + +function openApiKeysModalBody() { const modal = document.getElementById("api-keys-modal"); - modal.classList.add("open"); + openModal(modal); // Load current keys into inputs (masked) loadApiKeyInputs(); @@ -946,17 +1289,153 @@ function openApiKeysModal() { } } +function openApiKeysModal() { + // A standalone settings visit, not onboarding: closing it must not touch the + // walkthrough. + walkthroughSettingsActive = false; + openApiKeysModalBody(); +} + +// Entered by the walkthrough's "Connect your FlutterFlow account" step. Routes +// the user to the real account control and remembers, on this one close, to +// return to the originating tour step. +function walkthroughConnectAccount() { + walkthroughSettingsActive = true; + // Close the tour first so the shared editor never stacks on top of it. + const wt = document.getElementById("walkthrough-modal"); + if (wt) closeModal(wt); + openApiKeysModalBody(); +} + +// --- Composer generation settings (STU-385) --- +// +// The composer's gear opens this dialog, which presents the existing model +// selector and supported generation options. #code-generator-model still lives +// here and remains the single element the generation pipeline reads, so +// selections made in this dialog reach the actual request unchanged — no +// key-storage or transport change. Provider-key management is a shortcut into +// the canonical account connection editor (openApiKeysModal, STU-384), never a +// second independent editor. +// +// Closing this dialog from normal use must never reopen the walkthrough: the +// featured bug the milestone tracks is an ordinary settings close resuming +// onboarding. openComposerSettings runs with the standalone flag set (NOT the +// walkthrough-originating flag), so closeComposerSettings leaves the walkthrough +// untouched; only the walkthrough's own connect step flips that flag. + +let composerSettingsChangeWired = false; + +/** + * Keep the dialog's model mirror in step with the canonical #code-generator-model + * selector that still lives on the page. The mirror copies the canonical value, + * reuses the canonical availability labels (free tier marks PRO models "(PRO)"), + * and mirrors the canonical free-tier upgrade notice — so the dialog never + * drifts from the page or the pipeline. #code-generator-model remains the single + * element the generation request reads. + */ +function syncComposerSettingsModel() { + const canonical = document.getElementById("code-generator-model"); + const mirror = document.getElementById("composer-settings-model"); + if (!canonical || !mirror) return; + mirror.value = canonical.value; + const canonicalOptions = Array.from(canonical.options); + Array.from(mirror.options).forEach((mo, i) => { + const co = canonicalOptions[i]; + if (co) mo.textContent = co.textContent; + }); + const mirrorNotice = document.getElementById("composer-settings-free-notice"); + if (mirrorNotice) { + if (document.getElementById("model-selector-free-notice")) { + mirrorNotice.hidden = false; + mirrorNotice.innerHTML = + `Free plan — Gemini only. ` + + ``; + } else { + mirrorNotice.hidden = true; + } + } +} + +/** + * Reflect the selected model's supported generation options into the dialog and + * keep the composer's image-attach affordance in step (vision model → attach + * allowed; non-vision model → attach hidden and any attached images dropped). + */ +function renderComposerSettingsOptions() { + const select = document.getElementById("code-generator-model"); + const capability = document.getElementById("composer-image-capability"); + const note = document.getElementById("composer-image-capability-note"); + if (!select) return; + const label = getModelLabel(select.value); + const supports = modelSupportsImages(select.value); + if (capability) { + capability.textContent = supports ? "Supported" : "Not supported"; + } + if (note) { + note.textContent = supports + ? `${label} accepts reference images you attach to the prompt.` + : `Images can't be attached with ${label}. Attached images are removed when you switch to it.`; + } + updatePromptImageAvailability(); +} + +function openComposerSettings() { + // A standalone settings visit, not onboarding: closing it must not touch the + // walkthrough (same contract as openApiKeysModal). + walkthroughSettingsActive = false; + syncComposerSettingsModel(); + renderComposerSettingsOptions(); + if (!composerSettingsChangeWired) { + const mirror = document.getElementById("composer-settings-model"); + if (mirror) { + mirror.addEventListener("change", () => { + // Forward the dialog selection to the canonical selector and let its + // existing handler apply gating (PRO-on-free resets to FREE_MODEL and + // opens pricing), model info and image-capability updates. Then resync + // the mirror to reflect any reset and refresh the dialog's rows. + const canonical = document.getElementById("code-generator-model"); + canonical.value = mirror.value; + canonical.dispatchEvent(new Event("change")); + syncComposerSettingsModel(); + renderComposerSettingsOptions(); + }); + } + composerSettingsChangeWired = true; + } + const trigger = document.querySelector( + '.composer [aria-label="Generation settings"]', + ); + openModal("composer-settings-modal", { trigger }); +} + +function closeComposerSettings(event) { + if (event && event.target !== event.currentTarget) return; + closeModal("composer-settings-modal"); +} + function closeApiKeysModal(event) { if (event && event.target !== event.currentTarget) return; const modal = document.getElementById("api-keys-modal"); if (modal) { - modal.classList.remove("open"); - } - // Show walkthrough again after closing API keys - const walkthroughModal = document.getElementById("walkthrough-modal"); - if (walkthroughModal) { - advanceWalkthrough(); - walkthroughModal.classList.add("open"); + closeModal(modal); + } + const fromWalkthrough = walkthroughSettingsActive; + walkthroughSettingsActive = false; + if (fromWalkthrough) { + // Return to the originating walkthrough step. Advance only when the + // account is genuinely connected, per the STU-384 canonical connection + // state (ffConnectionState), which is set only from a successful + // listProjects outcome — never from the mere presence of stored key bytes. + // A failed or cancelled connection returns to the same connect step so the + // user can retry instead of being pushed forward past an unconnected + // account. + const walkthroughModal = document.getElementById("walkthrough-modal"); + if (walkthroughModal) { + if (ffConnectionState === "connected") { + advanceWalkthrough(); + } + openModal(walkthroughModal); + } } } @@ -973,38 +1452,17 @@ function updateWalkthroughUI() { if (!steps.length) return; steps.forEach((stepEl, idx) => { const i = idx + 1; + stepEl.classList.remove("wt-current", "wt-done", "wt-pending"); + const numEl = stepEl.querySelector(".wt-step-num"); if (i === walkthroughStep) { - stepEl.classList.remove("opacity-60", "bg-gray-50", "border-gray-200"); - stepEl.classList.add("bg-blue-50", "border-blue-200"); - const numEl = stepEl.querySelector("div:first-child"); - if (numEl) { - numEl.classList.remove("bg-gray-400"); - numEl.classList.add("bg-blue-500"); - numEl.innerHTML = i; - } + stepEl.classList.add("wt-current"); + if (numEl) numEl.textContent = i; } else if (i < walkthroughStep) { - stepEl.classList.remove("opacity-60", "bg-blue-50", "border-blue-200"); - stepEl.classList.add("bg-green-50", "border-green-200"); - const numEl = stepEl.querySelector("div:first-child"); - if (numEl) { - numEl.classList.remove("bg-blue-500", "bg-gray-400"); - numEl.classList.add("bg-green-500"); - numEl.innerHTML = "✓"; - } + stepEl.classList.add("wt-done"); + if (numEl) numEl.textContent = "✓"; } else { - stepEl.classList.add("opacity-60", "bg-gray-50", "border-gray-200"); - stepEl.classList.remove( - "bg-blue-50", - "border-blue-200", - "bg-green-50", - "border-green-200", - ); - const numEl = stepEl.querySelector("div:first-child"); - if (numEl) { - numEl.classList.remove("bg-blue-500", "bg-green-500"); - numEl.classList.add("bg-gray-400"); - numEl.innerHTML = i; - } + stepEl.classList.add("wt-pending"); + if (numEl) numEl.textContent = i; } }); } @@ -1022,7 +1480,7 @@ function openWalkthroughModal() { if (modal) { walkthroughStep = 1; updateWalkthroughUI(); - modal.classList.add("open"); + openModal(modal); } } @@ -1030,7 +1488,7 @@ function closeWalkthroughModal(event) { if (event && event.target !== event.currentTarget) return; const modal = document.getElementById("walkthrough-modal"); if (modal) { - modal.classList.remove("open"); + closeModal(modal); } const dontShow = document.getElementById("walkthrough-dont-show"); @@ -1049,7 +1507,7 @@ function showWalkthroughIfNeeded() { if (modal) { walkthroughStep = 1; updateWalkthroughUI(); - modal.classList.add("open"); + openModal(modal); } } } @@ -1095,11 +1553,7 @@ function updateDeployButtonVisibility() { pipelineState.step2Result && pipelineState.step2Result.length > 0; const deployBtn = document.getElementById("btn-deploy-to-ff"); - const runBtn = document.getElementById("btn-run-pipeline"); - // Run Pipeline stays visible next to Deploy so a generation can be restarted - // without closing the results. - if (runBtn) runBtn.classList.remove("hidden"); if (deployBtn) { deployBtn.classList.toggle("hidden", !hasGeneratedCode); } @@ -1154,25 +1608,84 @@ function updateApiKeyStatusIndicators() { async function saveApiKeys() { const flutterflowInput = document.getElementById("flutterflow-api-key-input"); const projectSelect = document.getElementById("flutterflow-projects-select"); + const enteredKey = flutterflowInput.value.trim(); + const isKeyReplaced = Boolean(enteredKey) && enteredKey !== flutterflowApiKey; + const selectedProjectId = projectSelect?.value.trim() || ""; // Only save if user entered a new value - if (flutterflowInput.value.trim()) { - await saveApiKey("flutterflow", flutterflowInput.value); + if (enteredKey) { + // A different key serves a different project set, so without a fresh + // selection the stored project id belongs to the old key and is not a + // trustworthy deploy target. + const previousKey = await getApiKey("flutterflow").catch(() => ""); + await saveApiKey("flutterflow", enteredKey); + if (enteredKey !== previousKey && !selectedProjectId) { + clearStoredProjectSelection(); + } } - const selectedProjectId = projectSelect?.value.trim() || ""; + // The key the selection is saved under: a replacement key is the effective + // one even though initializeApiKeys has not loaded it into memory yet. + const effectiveKey = enteredKey || flutterflowApiKey; + if (selectedProjectId) { if (!validateFlutterFlowProjectId(selectedProjectId)) { showToast("The selected FlutterFlow project has an unexpected ID format.", "error"); projectSelect.focus(); return; } - await saveApiKey("flutterflow_project_id", selectedProjectId); + // A selection is persisted only while the identity binding confirms it for + // the key being saved: the dropdown's change handler binds a choice to the + // key + endpoint generation of the list that produced it, and a completed + // response re-confirms the stored value. A choice made from the old key's + // list (or a value auto-reselected under a replaced key) carries the old + // identity, so it is cleared instead of becoming the new key's target. + if (isProjectSelectionConfirmed(selectedProjectId, effectiveKey)) { + await saveApiKey("flutterflow_project_id", selectedProjectId); + } else { + // The on-screen choice belongs to a different key's list. Only a key + // replacement may drop the stored target: with the configured key + // unchanged, that choice is a preview leftover — the stored project + // stays configured and merely the options are reloaded for it. + if (isKeyReplaced) { + clearStoredProjectSelection(); + } else { + // Drop the preview binding so the reloaded list's reconcile can + // re-confirm the stored project (its different-project guard would + // otherwise keep skipping it, leaving the stored target refused). + projectSelectionIdentity = null; + } + projectSelect.value = ""; + // The options on screen came from a list that does not belong to the key + // being saved; refresh them for the saved key so the user can make a + // fresh, confirmable choice. + if ( + effectiveKey && + !( + projectListIdentity && + projectListIdentity.key === effectiveKey && + projectListIdentity.generation === ffEndpointGeneration + ) + ) { + fetchProjects(effectiveKey); + } + } + } else if (isKeyReplaced) { + clearStoredProjectSelection(); } // Reinitialize keys await initializeApiKeys(); + // If a key was (re)entered, wait for the REAL connection outcome before the + // editor closes, so the walkthrough advance decision in closeApiKeysModal + // sees a settled canonical state rather than an in-flight "validating" or + // the mere presence of stored bytes. STU-384 owns this state; it is only + // "connected" after a real listProjects returns at least one project. + if (enteredKey) { + await validateFlutterFlowConnection(); + } + // Update UI loadApiKeyInputs(); @@ -1212,6 +1725,11 @@ async function clearAllApiKeys() { sessionStorage.removeItem(SESSION_STORAGE_KEY_PREFIX + "flutterflow"); sessionStorage.removeItem(SESSION_STORAGE_KEY_PREFIX + "flutterflow_project_id"); + // No key and no list: every project selection binding is meaningless now. + projectSelectionIdentity = null; + projectListIdentity = null; + confirmProjectListIdentity = null; + // Reinitialize keys await initializeApiKeys(); @@ -1238,6 +1756,191 @@ function validateFlutterFlowProjectId(projectId) { return /^[a-zA-Z0-9-]+$/.test(projectId); } +/** + * Renders the account connection card from the canonical connection state. + * Not-config/validating/connected/no-projects/unauthorized/network-error are + * derived from ffConnectionState, which is only ever set from a real + * listProjects outcome. No raw or masked API key is ever written into a status + * label here. + */ +function renderApiKeyConnection() { + const dot = document.getElementById("acct-ff-dot"); + const status = document.getElementById("acct-ff-status"); + const endpoint = document.getElementById("acct-ff-endpoint"); + const project = document.getElementById("acct-ff-project"); + + // Endpoint and default project always mirror the stored configuration (the + // same value the deploy confirmation pre-selects). + if (endpoint) { + const ep = getFlutterFlowEndpoint(); + endpoint.textContent = ep && ep.includes("staging") ? "Staging" : "Production"; + } + if (project) { + project.textContent = flutterflowProjectId || "—"; + } + if (!status) return; + + let label; + let tone; + if (!hasStoredKey("flutterflow")) { + label = "Not connected — add your FlutterFlow API key"; + tone = ""; + } else { + switch (ffConnectionState) { + case "connected": + label = "Connected to FlutterFlow"; + tone = "ok"; + break; + case "no-projects": + label = "Key accepted — no projects found"; + tone = "warn"; + break; + case "unauthorized": + label = "API key rejected (401/403) — re-enter your key"; + tone = "bad"; + break; + case "network-error": + label = "Could not reach FlutterFlow — check your network"; + tone = "bad"; + break; + case "validating": + default: + label = "Checking connection…"; + tone = "warn"; + break; + } + } + status.textContent = label; + if (dot) dot.className = `acct-dot${tone ? " " + tone : ""}`; +} + +/** + * Refreshes the canonical connection state by calling the real FlutterFlow + * projects endpoint with the stored key. A returned empty list and a 401/403 + * are distinct outcomes; both differ from a network failure. Used at startup + * and after saving/clearing so the account connection card is truthful. + * @returns {Promise} the loaded projects, or null on error. + */ +async function validateFlutterFlowConnection() { + // The connection identity this check belongs to. If the endpoint, the + // configured key, or the newest connection check moves while the check is in + // flight, its outcome describes a previous identity and must be discarded + // rather than overwrite the new one's state. A pending dropdown fetch is a + // different kind and does not supersede the check (nor the check it). + const seq = beginConnectionCheck(); + const order = ++ffRequestOrderSeq; + const generation = ffEndpointGeneration; + const storedKeyAtStart = flutterflowApiKey; + const apiKey = await getApiKey("flutterflow"); + const outcomeIsCurrent = () => + isCurrentProjectRequest({ + seq, + currentSeq: ffConnectionCheckSeq, + generation, + storedKeyAtStart, + requestKey: apiKey, + }); + // Everything a check writes is shared connection state, so a check that + // started before a newer request's outcome was applied has nothing left to + // write: skip it entirely rather than flash "validating" over the newer + // result and then fail silently. + if (!outcomeIsCurrent() || order <= ffAppliedOutcomeOrder) return null; + const applyConfirmation = () => { + ffAppliedConfirmationOrder = Math.max(ffAppliedConfirmationOrder, order); + }; + if (!apiKey || !hasStoredKey("flutterflow")) { + ffAppliedOutcomeOrder = order; + applyConfirmation(); + ffConnectionState = "not-configured"; + renderApiKeyConnection(); + return null; + } + + ffConnectionState = "validating"; + renderApiKeyConnection(); + + try { + const client = new FlutterFlowApiClient( + apiKey, + "", + "main", + getFlutterFlowEndpoint(), + ); + const projects = await client.listProjects(); + if (!outcomeIsCurrent()) return null; + // A newer request of either kind already applied its outcome: this older + // response must not write shared state over it. + if (order <= ffAppliedOutcomeOrder) return null; + ffAppliedOutcomeOrder = order; + applyConfirmation(); + ffConnectionState = projects && projects.length > 0 + ? "connected" + : "no-projects"; + // A completed check for the current key is authoritative for what that key + // can reach: it re-confirms the stored selection when the response lists + // it, and strips its confirmation when it does not — but only while it is + // still the newest confirmation writer, so a fresher list response wins. + if (order >= ffAppliedConfirmationOrder) { + reconcileStoredProjectSelection(projects, apiKey, generation); + } + renderApiKeyConnection(); + return projects; + } catch (error) { + if (!outcomeIsCurrent()) return null; + if (order <= ffAppliedOutcomeOrder) return null; + ffAppliedOutcomeOrder = order; + applyConfirmation(); + const msg = String((error && error.message) || ""); + ffConnectionState = /(401|403)|denied|unauthorized|scoped|list permission/i.test(msg) + ? "unauthorized" + : "network-error"; + renderApiKeyConnection(); + return null; + } +} + +/** + * Clears the currently selected FlutterFlow project so a stale selection + * (belonging to a different endpoint, or a removed key) is never reused as a + * deploy/sync default. Storage, the in-memory value, its identity binding and + * the dropdown mirror each other: the account connection card and the deploy + * confirmation read the same stored value, so invalidating it keeps them + * consistent. + */ +function clearStoredProjectSelection() { + flutterflowProjectId = ""; + projectSelectionIdentity = null; + localStorage.removeItem(STORAGE_KEY_PREFIX + "flutterflow_project_id"); + sessionStorage.removeItem(SESSION_STORAGE_KEY_PREFIX + "flutterflow_project_id"); +} + +/** + * Endpoint changes serve a different project set, so the previously selected + * project is no longer a trustworthy target. Invalidate the stale selection and + * re-fetch the project list for the new endpoint when a key is configured. + */ +function invalidateStaleProjectSelection() { + // Any request still in flight belongs to the previous endpoint: advancing + // the generation makes it discard its outcome instead of writing it over the + // new endpoint's status or project list. + ffEndpointGeneration += 1; + projectListIdentity = null; + confirmProjectListIdentity = null; + clearStoredProjectSelection(); + const select = document.getElementById("flutterflow-projects-select"); + if (select) { + select.innerHTML = ''; + select.value = ""; + } + if (hasStoredKey("flutterflow")) { + ffConnectionState = "validating"; + fetchProjects(flutterflowApiKey); + } else { + ffConnectionState = "not-configured"; + } + renderApiKeyConnection(); +} + function updateInputValidationState(inputId, isValid) { const input = document.getElementById(inputId); if (!input) return; @@ -1269,6 +1972,26 @@ function setupFlutterFlowValidation() { }, 500), ); } + + const projectSelect = document.getElementById("flutterflow-projects-select"); + if (projectSelect) { + projectSelect.addEventListener("change", () => { + const chosen = projectSelect.value.trim(); + // A choice is one of the options a completed fetch produced, so it is + // bound to that list's identity. Without a completed list there is + // nothing to bind, and any previous binding no longer matches the value + // on screen. + if (chosen && projectListIdentity) { + bindProjectSelection( + chosen, + projectListIdentity.key, + projectListIdentity.generation, + ); + } else { + bindProjectSelection("", null, null); + } + }); + } } /** @@ -1303,20 +2026,96 @@ async function fetchProjects(apiKey) { return; } - // Show loading state + // The connection identity this fetch belongs to. If the endpoint, the + // configured key, or the newest dropdown fetch moves while the fetch is in + // flight, its response describes a previous identity and must be discarded + // rather than overwrite the new one's list or status. A connection check is + // a different kind and does not supersede the fetch (nor the fetch it). + const seq = beginProjectFetch(); + const order = ++ffRequestOrderSeq; + const generation = ffEndpointGeneration; + const storedKeyAtStart = flutterflowApiKey; + const outcomeIsCurrent = () => + isCurrentProjectRequest({ + seq, + currentSeq: ffProjectFetchSeq, + generation, + storedKeyAtStart, + requestKey: apiKey, + }); + // The dropdown is this fetch's own surface: the newest fetch still fills it + // even when its shared-state outcome is stale. Shared writes — connection + // status and stored-project confirmation — go to the newest request of + // either kind only, so an older list cannot re-mark the account connected + // after a newer check failed. + const mayWriteConnectionOutcome = () => order > ffAppliedOutcomeOrder; + const claimConnectionOutcome = () => { + ffAppliedOutcomeOrder = Math.max(ffAppliedOutcomeOrder, order); + }; + + // Show loading state. The options are replaced by the loading placeholder + // below, so no list is on screen until this fetch's response is applied. + projectListIdentity = null; select.innerHTML = ''; if (errorElement) errorElement.classList.add("hidden"); + // A real request is in flight; the account connection card shows validating + // until the outcome is known (never "connected" from storage alone). Only a + // request for the key that is actually configured describes the account — a + // preview request for a key that is never saved must not flash validating + // (and must not write any account status below). + if ( + mayWriteConnectionOutcome() && + apiKey === flutterflowApiKey && + (hasStoredKey("flutterflow") || apiKey) + ) { + ffConnectionState = "validating"; + } + renderApiKeyConnection(); + try { // Create temporary client instance (no project ID needed) - const client = new FlutterFlowApiClient(apiKey, ""); + const client = new FlutterFlowApiClient( + apiKey, + "", + "main", + getFlutterFlowEndpoint(), + ); const projects = await client.listProjects(); + if (!outcomeIsCurrent()) return; + + // The applied options belong to this fetch's key + endpoint generation. + projectListIdentity = { key: apiKey, generation }; + // Shared writes — account status and stored-project confirmation — belong + // to the configured key only: a preview fetch for a key that is never + // saved must not describe the account or confirm a selection, while one + // whose key became the configured key mid-flight still applies. + const requestIsForConfiguredKey = apiKey === flutterflowApiKey; + const outcomeIsNewest = + mayWriteConnectionOutcome() && requestIsForConfiguredKey; + if (outcomeIsNewest) claimConnectionOutcome(); + // A response for the configured key re-confirms (or strips) the stored + // selection while it is still the newest confirmation response: an older + // list must not restore the target's confirmation over a newer one. + if (order > ffAppliedConfirmationOrder && requestIsForConfiguredKey) { + ffAppliedConfirmationOrder = order; + reconcileStoredProjectSelection(projects, apiKey, generation); + } if (!projects || projects.length === 0) { + if (outcomeIsNewest) { + ffConnectionState = "no-projects"; + renderApiKeyConnection(); + } select.innerHTML = ''; return; } + if (outcomeIsNewest) { + ffConnectionState = "connected"; + renderApiKeyConnection(); + } + // Populate dropdown select.innerHTML = ''; projects.forEach((project) => { @@ -1332,7 +2131,16 @@ async function fetchProjects(apiKey) { select.value = flutterflowProjectId; } } catch (error) { + if (!outcomeIsCurrent()) return; console.error("Failed to fetch projects:", error); + const msg = String((error && error.message) || ""); + if (mayWriteConnectionOutcome() && apiKey === flutterflowApiKey) { + claimConnectionOutcome(); + ffConnectionState = /(401|403)|denied|unauthorized|scoped|list permission/i.test(msg) + ? "unauthorized" + : "network-error"; + renderApiKeyConnection(); + } select.innerHTML = ''; if (errorElement) { errorElement.textContent = `Failed to load projects: ${error.message}`; @@ -1372,6 +2180,15 @@ let pipelineState = { resultsViewMode: "summary", currentStep: 0, isRunning: false, + // Incremented every time a pipeline run starts. Captured locally by each + // run so a stale run's async step results can never overwrite a newer + // run's UI state (e.g. a slow first request resolving after the user + // already retried). + runId: 0, + // The prompt and images as submitted, so a retry re-runs exactly what the + // user sent and an edit returns them to the composer unchanged. + submittedPrompt: "", + submittedImages: [], }; function resetPipelineResults() { @@ -1710,17 +2527,36 @@ class FlutterFlowApiClient { * @param {string} pushCodeRequest.functions_map - JSON string of function definitions * @returns {Promise} Fetch response object */ - async pushCodeWithRetry(pushCodeRequest, maxRetries = 3) { + async pushCodeWithRetry(pushCodeRequest, maxRetries = 3, stopToken = null) { const endpointUrls = [ FF_API_ENDPOINTS.production, FF_API_ENDPOINTS.staging, ]; const startEndpoint = Math.max(0, endpointUrls.indexOf(this._endpoint)); + // An attempt is uncertain when its outcome cannot prove the push was + // refused: a dropped response (the request may have landed) or a 5xx (the + // server's own failure report can follow a write). Once any attempt is + // uncertain, no later refusal can undo it — the outcome stays unknown. + let sawUncertainAttempt = false; + let lastHttpStatus = null; for (let attempt = 0; attempt < maxRetries; attempt++) { for (let ei = startEndpoint; ei < endpointUrls.length; ei++) { const baseUrl = endpointUrls[ei]; + // Once the UI bound expired, the outcome was already reported + // unconfirmed and the user may have started a new deploy — issuing + // another write would overlap it. An in-flight request is never + // aborted; this only stops attempts not yet sent. + if (stopToken?.stop) { + throw exhaustedPushError({ httpStatus: lastHttpStatus }); + } + + // Only a fetch rejection is a lost response: once headers arrive, a + // refusal status is a definitive answer for this endpoint — and a body + // that fails to read for logging must not reclassify one as a lost + // response (or send a non-500 refusal back through the retry loop). + let response; try { console.log( `Push attempt ${attempt + 1} to ${baseUrl}syncCustomCodeChanges`, @@ -1734,7 +2570,7 @@ class FlutterFlowApiClient { file_map_length: pushCodeRequest.file_map?.length || 0, functions_map_length: pushCodeRequest.functions_map?.length || 0, }); - const response = await fetch(`${baseUrl}syncCustomCodeChanges`, { + response = await fetch(`${baseUrl}syncCustomCodeChanges`, { method: "POST", headers: { "Content-Type": "application/json", @@ -1742,39 +2578,88 @@ class FlutterFlowApiClient { }, body: JSON.stringify(pushCodeRequest), }); - - if (response.ok) { - console.log(`Push to ${baseUrl} succeeded!`); - return response; - } - - const clonedForLog = response.clone(); - const responseText = await clonedForLog.text(); - console.log( - `Push to ${baseUrl} returned ${response.status}: ${responseText}`, - ); - - if (response.status === 500) { - console.warn(`Endpoint ${baseUrl} returned 500, trying next...`); - await new Promise((r) => setTimeout(r, 1000 * (attempt + 1))); - continue; - } - - return response; } catch (error) { + sawUncertainAttempt = true; console.warn( `Push to ${baseUrl} failed: ${error.message}, trying next...`, ); await new Promise((r) => setTimeout(r, 1000 * (attempt + 1))); + continue; + } + + if (response.ok) { + console.log(`Push to ${baseUrl} succeeded!`); + return response; + } + + lastHttpStatus = response.status; + // The status alone classifies this response — the body read is + // diagnostic only: detached so it can't block the refusal path, and + // bounded+cancelled so a stalled body can't leave a reader (and its + // connection) open past the bound. A response this loop will not + // hand back to the caller is read directly — teeing it with clone() + // would leave the original branch (and its connection) feeding a + // reader that doesn't exist; only the definitive-refusal path keeps + // the original body for parsePushCodeResponse, so it logs a clone. + const returnedToCaller = + response.status < 500 && !sawUncertainAttempt; + readBodyBounded( + returnedToCaller ? response.clone() : response, + PUSH_BODY_READ_TIMEOUT_MS, + ).then( + (responseText) => + console.log( + `Push to ${baseUrl} returned ${response.status}: ${responseText}`, + ), + () => + console.log( + `Push to ${baseUrl} returned ${response.status} (unreadable response body)`, + ), + ); + + // A 5xx is the server's own failure report: it can be raised after + // the write was applied, so it can never prove a refusal. + if (response.status >= 500) { + sawUncertainAttempt = true; + } + if (response.status === 500) { + console.warn(`Endpoint ${baseUrl} returned 500, trying next...`); + await new Promise((r) => setTimeout(r, 1000 * (attempt + 1))); + continue; + } + + // Any other server error is already an unknown outcome for this + // endpoint — the write may have been applied before the failure. + if (response.status >= 500) { + throw new UnconfirmedDeployError( + `FlutterFlow reported a server error (HTTP ${response.status}), ` + + "which cannot prove the push was refused — the write may have " + + "been applied before the failure. Open your FlutterFlow project " + + "to reconcile before retrying.", + ); + } + + // A refusal is definitive for this endpoint, but it cannot prove that + // an earlier attempt whose outcome was lost did not apply the push. + if (sawUncertainAttempt) { + throw new UnconfirmedDeployError( + `The push was refused (HTTP ${response.status}), but an earlier ` + + "sync attempt may already have applied it — server errors and " + + "dropped responses cannot prove a refusal. Open your FlutterFlow " + + "project to reconcile before retrying.", + ); } + return response; } } - throw new Error("All API endpoints failed after retries"); + // Every retry path left the outcome unknown: each attempt either lost its + // response or hit a server error, so the push may have been applied. + throw exhaustedPushError({ httpStatus: lastHttpStatus }); } - async pushCode(pushCodeRequest) { - return this.pushCodeWithRetry(pushCodeRequest); + async pushCode(pushCodeRequest, stopToken = null) { + return this.pushCodeWithRetry(pushCodeRequest, 3, stopToken); } /** @@ -1863,19 +2748,67 @@ class FlutterFlowApiClient { } } +/** + * Reads a response body to text under a bound. Unlike `text()`, it keeps the + * reader so that on expiry the stream is cancelled for real — `body.cancel()` + * rejects while a `text()`/`json()` read holds the lock, but `reader.cancel()` + * is valid even mid-read, so a stalled body releases its connection instead + * of leaving a pending reader alive after the waiter settled. + * @param {Response} response - Response whose body to read + * @param {number} ms - How long to wait for the body + * @returns {Promise} Rejects when the body stalls or the read fails + */ +function readBodyBounded(response, ms) { + const reader = response.body?.getReader?.(); + const work = reader + ? (async () => { + const decoder = new TextDecoder(); + let text = ""; + while (true) { + const { done, value } = await reader.read(); + if (done) break; + text += decoder.decode(value, { stream: true }); + } + return text + decoder.decode(); + })() + : Promise.resolve(""); + return withUiTimeout(work, ms, (resolve, reject) => { + try { + reader?.cancel()?.catch?.(() => {}); + } catch {} + reject(new Error("The response body stalled before it finished.")); + }); +} + /** * Parses the response from pushCode API call. * @param {Response} response - Fetch response object * @returns {Promise} Parsed result with file warnings */ -async function parsePushCodeResponse(response) { +async function parsePushCodeResponse( + response, + bodyTimeoutMs = PUSH_BODY_READ_TIMEOUT_MS, +) { const originalResponse = response.clone(); let jsonResult; try { - jsonResult = await response.json(); + // The status alone classifies the response — the body only carries the + // error detail, so this read is bounded and cancellable: a stalled body + // must not hide a definitive refusal (or an acceptance) behind the outer + // UI bound nor leave a pending reader behind. + jsonResult = JSON.parse(await readBodyBounded(response, bodyTimeoutMs)); } catch (error) { - const text = await originalResponse.text(); + // Both reads share the same connection: a body dropped mid-flight makes + // the clone reject too. The received status is still definitive — a non-ok + // response is a refusal, an ok one means the push may have been applied + // before the body was lost. + let text = ""; + try { + text = await readBodyBounded(originalResponse, bodyTimeoutMs); + } catch (readError) { + // The body never arrived; classify on the status alone. + } // Check if the response was an error with plain text body (common for 500s) if (!response.ok) { @@ -1887,7 +2820,11 @@ async function parsePushCodeResponse(response) { }; } - throw new Error(`Invalid JSON response: ${text}`); + // HTTP ok but the body never parsed: the push request reached FlutterFlow + // and was accepted, so the remote state is unknown — not a failure. + throw new UnconfirmedDeployError( + `FlutterFlow accepted the sync but returned an unreadable response${text ? `: ${text.slice(0, 200)}` : "."}`, + ); } if (!response.ok) { @@ -2096,6 +3033,26 @@ function getFileNameFromPath(filePath) { // the session. Fetching them means one full project export. const projectSourceCache = new Map(); +// File writes whose provisioning outcome is unconfirmed, per cache key — +// each dirty path maps content -> { uncertain, verified, explainedByVerified }: +// `uncertain` counts provision attempts that may still write that content (a +// lost/dropped request is not proof the runner stopped), and `verified` +// credits confirmed writes an export sighting must consume first. A sighting +// of content X consumes a verified X-credit before it can retire an uncertain +// X-write, and once a verified X-write has explained an X-sighting, +// `explainedByVerified` marks the sighting as spent evidence: a later export +// of the same unchanged X is the same fact, not a new landing, so it can never +// retire an uncertain X-write whose identical content may still land. While +// any entry is outstanding, fresh exports are never cached. +const projectSourceDirtyWrites = new Map(); + +// Unconfirmed sync pushes whose underlying request is still in flight, per +// cache key. Unlike provisioning, a push writes inside its own request +// handling — once the request settles (response or dropped connection) no +// write can land afterwards, so an export taken after settlement is +// authoritative again. +const projectSourcePendingPushes = new Map(); + function projectSourceCacheKey(apiClient) { return `${apiClient.baseUrl}|${apiClient.projectId}|${apiClient.branchName}`; } @@ -2104,17 +3061,137 @@ function invalidateProjectSourceCache(apiClient) { projectSourceCache.delete(projectSourceCacheKey(apiClient)); } -async function provisionMissingCodeFiles( - apiClient, - fileMap, - remoteFiles, - commitMessage, - pubspecYaml = "", -) { - const missingCodeFiles = findMissingCodeFiles(fileMap, remoteFiles); - if (missingCodeFiles.length === 0) { - return { remoteFiles, syncFileMap: fileMap, unverified: [] }; - } +function adjustProjectSourceDirty(apiClient, entries, delta) { + const key = projectSourceCacheKey(apiClient); + const dirty = projectSourceDirtyWrites.get(key) ?? new Map(); + for (const { path, content } of entries) { + const contents = dirty.get(path) ?? new Map(); + const record = contents.get(content) ?? { uncertain: 0, verified: 0 }; + if (delta.uncertain) record.uncertain += delta.uncertain; + if (delta.verified) record.verified += delta.verified; + if (record.uncertain <= 0 && record.verified <= 0) { + contents.delete(content); + } else { + contents.set(content, record); + } + if (contents.size === 0) dirty.delete(path); + else dirty.set(path, contents); + } + if (dirty.size === 0) projectSourceDirtyWrites.delete(key); + else projectSourceDirtyWrites.set(key, dirty); +} + +function markProjectSourceDirty(apiClient, entries) { + adjustProjectSourceDirty(apiClient, entries, { uncertain: 1 }); +} + +function markProjectSourcePushPending(apiClient) { + const key = projectSourceCacheKey(apiClient); + projectSourcePendingPushes.set(key, (projectSourcePendingPushes.get(key) ?? 0) + 1); +} + +function clearProjectSourcePushPending(apiClient) { + const key = projectSourceCacheKey(apiClient); + const pending = (projectSourcePendingPushes.get(key) ?? 0) - 1; + if (pending <= 0) projectSourcePendingPushes.delete(key); + else projectSourcePendingPushes.set(key, pending); +} + +/** + * Bounded waiting for a remote write. The UI shows live progress only while + * this promise settles; once the bound expires the waiter stops claiming + * progress and `onExpire` decides the terminal outcome. The underlying promise + * is deliberately *not* aborted or retried: it is handed back to the pending + * work, and any late settlement is ignored (the bound already resolved the + * waiter). This is a rendering bound, never a transport one. + * @param {Promise} promise - Work whose remote outcome may or may not arrive + * @param {number} ms - How long to wait for a decision + * @param {function} onExpire - Called with (resolve, reject) exactly once on expiry + * @returns {Promise} Settles with the work's value, or via onExpire on timeout + */ +function withUiTimeout(promise, ms, onExpire) { + return new Promise((resolve, reject) => { + let settled = false; + const finish = (fn, value, which) => { + if (settled) return; + settled = true; + if (which === "resolve") resolve(value); + else reject(value); + }; + const timer = setTimeout(() => { + if (settled) return; + settled = true; + onExpire(resolve, reject); + }, ms); + promise.then( + (value) => { clearTimeout(timer); finish(resolve, value, "resolve"); }, + (error) => { clearTimeout(timer); finish(reject, error, "reject"); }, + ); + }); +} + +/** + * Runs the sync push and its response parsing under one UI bound. A stalled + * fetch (headers never flush) or a stalled body read would otherwise park the + * deploy forever; on expiry the outcome is unconfirmed — the request may have + * been applied — and the in-flight write is left running rather than aborted. + * @param {FlutterFlowApiClient} apiClient - Configured API client + * @param {Object} pushRequest - The syncCustomCodeChanges request body + * @param {number} uiTimeoutMs - How long the UI waits for a decision + * @returns {Promise} The parsed push result + */ +async function pushCodeWithUiTimeout( + apiClient, + pushRequest, + uiTimeoutMs = DEPLOY_UI_TIMEOUT_MS, +) { + // Tells the retry loop to stop issuing writes once the bound expires: an + // in-flight request is left to settle on its own (its late result is + // ignored), but no further attempts may start — they could overlap a deploy + // the user just retried. + const stopToken = { stop: false }; + const pushWork = (async () => { + const response = await apiClient.pushCode(pushRequest, stopToken); + return parsePushCodeResponse(response); + })(); + return withUiTimeout( + pushWork, + uiTimeoutMs, + (resolve, reject) => { + stopToken.stop = true; + // The in-flight request is left running; its writes can still land + // until it settles (a push writes inside its own request handling — + // settlement is the boundary after which nothing can arrive). While + // pending, the project's exports must not be cached. + invalidateProjectSourceCache(apiClient); + markProjectSourcePushPending(apiClient); + pushWork.then( + () => clearProjectSourcePushPending(apiClient), + () => clearProjectSourcePushPending(apiClient), + ); + reject( + new UnconfirmedDeployError( + "FlutterFlow did not answer the sync in time — the push may still " + + "have been applied. The outcome is not yet known: open your " + + "FlutterFlow project to reconcile before retrying the deploy.", + ), + ); + }, + ); +} + +async function provisionMissingCodeFiles( + apiClient, + fileMap, + remoteFiles, + commitMessage, + pubspecYaml = "", + uiTimeoutMs = DEPLOY_UI_TIMEOUT_MS, +) { + const missingCodeFiles = findMissingCodeFiles(fileMap, remoteFiles); + if (missingCodeFiles.length === 0) { + return { remoteFiles, syncFileMap: fileMap, unverified: [], approximate: [] }; + } // The runner compiles these against the project's own package versions // before it writes anything, so an API the generated code invented - a named @@ -2137,37 +3214,169 @@ async function provisionMissingCodeFiles( const unverified = verificationPlan.skipped.map((entry) => entry.reason); unverified.forEach((reason) => console.warn(`[custom class deploy] ${reason}`)); + // The planner skips every class that resolves packages when a source is + // unrepresentable, so nothing is checked approximately; the field stays in + // the deploy result's shape for the outcome renderers that read it. + const approximate = verificationPlan.approximate; + approximate.forEach((notice) => console.warn(`[custom class deploy] ${notice}`)); + console.log( `Provisioning ${missingCodeFiles.length} new FlutterFlow custom code file(s) before sync.`, ); commitProgress.set("provision"); - const response = await fetch(FLUTTERFLOW_CLASS_PROVISION_ENDPOINT, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - apiKey: apiClient.apiKey, - projectId: apiClient.projectId, - baseUrl: apiClient.baseUrl, - commitMessage, - customClasses: missingCodeFiles, - verification, - stream: true, - }), - }); + // Once the bound expires, progress updates from a late-arriving stream must + // not keep mutating a UI that already showed the terminal state. + let progressLive = true; + // The bounded wait covers the fetch itself, not just the stream body: a + // runner that accepts the connection but never flushes headers would + // otherwise hang the deploy past the UI bound. A fetch that rejects before + // any response is still an unknown outcome — the POST may have reached the + // server — so it maps to unconfirmed, not failed. + let result; + // Kept outside the try: a verified result that arrives after the bound + // resolves this attempt's dirty entries (success → verified credit, + // provable pre-write failure → retired). + let provisionWork; + try { + provisionWork = (async () => { + let response; + try { + response = await fetch(FLUTTERFLOW_CLASS_PROVISION_ENDPOINT, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + apiKey: apiClient.apiKey, + projectId: apiClient.projectId, + baseUrl: apiClient.baseUrl, + commitMessage, + customClasses: missingCodeFiles, + verification, + stream: true, + }), + }); + } catch (fetchError) { + throw new UnconfirmedDeployError( + "The provisioning request did not return a response. The deploy may have reached the " + + "FlutterFlow server — open your FlutterFlow project to reconcile before retrying.", + ); + } + return readProvisionResponse(response, { + onPhase: (message) => { + if (progressLive) commitProgress.setSubstatus(message); + }, + onLog: (message) => { + if (progressLive) console.log(`[custom class deploy] ${message}`); + }, + }); + })(); + result = await withUiTimeout( + provisionWork, + uiTimeoutMs, + (resolve, reject) => { + progressLive = false; + reject( + new UnconfirmedDeployError( + "The deploy is still working on the FlutterFlow server, but this browser tab has stopped waiting. " + + "Your custom classes may or may not have been written — the outcome is not yet known. " + + "Open your FlutterFlow project to reconcile before retrying the deploy.", + ), + ); + }, + ); - const result = await readProvisionResponse(response, { - onPhase: (message) => commitProgress.setSubstatus(message), - onLog: (message) => console.log(`[custom class deploy] ${message}`), - }); + // A stream that ended (or a body that carried) no definitive result leaves + // the remote decision ambiguous. An explicit 4xx is a definitive pre-write + // refusal — the request was turned away before any write — so it is a + // FAILURE, not an unknown outcome. A 5xx is no such proof: a gateway can + // answer 502/503/504 after forwarding the request to the runner, which may + // already be deploying, so a 5xx — like an ok response whose stream dropped + // before a result, or a client wait expiry — leaves the remote state + // genuinely unknown and must be UNCONFIRMED. + if (!result.finalResultReceived) { + if (deployOutcomeOfStreamResult(result) === DeployOutcome.FAILED) { + // Not marked remoteRefusal: the refusal comes from our deploy runner, + // not from FlutterFlow — its answer was never requested. + throw new Error( + result.error || + `FlutterFlow custom class provisioning failed (HTTP ${result.httpStatus}).`, + ); + } + // The cause must match what actually happened. A non-ok status (a 5xx, + // typically a gateway) was received, so the runner answered — it did not + // drop the connection — and the message names the status. Only an ok + // response whose stream ended without a result is a dropped connection. + const cause = + result.httpRejected && typeof result.httpStatus === "number" + ? `The FlutterFlow deploy runner returned HTTP ${result.httpStatus} without reporting a result.` + : "The connection to the FlutterFlow deploy runner dropped before it reported a result."; + throw new UnconfirmedDeployError( + `${cause} The deploy may still be finishing on the server; open your FlutterFlow project to reconcile ` + + "before retrying.", + ); + } - if (!result.success) { - const details = result.details ? ` ${result.details}` : ""; - throw new Error( - `${result.error || "FlutterFlow custom class provisioning failed."}${details}`, - ); + if (!result.success) { + const details = result.details ? ` ${result.details}` : ""; + const message = `${result.error || "FlutterFlow custom class provisioning failed."}${details}`; + // A runner-reported failure is only a definitive refusal when it provably + // precedes the write; a failure after the deploy began can follow classes + // already uploaded, so it must be reported unconfirmed (and the catch + // below drops the stale snapshot). + if (deployOutcomeOfStreamResult(result) === DeployOutcome.UNCONFIRMED) { + throw new UnconfirmedDeployError( + `${message} The failure arrived after the deploy began — custom classes ` + + "may already be written. Open your FlutterFlow project to reconcile " + + "before retrying.", + ); + } + // A verified pre-write rejection (compile gate, workspace, request + // validation) is still the runner's answer — FlutterFlow was never + // asked — so it is a plain failure, not a remoteRefusal. + throw new Error(message); + } + } catch (error) { + // An unconfirmed provisioning may have written classes on the runner after + // the client stopped waiting, so the cached pre-write project snapshot is + // stale — a later deploy must re-read the project instead of provisioning + // the same classes a second time. + if (error instanceof UnconfirmedDeployError) { + invalidateProjectSourceCache(apiClient); + // Every file this request may have written stays dirty until a fresh + // export observes that exact content with no verified write to explain + // it — the runner can keep working after the request is lost or the + // bound expires. While dirty, exports are never cached. + markProjectSourceDirty(apiClient, missingCodeFiles); + // A result event that arrives after the bound still proves this + // attempt's outcome: success converts its writes to verified (the sighting + // they produce is then attributable), a provable pre-write failure + // retires them outright. + provisionWork?.then( + (late) => { + if (late?.finalResultReceived && late.success) { + adjustProjectSourceDirty(apiClient, missingCodeFiles, { + uncertain: -1, + verified: 1, + }); + } else if ( + late?.finalResultReceived && + isPreWriteRunnerFailure(late) + ) { + adjustProjectSourceDirty(apiClient, missingCodeFiles, { + uncertain: -1, + }); + } + }, + () => {}, + ); + } + throw error; } invalidateProjectSourceCache(apiClient); + // A confirmed result credits this request's writes as verified: export + // sightings of that content are attributable to it, so earlier uncertain + // writes of the same path stay dirty until their own landing is observed. + adjustProjectSourceDirty(apiClient, missingCodeFiles, { verified: 1 }); if (result.verificationSkipped) { console.warn(`[custom class deploy] ${result.verificationSkipped}`); @@ -2178,6 +3387,11 @@ async function provisionMissingCodeFiles( remoteFiles, syncFileMap: excludeProvisionedCodeFiles(fileMap, missingCodeFiles), unverified, + approximate, + // Custom classes were actually upserted on the FlutterFlow side by the + // runner. Any failure of the *remaining* sync is therefore a partial + // outcome — classes wrote, the rest did not — never a clean total failure. + provisionSucceeded: true, }; } @@ -2230,7 +3444,52 @@ async function resolveProjectPubspec(apiClient, newDependencies = {}) { ); } - projectSourceCache.set(cacheKey, projectSource); + const dirty = projectSourceDirtyWrites.get(cacheKey); + if (dirty) { + // This fresh export is the authoritative read: an observed content + // first consumes a verified write credit (the sighting is explained by + // a confirmed provision), and only retires an uncertain write when no + // verified write could have produced it. A sighting explained by a + // verified write is spent evidence — a later export of the same + // unchanged content is the same fact, so it must not retire the + // uncertain write whose identical content may still land. + for (const [path, contents] of [...dirty]) { + const observed = projectSource.files.get(path); + if (observed !== undefined) { + const record = contents.get(observed); + if (record) { + if (record.verified > 0) { + record.verified -= 1; + record.explainedByVerified = true; + } else if (!record.explainedByVerified) { + record.uncertain -= 1; + } + if (record.uncertain <= 0 && record.verified <= 0) { + contents.delete(observed); + } + } + } + // This export postdates every confirmed write, so a verified credit + // is spent whether or not its recorded bytes were observed verbatim: + // a verified write already landed, and the file's current content — + // matching, reformatted by the server, or missing — is its end state. + // Uncertain records survive: an unproven write may still land later. + for (const [content, record] of [...contents]) { + record.verified = 0; + if (record.uncertain <= 0) contents.delete(content); + } + if (contents.size === 0) dirty.delete(path); + } + if (dirty.size === 0) projectSourceDirtyWrites.delete(cacheKey); + } + // Pending pushes keep exports uncached too: a request still in flight can + // still land its writes. + if ( + !projectSourceDirtyWrites.has(cacheKey) && + !projectSourcePendingPushes.has(cacheKey) + ) { + projectSourceCache.set(cacheKey, projectSource); + } } const plan = await planDependencyChanges( @@ -2247,7 +3506,11 @@ async function resolveProjectPubspec(apiClient, newDependencies = {}) { if (merged.added.length > 0) { console.log( "Adding dependencies:", - merged.added.map((name) => `${name}: ${plan.additions[name] || "any"}`).join(", "), + merged.added.map((name) => { + const addition = plan.additions[name]; + const display = addition?.sdk ? `sdk: ${addition.sdk}` : (addition || "any"); + return `${name}: ${display}`; + }).join(", "), plan.sdk.dartSdkFloor ? `(resolved for Dart ${plan.sdk.dartSdkFloor})` : "", ); } @@ -2731,6 +3994,84 @@ const commitState = { }, }; +/** + * The only way a deploy resolves its target from stored state. The stored + * project is returned only while the identity binding confirms it for the key + * the deploy will actually use (the stored key); otherwise "" is returned and + * the caller fails or asks for a fresh selection. Every deploy read goes + * through here, so a selection that survived a key or endpoint change cannot + * reach a push. + */ +async function getConfirmedStoredProjectId(forApiKey) { + // The deploy passes the key it captured, so the verification describes the + // same credential identity the push will use — never a key saved mid-flight. + const apiKey = + forApiKey !== undefined ? forApiKey : await getApiKey("flutterflow"); + const projectId = await getApiKey("flutterflow_project_id"); + if (!apiKey || !projectId) return ""; + if (isProjectSelectionConfirmed(projectId, apiKey)) return projectId; + + // The binding is process-local and starts empty on load, so a stored target + // is unconfirmed while the startup listProjects is still pending — and stays + // unconfirmed when no fetch ever ran. Before refusing the deploy, verify the + // stored target against the current key's real list here: the same guard + // applies (a completed response that omits the project leaves it refused), + // and a superseded or failed verification still returns "". + const order = ++ffRequestOrderSeq; + const generation = ffEndpointGeneration; + let verified = false; + try { + const client = new FlutterFlowApiClient( + apiKey, + "", + "main", + getFlutterFlowEndpoint(), + ); + const projects = await client.listProjects(); + verified = (projects || []).some( + (project) => (project.id || project.projectId) === projectId, + ); + } catch (error) { + // A project-scoped key can sync its project without list permission: its + // listProjects denial is a 403, not proof the stored project is absent. + // Nothing can disprove the stored target for such a key, so it stands + // (still guarded by the endpoint generation + key checks below) and the + // push itself decides reachability; any other failure refuses. + const msg = String((error && error.message) || ""); + if (!/denied \(403\)|without list permission/i.test(msg)) return ""; + verified = true; + } + // A response that describes a superseded identity — the endpoint moved on, + // the configured key changed, or a newer request already applied its + // outcome (including one that stripped this target's confirmation) — + // verifies nothing. + if (generation !== ffEndpointGeneration) return ""; + if (apiKey !== flutterflowApiKey) return ""; + if (order <= ffAppliedConfirmationOrder) return ""; + ffAppliedConfirmationOrder = order; + if (!verified) return ""; + // A selection bound to this key + endpoint generation is the active choice: + // when it names a different project the stored value is superseded, so the + // deploy follows the confirmed binding — never the stored target it + // replaced. A binding made under another key or generation does not + // describe this push and must not be clobbered. + if ( + projectSelectionIdentity && + projectSelectionIdentity.projectId !== projectId && + isProjectSelectionConfirmed(projectSelectionIdentity.projectId, apiKey) + ) { + return projectSelectionIdentity.projectId; + } + // Never overwrite an in-flight explicit choice for a different project. + if ( + !projectSelectionIdentity || + projectSelectionIdentity.projectId === projectId + ) { + bindProjectSelection(projectId, apiKey, generation); + } + return projectId; +} + /** * Commits generated code to FlutterFlow with full state tracking. * @param {string} dartCode - The generated Dart code to commit @@ -2756,13 +4097,27 @@ async function commitToFlutterFlow(dartCode, fileName, options = {}) { commitState.setState(CommitState.PREPARING); try { - // Get credentials + // Get credentials. The target project is read through the identity gate: + // a stored selection that is not confirmed for the stored key is never + // used. const apiKey = await getApiKey("flutterflow"); - const projectId = await getApiKey("flutterflow_project_id"); + const endpoint = getFlutterFlowEndpoint(); + let projectId = await getConfirmedStoredProjectId(apiKey); + // A key save or endpoint switch landing during the verification await + // would pair this captured identity with a target confirmed for another + // one — refuse rather than deploy a mismatched credential pair. + if (apiKey !== flutterflowApiKey || endpoint !== getFlutterFlowEndpoint()) { + projectId = ""; + } - if (!apiKey || !projectId) { + if (!apiKey) { + throw new Error( + "FlutterFlow API Key not configured. Please set your API key in the API Keys settings.", + ); + } + if (!projectId) { throw new Error( - "FlutterFlow credentials not configured. Please set your API key and Project ID in the API Keys settings.", + "No confirmed FlutterFlow project target. Choose a project from the loaded list in API Keys settings.", ); } @@ -2770,7 +4125,6 @@ async function commitToFlutterFlow(dartCode, fileName, options = {}) { throw new Error("Invalid FlutterFlow Project ID format."); } - const endpoint = getFlutterFlowEndpoint(); const apiClient = new FlutterFlowApiClient( apiKey, projectId, @@ -2847,8 +4201,7 @@ async function commitToFlutterFlow(dartCode, fileName, options = {}) { invalidateProjectSourceCache(apiClient); commitProgress.set("push"); - const response = await apiClient.pushCode(pushRequest); - const result = await parsePushCodeResponse(response); + const result = await pushCodeWithUiTimeout(apiClient, pushRequest); if (result.success) { commitState.setSuccess({ @@ -2862,7 +4215,9 @@ async function commitToFlutterFlow(dartCode, fileName, options = {}) { } else { const errorMsg = result.errorMessage || getFlutterFlowErrorMessage(result.responseCode); - throw new Error(errorMsg); + const refusal = new Error(errorMsg); + refusal.remoteRefusal = true; + throw refusal; } return { @@ -2870,15 +4225,28 @@ async function commitToFlutterFlow(dartCode, fileName, options = {}) { message: `Successfully committed ${fileName} to FlutterFlow project ${projectId}`, addedDependencies: pubspecMerge.added, unverified: provisioning.unverified, + approximate: provisioning.approximate, warnings: result.errorMap ? Array.from(result.errorMap.entries()) : [], }; } catch (error) { console.error("Commit failed:", error); commitState.setError(error); + // A lost or timed-out response after the push means the remote outcome is + // unknown — surface it as unconfirmed, never as a fabricated failure. + if (error instanceof UnconfirmedDeployError) { + return { + success: false, + unconfirmed: true, + error: error.message, + state: commitState.currentState, + }; + } + return { success: false, error: error.message, + remoteRefusal: error.remoteRefusal === true, state: commitState.currentState, }; } @@ -2917,6 +4285,18 @@ async function executeCommit(code, options = {}) { console.log(`Starting commit for ${artifactName} (${artifactType})`); + // Written before the try so the catch can decide partial vs failed: once the + // runner has upserted custom classes, a failure of the remaining sync is a + // genuine partial outcome, not a clean total failure. + let provisionClassesWritten = false; + const targetIdentity = { + projectId: null, + endpoint: getFlutterFlowEndpoint(), + artifactType, + artifactName, + fileName, + }; + try { // Step 1: Prepare the code commitState.setState(CommitState.PREPARING); @@ -2929,8 +4309,18 @@ async function executeCommit(code, options = {}) { // Step 3: Validate FlutterFlow credentials commitState.setState(CommitState.VALIDATING); const apiKey = await getApiKey("flutterflow"); - const projectId = - commitTargetProjectId || (await getApiKey("flutterflow_project_id")); + const endpoint = getFlutterFlowEndpoint(); + const storedProjectId = await getApiKey("flutterflow_project_id"); + // The modal's choice was gated on its list identity at read time; the + // stored fallback verifies against this deploy's captured key so the push + // always pairs one credential identity — and a key save or endpoint + // switch landing during that verification refuses rather than pairing + // the captured key with a target confirmed for another identity. + let projectId = + commitTargetProjectId || (await getConfirmedStoredProjectId(apiKey)); + if (apiKey !== flutterflowApiKey || endpoint !== getFlutterFlowEndpoint()) { + projectId = ""; + } if (!apiKey) { throw new Error( @@ -2939,7 +4329,9 @@ async function executeCommit(code, options = {}) { } if (!projectId) { throw new Error( - "FlutterFlow Project ID not configured. Please add it in API Keys settings.", + storedProjectId + ? "The FlutterFlow project target is not confirmed for your current API key. Reopen the deploy dialog and choose a project from the loaded list." + : "FlutterFlow Project ID not configured. Please add it in API Keys settings.", ); } @@ -2947,6 +4339,10 @@ async function executeCommit(code, options = {}) { throw new Error("Invalid FlutterFlow Project ID format."); } + // Identity is captured as soon as the project is validated so an early + // unconfirmed outcome still names the target it was deploying to. + targetIdentity.projectId = projectId; + // Step 5: Prepare file map const fileMap = new Map(); fileMap.set(codeInfo.fileName, { @@ -2973,7 +4369,6 @@ async function executeCommit(code, options = {}) { } commitState.setState(CommitState.PUSHING); - const endpoint = getFlutterFlowEndpoint(); const apiClient = new FlutterFlowApiClient( apiKey, projectId, @@ -2991,6 +4386,7 @@ async function executeCommit(code, options = {}) { `Provision ${artifactName} custom class`, serializedYaml, ); + provisionClassesWritten = provisioning.provisionSucceeded === true; const syncMetadata = await buildApiSyncMetadata( provisioning.syncFileMap, @@ -3024,8 +4420,7 @@ async function executeCommit(code, options = {}) { invalidateProjectSourceCache(apiClient); commitProgress.set("push"); - const response = await apiClient.pushCode(pushRequest); - const result = await parsePushCodeResponse(response); + const result = await pushCodeWithUiTimeout(apiClient, pushRequest); // Step 10: Handle result if (result.success) { @@ -3041,8 +4436,10 @@ async function executeCommit(code, options = {}) { success: true, message: `Successfully committed ${codeInfo.fileName} to FlutterFlow`, metadata, + targetIdentity, addedDependencies: pubspecMerge.added, unverified: provisioning.unverified, + approximate: provisioning.approximate, warnings: result.errorMap ? Array.from(result.errorMap.entries()) : [], elapsedTime: commitState.getElapsedTime(), }; @@ -3051,6 +4448,7 @@ async function executeCommit(code, options = {}) { result.errorMessage || getFlutterFlowErrorMessage(result.responseCode); const errorWithMap = new Error(errorMsg); errorWithMap.errorMap = result.errorMap; + errorWithMap.remoteRefusal = true; throw errorWithMap; } } catch (error) { @@ -3074,10 +4472,40 @@ async function executeCommit(code, options = {}) { } } + // A client-side wait expiry or a dropped stream means the remote outcome + // is unknown: report unconfirmed, never fabricated failed or committed. + if (error instanceof UnconfirmedDeployError) { + return { + success: false, + unconfirmed: true, + error: error.message, + errorMap, + targetIdentity, + state: commitState.currentState, + elapsedTime: commitState.getElapsedTime(), + }; + } + + // Custom classes were already upserted but the remaining sync failed: + // that is a partial outcome, and concealing the written classes would lie. + if (provisionClassesWritten) { + return { + success: false, + partial: true, + error: error.message, + errorMap, + targetIdentity, + state: commitState.currentState, + elapsedTime: commitState.getElapsedTime(), + }; + } + return { success: false, error: error.message, errorMap: errorMap, + remoteRefusal: error.remoteRefusal === true, + targetIdentity, state: commitState.currentState, elapsedTime: commitState.getElapsedTime(), }; @@ -3087,6 +4515,17 @@ async function executeCommit(code, options = {}) { async function executeBundleCommit(bundlePlan, options = {}) { const { pipelineResult } = options; + let provisionClassesWritten = false; + const targetIdentity = { + projectId: null, + endpoint: getFlutterFlowEndpoint(), + artifactType: "Bundle", + artifactName: bundlePlan?.title, + fileName: bundlePlan?.fileEntries + ? `${bundlePlan.fileEntries.length} artifacts` + : "bundle", + }; + try { commitState.setState(CommitState.PREPARING); if (bundlePlan.errors?.length > 0) { @@ -3118,21 +4557,38 @@ async function executeBundleCommit(bundlePlan, options = {}) { commitState.setState(CommitState.VALIDATING); const apiKey = await getApiKey("flutterflow"); - const projectId = - commitTargetProjectId || (await getApiKey("flutterflow_project_id")); + const endpoint = getFlutterFlowEndpoint(); + const storedProjectId = await getApiKey("flutterflow_project_id"); + // The modal's choice was gated on its list identity at read time; the + // stored fallback verifies against this deploy's captured key so the push + // always pairs one credential identity — and a key save or endpoint + // switch landing during that verification refuses rather than pairing + // the captured key with a target confirmed for another identity. + let projectId = + commitTargetProjectId || (await getConfirmedStoredProjectId(apiKey)); + if (apiKey !== flutterflowApiKey || endpoint !== getFlutterFlowEndpoint()) { + projectId = ""; + } if (!apiKey) { throw new Error("FlutterFlow API Key not configured. Please add it in API Keys settings."); } if (!projectId) { - throw new Error("FlutterFlow Project ID not configured. Please add it in API Keys settings."); + throw new Error( + storedProjectId + ? "The FlutterFlow project target is not confirmed for your current API key. Reopen the deploy dialog and choose a project from the loaded list." + : "FlutterFlow Project ID not configured. Please add it in API Keys settings.", + ); } if (!validateFlutterFlowProjectId(projectId)) { throw new Error("Invalid FlutterFlow Project ID format."); } + // Identity is captured as soon as the project is validated so an early + // unconfirmed outcome still names the target it was deploying to. + targetIdentity.projectId = projectId; + commitState.setState(CommitState.PUSHING); - const endpoint = getFlutterFlowEndpoint(); const apiClient = new FlutterFlowApiClient( apiKey, projectId, @@ -3152,6 +4608,7 @@ async function executeBundleCommit(bundlePlan, options = {}) { `Provision ${bundlePlan.title} custom classes`, serializedYaml, ); + provisionClassesWritten = provisioning.provisionSucceeded === true; const syncMetadata = await buildApiSyncMetadata( provisioning.syncFileMap, provisioning.remoteFiles, @@ -3182,8 +4639,7 @@ async function executeBundleCommit(bundlePlan, options = {}) { invalidateProjectSourceCache(apiClient); commitProgress.set("push"); - const response = await apiClient.pushCode(pushRequest); - const result = await parsePushCodeResponse(response); + const result = await pushCodeWithUiTimeout(apiClient, pushRequest); if (result.success) { const metadata = { @@ -3205,8 +4661,10 @@ async function executeBundleCommit(bundlePlan, options = {}) { success: true, message: `Successfully committed ${bundlePlan.fileEntries.length} artifacts to FlutterFlow`, metadata, + targetIdentity, addedDependencies: pubspecMerge.added, unverified: provisioning.unverified, + approximate: provisioning.approximate, warnings: result.errorMap ? Array.from(result.errorMap.entries()) : [], elapsedTime: commitState.getElapsedTime(), }; @@ -3215,14 +4673,43 @@ async function executeBundleCommit(bundlePlan, options = {}) { const errorMsg = result.errorMessage || getFlutterFlowErrorMessage(result.responseCode); const errorWithMap = new Error(errorMsg); errorWithMap.errorMap = result.errorMap; + errorWithMap.remoteRefusal = true; throw errorWithMap; } catch (error) { console.error("Bundle commit execution failed:", error); commitState.setError(error); + + const errorMap = error.errorMap || new Map(); + + if (error instanceof UnconfirmedDeployError) { + return { + success: false, + unconfirmed: true, + error: error.message, + errorMap, + targetIdentity, + state: commitState.currentState, + elapsedTime: commitState.getElapsedTime(), + }; + } + + if (provisionClassesWritten) { + return { + success: false, + partial: true, + error: error.message, + errorMap, + targetIdentity, + state: commitState.currentState, + elapsedTime: commitState.getElapsedTime(), + }; + } + return { success: false, error: error.message, - errorMap: error.errorMap || new Map(), + errorMap, + targetIdentity, state: commitState.currentState, elapsedTime: commitState.getElapsedTime(), }; @@ -3244,11 +4731,16 @@ async function runPromptArchitect(userInput, images = []) { return result } catch (error) { if (error.isModelArmor) throw error + // An exhausted allowance must keep its marker or the failure view loses + // the upgrade action and stage attribution. + if (error.isUsageLimit) throw error + // A cancelled request is a stale run, not a stage failure. + if (error.isPipelineCancel) throw error throw new Error(`Prompt Architect failed: ${error.message}`) } } -async function runCodeGenerator(masterPrompt, selectedModel, images = []) { +async function runCodeGenerator(masterPrompt, selectedModel, images = [], runId) { const prompt = buildGeneratorPrompt(masterPrompt) const context = createBuildShipContext("generator", pipelineState.bundleSpec) try { @@ -3256,13 +4748,27 @@ async function runCodeGenerator(masterPrompt, selectedModel, images = []) { return result } catch (primaryError) { if (primaryError.isModelArmor) throw primaryError + // An exhausted allowance is not a model problem: retrying on the fallback + // model would spend another request and lose the quota signal the view + // needs to offer an upgrade. + if (primaryError.isUsageLimit) throw primaryError + // A cancelled request is a stale run, not a model problem: it must not + // trigger a second request on the fallback model. + if (primaryError.isPipelineCancel) throw primaryError if (selectedModel !== FALLBACK_MODEL) { console.warn(`Code Generator failed with ${selectedModel}, retrying with fallback model:`, primaryError.message) + // The fallback is a real service event, so the run says so while it + // continues rather than silently swapping models behind the progress. + notePipelineFallback(selectedModel, FALLBACK_MODEL, runId) try { const result = await callBuildShip("generator", FALLBACK_MODEL, prompt, context, images) return result } catch (fallbackError) { if (fallbackError.isModelArmor) throw fallbackError + // A quota refusal on the fallback is terminal the same way it was on + // the primary: wrap it and the upgrade affordance is lost. + if (fallbackError.isUsageLimit) throw fallbackError + if (fallbackError.isPipelineCancel) throw fallbackError throw new Error(`Code Generator failed: primary (${selectedModel}): ${primaryError.message} | fallback (${FALLBACK_MODEL}): ${fallbackError.message}`) } } @@ -3280,6 +4786,10 @@ async function runCodeReview(code, architectOutput = null) { return result } catch (error) { if (error.isModelArmor) throw error + // An exhausted allowance must keep its marker or the failure view loses + // the upgrade action and stage attribution. + if (error.isUsageLimit) throw error + if (error.isPipelineCancel) throw error throw new Error(`Code Review failed: ${error.message}`) } } @@ -3448,6 +4958,114 @@ function updateModelInfo(selectedModel) { console.log(`Step 3 (Code Review): ${getModelLabel(CODE_REVIEW_MODEL)}`) } +/** + * Snapshot the current successful generation result so a failed refinement or + * build-error replacement can restore it verbatim. The selected artifact, full + * bundle, prompt, review and selection are held untouched until a replacement + * generation AND review both succeed. + */ +function snapshotGenerationResult() { + return { + step1Result: pipelineState.step1Result, + step2Result: pipelineState.step2Result, + step3Result: pipelineState.step3Result, + artifactBundle: pipelineState.artifactBundle, + bundleReview: pipelineState.bundleReview, + selectedArtifactId: pipelineState.selectedArtifactId, + resultsViewMode: pipelineState.resultsViewMode, + }; +} + +/** + * Bring a prior successful result back into shared state and reconcile the + * selection to an id that still exists in the restored bundle (so the prior + * result never points at a stale artifact that the failed replacement no + * longer defined). + */ +function restoreGenerationResult(snapshot) { + if (!snapshot) return; + Object.assign(pipelineState, snapshot); + const ids = new Set((pipelineState.artifactBundle?.artifacts || []).map((a) => a.id)); + if (!ids.has(pipelineState.selectedArtifactId)) { + pipelineState.selectedArtifactId = + getPrimaryArtifact(pipelineState.artifactBundle)?.id || null; + } +} + +const RESULTS_REPLACEMENT_ERROR_ID = "results-replacement-error"; + +/** Persistent error + retry UI that sits over the retained previous result. */ +function showReplacementFailure(error, { stage = 2, runId, retry }) { + if (!isCurrentPipelineRun(runId)) return; + const banner = document.getElementById(RESULTS_REPLACEMENT_ERROR_ID); + if (!banner) return; + const failure = classifyPipelineError(error); + const titleEl = document.getElementById("results-replacement-error-title"); + const messageEl = document.getElementById("results-replacement-error-message"); + const retryEl = document.getElementById("results-replacement-error-retry"); + const upgradeEl = document.getElementById("results-replacement-error-upgrade"); + if (titleEl) titleEl.textContent = `${PIPELINE_STAGE_LABELS[stage] || "Regeneration"}: ${failure.title}`; + if (messageEl) messageEl.textContent = failure.message; + banner.hidden = false; + + // A quota/usage-limit rejection is the one failure a protected retry cannot + // fix — re-firing launches another generation into an already-exhausted + // allowance, a dead end. Surface the upgrade affordance as the primary + // action, exactly as the non-replacement path does. Every other failure + // keeps the retry. + let focusTarget = null; + if (upgradeEl) { + upgradeEl.hidden = !failure.canUpgrade; + if (failure.canUpgrade) { + upgradeEl.textContent = "View plans"; + upgradeEl.onclick = () => openPricingModal(); + focusTarget = upgradeEl; + } + } + if (retryEl) { + retryEl.hidden = failure.canUpgrade; + if (!failure.canUpgrade) { + retryEl.onclick = () => { + hideReplacementFailure(); + if (typeof retry === "function") retry(); + }; + retryEl.textContent = "Retry"; + focusTarget = retryEl; + } + } + // Keyboard accessible: a failed replacement lands focus on the action that + // can actually resolve it. + (focusTarget || banner).focus({ preventScroll: true }); +} + +function hideReplacementFailure() { + const banner = document.getElementById(RESULTS_REPLACEMENT_ERROR_ID); + if (banner) banner.hidden = true; +} + +/** + * Shared completion path for a replacement run (refinement / build-error fix): + * the previous successful result is restored verbatim, the Results surface is + * repainted from it, and a persistent error + retry banner is shown. A toast + * alone is insufficient - the old code and review must stay inspectable and + * copyable while the user decides whether to retry. + */ +function restoreAndShowReplacementFailure(error, { previous, stage, runId, retry }) { + if (!isCurrentPipelineRun(runId)) return; + if (error.isUsageLimit) updateUsageDisplay(); + restoreGenerationResult(previous); + hidePipelineProgress(); + setGenerationStageVisible(true); + showResultsView(); + // showResultsView lands every result on Summary; a restored result goes + // back to whichever surface the user was inspecting before the run failed. + pipelineState.resultsViewMode = previous.resultsViewMode || "summary"; + updateSelectedArtifactPanels(); + cancelPipelineMorph(); + showReplacementFailure(error, { stage, runId, retry }); + updateDeployButtonVisibility(); +} + async function runRefinement() { console.log("runRefinement called"); @@ -3458,9 +5076,14 @@ async function runRefinement() { // Set running state pipelineState.isRunning = true; + const runId = startPipelineRun(); callEndpoint('standardRegenerate', pipelineState.step2Result, pipelineState.step1Result) const btns = document.querySelectorAll(".btn-refine-action"); + // Hold the prior successful result verbatim until a replacement generation + // AND review both succeed; a failure restores it below. + const previousResult = snapshotGenerationResult(); + btns.forEach((btn) => { btn.disabled = true; btn.innerHTML = ` @@ -3470,7 +5093,9 @@ async function runRefinement() { }); try { + hideReplacementFailure(); const selectedArtifact = getSelectedArtifact(); + const refinedArtifactId = selectedArtifact.id; const refinementPrompt = buildArtifactRegenerationPrompt({ bundleSpec: pipelineState.step1Result, artifactBundle: JSON.stringify(pipelineState.artifactBundle || pipelineState.step2Result), @@ -3479,20 +5104,28 @@ async function runRefinement() { userFeedback: "Fix the issues listed in the audit report.", }); - // Show progress bar for refinement - showPipelineProgress(); - updatePipelineProgressStep(2); + // Show progress bar for refinement. The run was already claimed above, + // so a late response from an older run cannot overwrite this one. + showPipelineProgress({ runId }); + updatePipelineProgressStep(2, runId); // Step 2: Code Generator (Refinement) selectWorkflowStep(2); showStepLoading(2, true); - // We use the same runCodeGenerator function but with the refinement prompt - pipelineState.step2Result = await runCodeGenerator( + // We use the same runCodeGenerator function but with the refinement + // prompt. Stage results commit to shared state only after the run is + // revalidated, so an abandoned run cannot overwrite a newer one. + const step2Result = await runCodeGenerator( refinementPrompt, selectedModel, + [], + runId, ); + if (!isCurrentPipelineRun(runId)) return; + pipelineState.step2Result = step2Result; updateArtifactBundleFromGeneratedCode(); + completePipelineStage(2, runId); const step2Output = document.getElementById("step2-output"); const cleanStep2 = extractCodeFromMarkdown(pipelineState.step2Result); @@ -3502,14 +5135,27 @@ async function runRefinement() { // Step 3: Code Audit (Re-audit) selectWorkflowStep(3); - updatePipelineProgressStep(3); + updatePipelineProgressStep(3, runId); showStepLoading(3, true); - pipelineState.step3Result = await runCodeReview( + const step3Result = await runCodeReview( pipelineState.step2Result, pipelineState.step1Result, ); + if (!isCurrentPipelineRun(runId)) return; + pipelineState.step3Result = step3Result; updateBundleReviewFromReviewResult(); + completePipelineStage(3, runId); + + // The whole replacement (generation + review) succeeded, so the new result + // is committed. Reconcile the selection onto the re-refined artifact if it + // still exists, otherwise fall back to the new bundle's primary — either + // way the tabs are rebuilt from the new bundle, so none go stale. + if (pipelineState.artifactBundle?.artifacts?.some((a) => a.id === refinedArtifactId)) { + pipelineState.selectedArtifactId = refinedArtifactId; + } else { + pipelineState.selectedArtifactId = getPrimaryArtifact(pipelineState.artifactBundle)?.id || null; + } const auditOutput = document.getElementById("step3-output"); auditOutput.textContent = pipelineState.step3Result; @@ -3522,15 +5168,34 @@ async function runRefinement() { showResultsView(cleanStep2, auditHtml); } catch (error) { console.error("Refinement failed:", error); - hidePipelineProgress(); - showToast(getPipelineErrorMessage(error, "Refinement failed"), "error"); + if (!isCurrentPipelineRun(runId)) return; + + const errorStep = resolvePipelineErrorStep(error, { + architect: 2, + generator: 2, + review: 3, + }); + + // Restore the previous successful result and keep it visible and copyable + // with persistent error + retry UI; the failed replacement never owns the + // screen. + restoreAndShowReplacementFailure(error, { + previous: previousResult, + stage: errorStep, + runId, + retry: runRefinement, + }); } finally { - pipelineState.isRunning = false; + // The control's own busy affordance is restored even for an abandoned + // run — the run guard only protects shared pipeline state. btns.forEach((btn) => { btn.disabled = false; btn.textContent = "Refine & Regenerate"; }); - updateDeployButtonVisibility(); + if (isCurrentPipelineRun(runId)) { + pipelineState.isRunning = false; + updateDeployButtonVisibility(); + } } } @@ -3584,6 +5249,7 @@ async function regenerateFromPastedErrors() { const selectedModel = document.getElementById("code-generator-model").value pipelineState.isRunning = true + const runId = startPipelineRun() callEndpoint('flutterflowError', pipelineState.step2Result, pastedErrors) const btn = document.getElementById("btn-fix-from-errors") @@ -3594,7 +5260,12 @@ async function regenerateFromPastedErrors() { Fixing…` } + // Hold the prior successful result verbatim until the bundle replacement + // generation AND review both succeed; a failure restores it below. + const previousResult = snapshotGenerationResult() + try { + hideReplacementFailure() const refinementPrompt = buildBundleRegenerationPrompt({ bundleSpec: pipelineState.step1Result, artifactBundle: JSON.stringify(pipelineState.artifactBundle || pipelineState.step2Result), @@ -3603,14 +5274,17 @@ async function regenerateFromPastedErrors() { }); hideErrorInputPanel() - showPipelineProgress() - updatePipelineProgressStep(2) + showPipelineProgress({ runId }) + updatePipelineProgressStep(2, runId) selectWorkflowStep(2) showStepLoading(2, true) - pipelineState.step2Result = await runCodeGenerator(refinementPrompt, selectedModel) + const step2Result = await runCodeGenerator(refinementPrompt, selectedModel, [], runId) + if (!isCurrentPipelineRun(runId)) return + pipelineState.step2Result = step2Result updateArtifactBundleFromGeneratedCode() + completePipelineStage(2, runId) const step2Output = document.getElementById("step2-output") const cleanStep2 = extractCodeFromMarkdown(pipelineState.step2Result) @@ -3619,11 +5293,14 @@ async function regenerateFromPastedErrors() { showStepLoading(2, false) selectWorkflowStep(3) - updatePipelineProgressStep(3) + updatePipelineProgressStep(3, runId) showStepLoading(3, true) - pipelineState.step3Result = await runCodeReview(pipelineState.step2Result, pipelineState.step1Result) + const step3Result = await runCodeReview(pipelineState.step2Result, pipelineState.step1Result) + if (!isCurrentPipelineRun(runId)) return + pipelineState.step3Result = step3Result updateBundleReviewFromReviewResult() + completePipelineStage(3, runId) const auditOutput = document.getElementById("step3-output") auditOutput.textContent = pipelineState.step3Result @@ -3636,15 +5313,32 @@ async function regenerateFromPastedErrors() { if (input) input.value = "" } catch (error) { console.error("Fix from errors failed:", error) - hidePipelineProgress() - showToast(getPipelineErrorMessage(error, "Failed to fix errors"), "error") + if (!isCurrentPipelineRun(runId)) return + + const errorStep = resolvePipelineErrorStep(error, { + architect: 2, + generator: 2, + review: 3, + }) + + // Restore the previous successful result and keep it visible and copyable + // with persistent error + retry UI; the failed replacement never owns the + // screen. + restoreAndShowReplacementFailure(error, { + previous: previousResult, + stage: errorStep, + runId, + retry: regenerateFromPastedErrors, + }) } finally { - pipelineState.isRunning = false if (btn) { btn.disabled = false btn.textContent = "Fix Errors & Regenerate" } - updateDeployButtonVisibility() + if (isCurrentPipelineRun(runId)) { + pipelineState.isRunning = false + updateDeployButtonVisibility() + } } } @@ -3659,40 +5353,62 @@ async function runThinkingPipeline() { const userInput = document.getElementById("pipeline-input").value; const selectedModel = document.getElementById("code-generator-model").value; + // Freeze the attachment list at submission time: a thumbnail removal or a + // non-vision model switch during the preflight awaits below must not change + // the images this run was started with. Still-pending slots live in the + // slice too — their jobs commit into these same objects before the payload + // is built, so the wait-for-uploads path still works. + const submittedImages = promptImages.slice(); if (!userInput.trim()) { showToast("Please describe your FlutterFlow widget first.", "warning"); return; } - if (!(await canRunPipeline())) return; + // The run is claimed before the first await, so a second submission during + // preflight sees it already running instead of starting a concurrent run + // beside it. + pipelineState.isRunning = true; + const runId = startPipelineRun(); + + try { + // A submission can beat startup auth/subscription reconciliation; wait for + // it so entitlement checks see the real session instead of free defaults. + await sessionReadiness; + if (!isCurrentPipelineRun(runId)) return; + + // Images still uploading must join this run: wait for every accepted file + // to produce a URL (or fail out). Their slots sit in the frozen + // submittedImages slice, so commits land there without needing promptImages. + if (pendingImageUploads.length) { + await Promise.allSettled(pendingImageUploads.map((entry) => entry.job)); + } + if (!isCurrentPipelineRun(runId)) return; - await ensureIdentityReady(); + if (!(await canRunPipeline())) return; + if (!isCurrentPipelineRun(runId)) return; - const effectiveModel = getEffectiveModel(selectedModel); + await ensureIdentityReady(); + if (!isCurrentPipelineRun(runId)) return; - trackEvent("Pipeline Started", { - selectedModel, - effectiveModel, - inputLength: userInput.length - }); + const effectiveModel = getEffectiveModel(selectedModel); - const btn = document.getElementById("btn-run-pipeline"); + trackEvent("Pipeline Started", { + selectedModel, + effectiveModel, + inputLength: userInput.length + }); - // Reset state - pipelineState.isRunning = true; - resetPipelineResults(); + // Reset state + resetPipelineResults(); + pipelineState.submittedPrompt = userInput; + pipelineState.submittedImages = submittedImages.filter((img) => img.url); - btn.disabled = true; - btn.innerHTML = ` - - - Running...`; + setRunPipelineButtonBusy(true); - // Update model info - updateModelInfo(effectiveModel); + // Update model info + updateModelInfo(effectiveModel); - try { // Dismiss welcome video and hide ready state, show progress dismissWelcomeVideo(); const readyState = document.getElementById("ready-state"); @@ -3700,25 +5416,36 @@ async function runThinkingPipeline() { const paywallEl = document.getElementById("paywall-exhausted"); if (paywallEl) paywallEl.classList.add("hidden"); - // Show pipeline progress bar - showPipelineProgress(); + // Show pipeline progress bar. The outline morph runs over the panel once + // the panel itself is in place, so busy feedback is immediate either way. + const composerRect = document.getElementById("composer")?.getBoundingClientRect(); + const heroRect = document.getElementById("hero")?.getBoundingClientRect(); + showPipelineProgress({ prompt: userInput, runId }); + morphComposerToPipeline(composerRect, heroRect); // Step 1: Prompt Architect selectWorkflowStep(1); - updatePipelineProgressStep(1); + updatePipelineProgressStep(1, runId); showStepLoading(1, true); // Uploaded image URLs are sent to both the architect and the generator so // the vision-carrying model sees them when producing the widget. - const imagePayload = promptImages - .filter((img) => img.url) - .map((img) => ({ url: img.url })); + const imagePayload = pipelineState.submittedImages.map((img) => ({ + url: img.url, + })); - pipelineState.step1Result = await runPromptArchitect( + // A stage result commits to shared pipeline state only after its run is + // revalidated: a response that lands after the user started a newer run + // belongs to a run nobody is watching any more, so it must not touch + // pipeline state or the view. + const step1Result = await runPromptArchitect( userInput, imagePayload, ); + if (!isCurrentPipelineRun(runId)) return; + pipelineState.step1Result = step1Result; updateBundleSpecFromArchitectResult(); + completePipelineStage(1, runId); trackEvent("Prompt Architect Completed"); const step1Output = document.getElementById("step1-output") @@ -3729,15 +5456,19 @@ async function runThinkingPipeline() { // Step 2: Code Generator selectWorkflowStep(2); - updatePipelineProgressStep(2); + updatePipelineProgressStep(2, runId); showStepLoading(2, true); - pipelineState.step2Result = await runCodeGenerator( + const step2Result = await runCodeGenerator( pipelineState.step1Result, effectiveModel, imagePayload, + runId, ); + if (!isCurrentPipelineRun(runId)) return; + pipelineState.step2Result = step2Result; updateArtifactBundleFromGeneratedCode(); + completePipelineStage(2, runId); trackEvent("Code Generator Completed"); const step2Output = document.getElementById("step2-output"); @@ -3748,14 +5479,17 @@ async function runThinkingPipeline() { // Step 3: Code Audit selectWorkflowStep(3); - updatePipelineProgressStep(3); + updatePipelineProgressStep(3, runId); showStepLoading(3, true); - pipelineState.step3Result = await runCodeReview( + const step3Result = await runCodeReview( pipelineState.step2Result, pipelineState.step1Result, ); + if (!isCurrentPipelineRun(runId)) return; + pipelineState.step3Result = step3Result; updateBundleReviewFromReviewResult(); + completePipelineStage(3, runId); trackEvent("Code Review Completed"); const auditOutput = document.getElementById("step3-output"); @@ -3763,85 +5497,44 @@ async function runThinkingPipeline() { showStepLoading(3, false); - // Hide progress bar and show split-panel results + // Every stage reported, so the Results view is a real outcome: expand the + // panel into it and hand the outline morph over to the expansion. hidePipelineProgress(); const auditHtml = renderMarkdownAudit(pipelineState.step3Result); showResultsView(cleanStep2, auditHtml); } catch (error) { - console.error("Pipeline failed:", error); - hidePipelineProgress(); - - if (error.isUsageLimit) { - const { count } = getUsage() - showPaywallExhausted(count, getRunLimit(), { openModal: true }) - return - } - - trackEvent("Pipeline Failed", { - error: error.message, - effectiveModel: getEffectiveModel(document.getElementById("code-generator-model").value) - }); - - // Determine which step failed based on the error context - const modelArmorSteps = { + // A cancelled request belongs to a run the user already abandoned; it is + // not a failure and the run check below discards it quietly anyway. + if (!error.isPipelineCancel) console.error("Pipeline failed:", error); + // A terminated run never renders a result. The failure replaces the + // in-flight state in the same panel and stays there until the user acts. + if (!isCurrentPipelineRun(runId)) return; + + const errorStep = resolvePipelineErrorStep(error, { architect: 1, generator: 2, review: 3, - }; - const errorStep = resolvePipelineErrorStep(error, modelArmorSteps); - - selectWorkflowStep(errorStep); - const resultDiv = document.getElementById(`step${errorStep}-result`); - const loadingDiv = document.getElementById(`step${errorStep}-loading`); - const output = document.getElementById(`step${errorStep}-output`); - - // Hide loading and show error - if (loadingDiv) loadingDiv.classList.add("hidden"); - if (resultDiv) resultDiv.classList.remove("hidden"); - - if (output) { - if (error.isModelArmor) { - output.innerHTML = ``; - } else { - // Format error message based on type - let errorMessage = error.message; - if (error.message.includes("image input")) { - errorMessage = - `This model doesn't support image input. Please use ${getModelLabel(FREE_MODEL)} for image-based requests or remove image references from your prompt.`; - } else if ( - error.message.includes("Load failed") || - error.message.includes("CORS") - ) { - errorMessage = - "API connection failed. This might be due to CORS restrictions or network issues. Please check your API key and try again."; - } + }); - output.innerHTML = `
-

Connection Error

-

${escapeHtml(errorMessage)}

-
-

Check if API key is valid

-

Try using a different model

-

Ensure network allows API calls

-
-
`; - } + if (error.isUsageLimit) { + updateUsageDisplay(); + } else { + trackEvent("Pipeline Failed", { + error: error.message, + effectiveModel: getEffectiveModel(document.getElementById("code-generator-model").value) + }); } + selectWorkflowStep(errorStep); + showStepLoading(errorStep, false); + showPipelineFailure(error, { stage: errorStep, runId }); updateStepIndicator(errorStep, "error"); } finally { - pipelineState.isRunning = false; - btn.disabled = false; - btn.innerHTML = ` - - - Run Pipeline`; - - updateDeployButtonVisibility(); + if (isCurrentPipelineRun(runId)) { + pipelineState.isRunning = false; + setRunPipelineButtonBusy(false); + updateDeployButtonVisibility(); + } } } @@ -4022,6 +5715,7 @@ async function regenerateWithErrors(originalError, errorMap) { const selectedModel = document.getElementById("code-generator-model").value; pipelineState.isRunning = true; + const runId = startPipelineRun(); const btn = document.getElementById("btn-regenerate-from-error"); if (btn) { @@ -4052,19 +5746,25 @@ async function regenerateWithErrors(originalError, errorMap) { userFeedback: errorContext, }); - showPipelineProgress(); - updatePipelineProgressStep(2); + showPipelineProgress({ runId }); + updatePipelineProgressStep(2, runId); // Go to step 2 selectWorkflowStep(2); showStepLoading(2, true); - // Generate new code - pipelineState.step2Result = await runCodeGenerator( + // Generate new code. Stage results commit to shared state only after the + // run is revalidated, so an abandoned run cannot overwrite a newer one. + const step2Result = await runCodeGenerator( refinementPrompt, selectedModel, + [], + runId, ); + if (!isCurrentPipelineRun(runId)) return; + pipelineState.step2Result = step2Result; updateArtifactBundleFromGeneratedCode(); + completePipelineStage(2, runId); const step2Output = document.getElementById("step2-output"); const cleanStep2 = extractCodeFromMarkdown(pipelineState.step2Result); @@ -4074,14 +5774,17 @@ async function regenerateWithErrors(originalError, errorMap) { // Run audit selectWorkflowStep(3); - updatePipelineProgressStep(3); + updatePipelineProgressStep(3, runId); showStepLoading(3, true); - pipelineState.step3Result = await runCodeReview( + const step3Result = await runCodeReview( pipelineState.step2Result, pipelineState.step1Result, ); + if (!isCurrentPipelineRun(runId)) return; + pipelineState.step3Result = step3Result; updateBundleReviewFromReviewResult(); + completePipelineStage(3, runId); const auditOutput = document.getElementById("step3-output"); auditOutput.textContent = pipelineState.step3Result; @@ -4093,17 +5796,35 @@ async function regenerateWithErrors(originalError, errorMap) { showResultsView(cleanStep2, auditHtml); } catch (error) { console.error("Regeneration failed:", error); - hidePipelineProgress(); - showToast(getPipelineErrorMessage(error, "Regeneration failed"), "error"); - } finally { - pipelineState.isRunning = false; + if (!isCurrentPipelineRun(runId)) return; + const errorStep = resolvePipelineErrorStep(error, { + architect: 2, + generator: 2, + review: 3, + }); + + if (error.isUsageLimit) { + updateUsageDisplay(); + } + + selectWorkflowStep(errorStep); + showStepLoading(errorStep, false); + showPipelineFailure(error, { + stage: errorStep, + runId, + retry: () => regenerateWithErrors(originalError, errorMap), + }); + updateStepIndicator(errorStep, "error"); + } finally { if (btn) { btn.disabled = false; btn.textContent = "Fix Errors & Regenerate"; } - - updateDeployButtonVisibility(); + if (isCurrentPipelineRun(runId)) { + pipelineState.isRunning = false; + updateDeployButtonVisibility(); + } } } @@ -4235,12 +5956,23 @@ async function initializeAuth() { const magicToken = params.get('token') if (magicToken) { - window.history.replaceState({}, '', window.location.pathname) + window.history.replaceState({}, '', window.location.pathname + window.location.hash) try { const { email, sessionToken } = await verifyMagicLink(magicToken) saveSession(email, sessionToken) + closeSignInModal() + // Land back on whichever surface (composer, plans, billing) the user + // asked to sign in from, unless the link itself already carried a hash. + const returnHash = consumeSignInReturnSurface() + if (returnHash && !window.location.hash) window.location.hash = returnHash } catch (err) { - showToast(err.message || 'Sign-in link invalid or expired.', 'error') + consumeSignInReturnSurface() + const message = err.message || 'Sign-in link invalid or expired.' + showToast(message, 'error') + // Surface the failure inline too, with the retry control right there, + // instead of leaving the user to hunt for a way back in. + openSignInModal() + setSignInMessage(message, 'error') } } else { const { email, sessionToken } = getStoredSession() @@ -4257,49 +5989,192 @@ async function initializeAuth() { updateAuthUI() } -function openSignInModal() { - const modal = document.getElementById('signin-modal') - if (modal) modal.classList.add('open') -} - -function closeSignInModal(event) { - if (event && event.target !== event.currentTarget) return - const modal = document.getElementById('signin-modal') - if (modal) modal.classList.remove('open') +// Records which surface (home/composer, plans, or account/billing) the user +// was on when they opened the sign-in modal, so a magic-link click — which +// lands as a fresh page load — can return them there. Keyed by URL hash, +// which is how switchView() already tracks the current surface. +function rememberSignInReturnSurface() { + try { + localStorage.setItem(SIGNIN_RETURN_STORAGE_KEY, JSON.stringify({ + hash: window.location.hash || '#home', + ts: Date.now(), + })) + } catch (err) { + console.warn('rememberSignInReturnSurface: failed to persist return surface:', err) + } +} + +function consumeSignInReturnSurface() { + try { + const raw = localStorage.getItem(SIGNIN_RETURN_STORAGE_KEY) + localStorage.removeItem(SIGNIN_RETURN_STORAGE_KEY) + if (!raw) return null + const { hash, ts } = JSON.parse(raw) + if (!hash || typeof ts !== 'number' || Date.now() - ts > SIGNIN_RETURN_TTL_MS) return null + return hash + } catch (err) { + console.warn('consumeSignInReturnSurface: failed to read return surface:', err) + return null + } +} + +function openSignInModal() { + const modal = document.getElementById('signin-modal') + if (!modal) return + rememberSignInReturnSurface() + const input = document.getElementById('signin-email-input') + input?.removeAttribute('aria-invalid') + setSignInMessage('') + openModal(modal) +} + +function closeSignInModal(event) { + if (event && event.target !== event.currentTarget) return + const modal = document.getElementById('signin-modal') + if (modal) closeModal(modal) +} + +function setSignInMessage(text, variant) { + const msg = document.getElementById('signin-message') + if (!msg) return + msg.textContent = text || '' + msg.classList.remove('signin-message-success', 'signin-message-error') + if (variant) msg.classList.add(`signin-message-${variant}`) } async function handleMagicLinkRequest() { const input = document.getElementById('signin-email-input') const btn = document.getElementById('signin-submit-btn') - const msg = document.getElementById('signin-message') - const email = input?.value?.trim() + const email = trimEmail(input?.value) const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ if (!email || !emailRegex.test(email) || email.length > 254) { - if (msg) msg.textContent = 'Please enter a valid email address.' + input?.setAttribute('aria-invalid', 'true') + setSignInMessage('Please enter a valid email address.', 'error') return } + input?.removeAttribute('aria-invalid') if (btn) { btn.disabled = true; btn.textContent = 'Sending…' } - if (msg) msg.textContent = '' + + // Explain the rule for known providers, but do not block submission here. + // Existing accounts on plus-tagged addresses are still allowed to recover + // because the server performs the authoritative check. + const plusAliasHint = explainPlusAliasRule(email) + if (plusAliasHint) setSignInMessage(plusAliasHint, 'error') try { - await sendMagicLink(email) - if (input) input.value = '' - if (msg) msg.textContent = `Check your email — we sent a link to ${email}` - if (btn) btn.textContent = 'Sent!' + const data = await sendMagicLink(email) + // Only the explicit success code (or a legacy code-less response) counts + // as sent. Any other code — the plus-alias rejection or an unexpected + // error — keeps the address, marks the field invalid and reports an + // error, so the user is never told to check for a link that was not sent. + const isSuccess = isMagicLinkSuccess(data) + if (input && isSuccess) input.value = '' + input?.setAttribute('aria-invalid', String(!isSuccess)) + setSignInMessage(getMagicLinkResultMessage(data, email), isSuccess ? 'success' : 'error') + // A successful send must stay retryable — the user may want to resend to + // a different address, or send another link if the first one expires — + // so the button is re-enabled either way, never left permanently disabled. + // "Sent!" is shown briefly for confirmation, then reverts so the control + // clearly reads as usable again. + if (btn) { + btn.disabled = false + btn.textContent = isSuccess ? 'Sent!' : 'Send Sign-in Link' + if (isSuccess) { + setTimeout(() => { if (btn.textContent === 'Sent!') btn.textContent = 'Send Sign-in Link' }, 2500) + } + } } catch (err) { console.error('handleMagicLinkRequest: sendMagicLink failed', { email, err }) - if (msg) msg.textContent = 'Something went wrong. Please try again.' - if (btn) { btn.disabled = false; btn.textContent = 'Send Link' } + setSignInMessage('Something went wrong. Please try again.', 'error') + if (btn) { btn.disabled = false; btn.textContent = 'Send Sign-in Link' } } } function handleSignOut() { - clearSession() - clearSubscriptionCache() - updateAuthUI() - updateSubscriptionUI() + // Reset in-memory auth/subscription state first so the immediate re-render + // below reflects a signed-out identity/plan. + authState.email = null + authState.sessionToken = null + authState.isVerified = false + subscriptionState = createSubscriptionState({ isResolved: true }) + // Remove the session + subscription cache keys (scoped adapter) and then + // synchronously re-render every identity/plan surface. + performSignOut({ + storage: window.localStorage, + onIdentityChanged: updateAuthUI, + onPlanChanged: updateSubscriptionUI, + }) +} + +// --- ACCOUNT ACCESS & DATA WIRING (STU-387) --- +// One "Send new link" controller guards against duplicate requests and reflects +// the actual response or failure into the row's status line. +const accessSendNewLink = createSendLinkController({ + sendLink: sendMagicLink, + getEmail: () => authState.email || "", + onState: renderSendNewLinkState, +}) + +function renderSendNewLinkState(state) { + const btn = document.getElementById("send-new-link-btn") + const msg = document.getElementById("send-new-link-msg") + if (!btn || !msg) return + if (state.status === "pending") { + btn.disabled = true + btn.textContent = "Sending…" + msg.className = "acct-access-msg" + msg.textContent = "Sending a fresh sign-in link…" + return + } + if (state.status === "sent") { + btn.disabled = false + btn.textContent = "Send new link" + msg.className = "acct-access-msg" + msg.textContent = getMagicLinkResultMessage(state.data, authState.email || "") || "Link sent — check your email." + return + } + // status === "error": surface the real failure, never a canned success. The + // propagated Error carries a user-safe reason (e.g. "HTTP 429", "HTTP 500") + // rather than raw server internals, and a rate-limit must not read identically + // to a server error. Fall back to the generic copy only when no reason escaped. + btn.disabled = false + btn.textContent = "Send new link" + msg.className = "acct-access-msg error" + const reason = state.error?.message + ? `Couldn't send a link right now. ${state.error.message}` + : "Couldn't send a link right now. Please try again." + msg.textContent = reason +} + +async function handleSendNewLink() { + await accessSendNewLink() +} + +function handleClearCache() { + // Scoped to the named disposable UI caches only — never usage, identity, + // credentials, or the active session, so it cannot hand out new runs. + const removed = clearDisposableUiCaches(window.localStorage) + const detail = removed.length + ? `Cleared disposable UI caches: ${removed.join(", ")}.` + : "Nothing disposable to clear." + showToast(`${detail} Your run count, identity and stored keys are kept.`, "info") +} + +function handleDeleteAccount() { + // Truthful: no backend deletion contract exists in this slice, so this control + // only explains that deletion is unavailable. It performs no deletion and + // never resets usage, identity, credentials, or the session. + if (isDeleteAccountSupported()) return + const modal = document.getElementById("delete-unavailable-modal") + if (modal) openModal(modal, { trigger: document.activeElement }) +} + +function closeDeleteUnavailableModal(event) { + if (event && event.target !== event.currentTarget) return + const modal = document.getElementById("delete-unavailable-modal") + if (modal) closeModal(modal) } function updateAuthUI() { @@ -4312,6 +6187,8 @@ function updateAuthUI() { if (guestUsage) guestUsage.classList.toggle('hidden', signedIn) const emailEl = document.getElementById('auth-user-email') if (emailEl) emailEl.textContent = authState.email || '' + const accessEmailEl = document.getElementById('access-signed-email') + if (accessEmailEl) accessEmailEl.textContent = authState.email || '' updateGuestUsageCounter() updateSubscriptionUI() } @@ -4536,8 +6413,9 @@ function hidePaywallExhausted() { } function showPaywallExhausted(count, limit, options = {}) { + setGenerationStageVisible(true); const walkthroughModal = document.getElementById('walkthrough-modal') - if (walkthroughModal) walkthroughModal.classList.remove('open') + if (walkthroughModal) closeModal(walkthroughModal, { restoreFocus: false }) const readyState = document.getElementById('ready-state') if (readyState) readyState.classList.add('hidden') @@ -4638,38 +6516,216 @@ function updateModelSelectorGating() { updateModelInfo(select.value) } -function updateUsageDisplay() { - const el = document.getElementById('usage-counter') - if (!el) return +/** + * Single source of truth for the monthly-usage presentation shown in the + * topbar allowance and the usage/billing dialog. Reads the metered count, the + * resolved tier limit and the auth/subscription state, then writes every usage + * surface (topbar, dialog, account row, guest counter) consistently. Remaining + * runs are clamped to zero and an unresolved plan never surfaces a fake balance. + */ +function renderUsageSurfaces() { + const signedIn = authState.isVerified && !!authState.email; + const loading = signedIn && isSubscriptionLoading(); + const resolved = !signedIn || isSubscriptionResolved(); + + const usage = getUsage(); + const count = resolved ? usage.count : 0; + const limit = resolved ? getRunLimit() : 0; + const remaining = Math.max(0, limit - count); + const usedLimitText = `${count} / ${limit} runs this month`; + const labels = planLabels; + const tier = resolved ? (subscriptionState.tier || "free") : null; + + const topbarCredits = document.getElementById("topbar-credits-count"); + if (topbarCredits) { + if (loading) topbarCredits.textContent = "…"; + else if (!resolved) topbarCredits.textContent = "—"; + else topbarCredits.textContent = String(remaining); + } + + const balance = document.getElementById("credits-balance"); + if (balance) { + if (loading) balance.textContent = "Checking plan…"; + else if (!resolved) balance.textContent = "Plan check failed"; + else balance.textContent = usedLimitText; + } + + const dialogTier = document.getElementById("usage-dialog-tier"); + if (dialogTier) { + if (loading) dialogTier.textContent = "Checking…"; + else if (!resolved) dialogTier.textContent = "Unavailable"; + else dialogTier.textContent = labels[tier] || "Free"; + } + + const dialogStatus = document.getElementById("usage-dialog-status"); + if (dialogStatus) { + if (loading) dialogStatus.textContent = "Verifying your subscription…"; + else if (!resolved) dialogStatus.textContent = "Could not verify your subscription. Try again or sign out."; + else dialogStatus.textContent = "Runs reset at the start of each month."; + } + + const counter = document.getElementById("usage-counter"); + if (counter) { + if (loading && signedIn) { + counter.textContent = "Checking plan…"; + counter.className = "text-xs text-gray-500"; + } else if (!resolved && signedIn) { + counter.textContent = "Plan check failed"; + counter.className = "text-xs text-red-600 font-medium"; + } else { + counter.textContent = usedLimitText; + const pct = limit > 0 ? count / limit : 0; + counter.className = pct >= 1 + ? "text-xs text-red-600 font-medium" + : pct >= 0.8 + ? "text-xs text-yellow-600 font-medium" + : "text-xs text-gray-500"; + } + } - if (authState.isVerified && isSubscriptionLoading()) { - el.textContent = 'Checking plan…' - el.className = 'text-xs text-gray-500' - updateGuestUsageCounter() - hidePaywallExhausted() - return + if (!signedIn) { + const guestEl = document.getElementById("guest-usage-text"); + if (guestEl) { + const g = getUsageData(); + const gCount = g.month === getCurrentYearMonth() ? (g.count ?? 0) : 0; + guestEl.textContent = `${gCount} / ${TIER_LIMITS.free} generations used`; + } } - if (authState.isVerified && !isSubscriptionResolved()) { - el.textContent = 'Plan check failed' - el.className = 'text-xs text-red-600 font-medium' - updateGuestUsageCounter() + renderAccountOverview(); +} + +/** + * Renders the account overview: identity, plan, usage meter and available + * period information. This is the single presentation adapter for the account + * view and reads the same session, subscription and metered state as the + * topbar (renderUsageSurfaces), so sign-in/out and a usage refresh move all + * surfaces together. + * + * Honesty contract, enforced by render: every number/date/identity traces to a + * real field or a documented derivation (email-derived display name/avatar + * initial, metered count, tier limit). A renewal/reset date is shown ONLY when + * subscriptionState.periodEnd is a real value — never fabricated — and an + * unresolved plan surfaces checking/unavailable copy, never a stale balance. + */ +function renderAccountOverview() { + const signedIn = authState.isVerified && !!authState.email; + if (!signedIn) { + // Signed-out/guest state has its own container; leave the signed-in + // overview untouched in the hidden subtree so no previous identity lingers + // anywhere a later sign-in could briefly flash it. + return; + } + + const loading = isSubscriptionLoading(); + const resolved = isSubscriptionResolved(); + const usage = getUsage(); + const count = resolved ? usage.count : 0; + const limit = resolved ? getRunLimit() : 0; + const remaining = Math.max(0, limit - count); + const tier = resolved ? (subscriptionState.tier || "free") : null; + const tierLabel = { free: "Free", professional: "Pro", power: "Power" }[tier] || "Free"; + + // --- identity: real email, documented derivations only, no member-since --- + const email = authState.email || ""; + const localPart = email.split("@")[0] || email; + const avatar = document.getElementById("acct-avatar"); + if (avatar) avatar.textContent = (email[0] || "?").toUpperCase(); + const name = document.getElementById("acct-name"); + if (name) name.textContent = localPart || "—"; + + // --- plan --- + const planTier = document.getElementById("acct-plan-tier"); + const planPrice = document.getElementById("acct-plan-price"); + const planNote = document.getElementById("acct-plan-note"); + const renewal = document.getElementById("acct-renewal"); + if (planTier) { + planTier.textContent = loading ? "Checking…" : resolved ? tierLabel : "Plan unavailable"; + } + if (planPrice) { + if (loading) planPrice.textContent = "—"; + else if (!resolved) planPrice.textContent = "—"; + else if (tier === "free") planPrice.textContent = "$0 / month"; + else { + const money = formatPrice(BASE_PRICES_AUD[tier] ?? 0, detectUserCurrency()); + planPrice.textContent = `${money} / month`; + } + } + if (planNote) { + if (loading) planNote.textContent = "Verifying your subscription…"; + else if (!resolved) planNote.textContent = "Could not verify your subscription. Check billing or sign out."; + else if (tier === "free") planNote.textContent = "No subscription. Upgrade for more generations."; + else planNote.textContent = "billed monthly through Stripe"; + } + if (renewal) { + const periodEndMs = Date.parse(subscriptionState.periodEnd || ""); + const hasRealPeriodEnd = resolved && tier !== "free" && !!subscriptionState.periodEnd && !Number.isNaN(periodEndMs); + if (loading) renewal.textContent = ""; + else if (!resolved) renewal.textContent = ""; + else if (tier === "free") renewal.textContent = ""; + else if (hasRealPeriodEnd) { + const date = new Date(periodEndMs).toLocaleDateString(undefined, { year: "numeric", month: "long", day: "numeric" }); + renewal.textContent = `Renews ${date} · reset at the start of each month.`; + } else { + // No fabricated date: if the plan has no real period end we say so plainly. + renewal.textContent = "Renewal date is not available for this period."; + } + } + + // --- usage: generations left + meter --- + const leftCount = document.getElementById("acct-left-count"); + const leftLimit = document.getElementById("acct-left-limit"); + const resetNote = document.getElementById("acct-reset-note"); + if (leftCount) leftCount.textContent = loading ? "…" : !resolved ? "—" : String(remaining); + if (leftLimit) leftLimit.textContent = loading ? "…" : !resolved ? "—" : String(limit); + if (resetNote) { + if (loading) resetNote.textContent = "Checking plan…"; + else if (!resolved) resetNote.textContent = "Plan check failed. Refresh or manage billing."; + else resetNote.textContent = "Runs reset at the start of each month."; + } + + const usedCount = document.getElementById("acct-used-count"); + const meterFill = document.getElementById("acct-meter-fill"); + const meterMeta = document.getElementById("acct-meter-meta"); + const meterTrack = document.getElementById("acct-meter-track"); + if (usedCount) usedCount.textContent = loading ? "…" : !resolved ? "—" : String(count); + if (meterFill) { + const pct = resolved && limit > 0 ? Math.min(100, Math.round((count / limit) * 100)) : 0; + meterFill.style.width = `${pct}%`; + } + if (meterMeta) { + if (loading) meterMeta.textContent = "Checking…"; + else if (!resolved) meterMeta.textContent = "Plan check failed"; + else if (limit === 0) meterMeta.textContent = `${count} of ${limit}`; + else { + const pct = Math.round((count / limit) * 100); + meterMeta.textContent = `${count} of ${limit} · ${pct}%`; + } + } + if (meterTrack) { + if (loading) meterTrack.setAttribute("aria-label", "Checking usage…"); + else if (!resolved) meterTrack.setAttribute("aria-label", "Usage unavailable"); + else meterTrack.setAttribute("aria-label", `${count} of ${limit} generations used`); + } + + // --- FlutterFlow connection (real response-driven state) --- + renderApiKeyConnection(); +} + +function updateUsageDisplay() { + renderUsageSurfaces() + + if (authState.isVerified && (isSubscriptionLoading() || !isSubscriptionResolved())) { hidePaywallExhausted() return } const { count } = getUsage() const limit = getRunLimit() - el.textContent = `${count} / ${limit} runs this month` - const pct = limit > 0 ? count / limit : 0 - el.className = pct >= 1 - ? 'text-xs text-red-600 font-medium' - : pct >= 0.8 - ? 'text-xs text-yellow-600 font-medium' - : 'text-xs text-gray-500' - updateGuestUsageCounter() - - if (count >= limit && !pipelineState.isRunning) { + // Auto-surfacing the paywall swaps the stage and closes the walkthrough, so + // defer it while a dialog is open; the next usage update or run attempt + // still gates on the limit. + if (count >= limit && !pipelineState.isRunning && !hasActiveModal()) { showPaywallExhausted(count, limit) } else { hidePaywallExhausted() @@ -4677,12 +6733,7 @@ function updateUsageDisplay() { } function updateGuestUsageCounter() { - const el = document.getElementById('guest-usage-text') - if (!el) return - const usage = getUsageData() - const count = usage.month === getCurrentYearMonth() ? (usage.count ?? 0) : 0 - const limit = TIER_LIMITS.free - el.textContent = `${count} / ${limit} generations used` + renderUsageSurfaces() } // --- STRIPE FUNCTIONS --- @@ -4696,6 +6747,7 @@ async function fetchSubscription(options = {}) { } subscriptionState = { ...subscriptionState, isLoading: true, error: null } + const requestSessionToken = authState.sessionToken const cached = localStorage.getItem(SUBSCRIPTION_CACHE_KEY) if (!force && cached) { @@ -4720,6 +6772,13 @@ async function fetchSubscription(options = {}) { const data = await res.json() + // The session ended or rotated while the request was in flight: this + // response belongs to the old account and must not overwrite the plan + // state sign-out already reset. + if (!authState.isVerified || authState.sessionToken !== requestSessionToken) { + return + } + if (data.error) { const isAuthError = ['unauthorized', 'invalid session', 'expired session'].some(message => String(data.error).toLowerCase().includes(message)) if (isAuthError) { @@ -4739,6 +6798,9 @@ async function fetchSubscription(options = {}) { ts: Date.now() })) } catch (err) { + if (!authState.isVerified || authState.sessionToken !== requestSessionToken) { + return + } console.error('fetchSubscription failed:', err) subscriptionState = { ...subscriptionState, isLoading: false, isResolved: false, error: err.message } } @@ -4784,13 +6846,17 @@ async function startCheckout(tierId) { } } -async function openCustomerPortal() { +async function openCustomerPortal(trigger) { if (!authState.isVerified || !authState.sessionToken) { openSignInModal() return } - const btn = document.getElementById('manage-billing-btn') + // Every Manage Subscription / Manage Billing trigger shares this single + // portal request and its loading/error state, so only one fresh session URL + // is ever requested. + const btn = trigger || document.getElementById('manage-billing-btn') + const prevText = btn ? btn.textContent : '' if (btn) { btn.disabled = true; btn.textContent = 'Loading…' } try { @@ -4806,15 +6872,31 @@ async function openCustomerPortal() { window.location.href = url } catch (err) { console.error('openCustomerPortal failed:', err) - if (btn) { btn.disabled = false; btn.textContent = 'Manage billing' } + if (btn) { btn.disabled = false; btn.textContent = prevText } showToast('Could not open billing portal. Please try again.', 'error') } } +// Every in-flight BuildShip request registers its controller here so a run +// the user abandoned can cancel its request instead of only discarding the +// response when it lands. +const activeBuildShipControllers = new Set(); + +/** Cancel every in-flight BuildShip request; the run they served is stale. */ +function abortPipelineRequests() { + activeBuildShipControllers.forEach((controller) => controller.abort()); + activeBuildShipControllers.clear(); +} + async function callBuildShip(step, model, prompt, context = {}, images = []) { const BUILDSHIP_TIMEOUT_MS = 120000 const controller = new AbortController() - const timeoutId = setTimeout(() => controller.abort(), BUILDSHIP_TIMEOUT_MS) + activeBuildShipControllers.add(controller) + let timedOut = false + const timeoutId = setTimeout(() => { + timedOut = true + controller.abort() + }, BUILDSHIP_TIMEOUT_MS) try { const res = await fetch(PIPELINE_ENDPOINT, { @@ -4852,6 +6934,9 @@ async function callBuildShip(step, model, prompt, context = {}, images = []) { } const usageError = new Error(data.message || 'Monthly usage limit reached. Upgrade to continue.') usageError.isUsageLimit = true + // The step is the authoritative signal the pipeline view uses to mark + // which stage stopped; a quota message carries no step prefix of its own. + usageError.pipelineStep = step throw usageError } @@ -4895,7 +6980,14 @@ async function callBuildShip(step, model, prompt, context = {}, images = []) { return output } catch (error) { if (error.name === 'AbortError') { - throw new Error(`BuildShip ${step} timed out after ${BUILDSHIP_TIMEOUT_MS / 1000}s`) + if (timedOut) { + throw new Error(`BuildShip ${step} timed out after ${BUILDSHIP_TIMEOUT_MS / 1000}s`) + } + // The run that owned this request was abandoned, so the cancellation + // must never read as a service outcome. + const cancelled = new Error(`BuildShip ${step} request cancelled`) + cancelled.isPipelineCancel = true + throw cancelled } if (error instanceof TypeError) { throw new Error(`BuildShip unreachable: ${error.message}`) @@ -4903,20 +6995,47 @@ async function callBuildShip(step, model, prompt, context = {}, images = []) { throw error } finally { clearTimeout(timeoutId) + activeBuildShipControllers.delete(controller) } } +// Set when the user returns from Stripe with `?checkout=success`. The paid +// entitlement is never granted by the return param itself — it is only ever +// set by the subscription reconciliation below. This flag defers the "plan +// active" confirmation until after reconcileSubscription has confirmed a paid +// tier, so a return that has NOT reconciled (blocked, webhook lag, or a +// cancelled/failed session) can never be reported as subscribed (STU-382 +// criterion 3). +let checkoutConfirmPending = false + function handleCheckoutRedirect() { const params = new URLSearchParams(window.location.search) const checkout = params.get('checkout') if (checkout === 'success') { - window.history.replaceState({}, '', window.location.pathname) + window.history.replaceState({}, '', window.location.pathname + window.location.hash) clearSubscriptionCache() - showToast('Subscription active! Welcome aboard.', 'success') + checkoutConfirmPending = true } else if (checkout === 'cancel') { - window.history.replaceState({}, '', window.location.pathname) + window.history.replaceState({}, '', window.location.pathname + window.location.hash) showToast('Checkout cancelled.', 'info') } + return checkout +} + +// Called once the subscription has been reconciled after a checkout return. +// Only reports a live plan when the contract is actually paid; otherwise it +// says the subscription is still being confirmed so the UI never claims a +// subscribed state it cannot back up. +function confirmCheckoutAfterReconcile() { + if (!checkoutConfirmPending) return + checkoutConfirmPending = false + const isPaid = subscriptionState.tier !== 'free' + showToast( + isPaid + ? 'Subscription active! Your plan is live.' + : 'Checkout complete — confirming your subscription. Check Manage billing if it does not update.', + isPaid ? 'success' : 'info', + ) } // --- SUBSCRIPTION UI --- @@ -4929,7 +7048,7 @@ function updateSubscriptionUI() { const badge = document.getElementById('subscription-tier-badge') if (badge) { - const labels = { free: 'Free', professional: 'Professional', power: 'Power Developer' } + const labels = planLabels const colors = { free: 'bg-gray-100 text-gray-600', professional: 'bg-indigo-100 text-indigo-700', @@ -4950,6 +7069,7 @@ function updateSubscriptionUI() { updateModelSelectorGating() updatePromptImageAvailability() updateUsageDisplay() + updateShellUI() } function updatePricingModalState(tier) { @@ -4975,32 +7095,61 @@ function updatePricingModalState(tier) { if (freeCurrent) freeCurrent.classList.toggle('hidden', tier !== 'free') } +// Render every plan card's feature list from the single PLAN_FEATURES source, +// so the plans page and the pricing modal share one feature set and can never +// drift (and a test can never assert a constant the UI does not render). Each +// .pm-card carries data-tier; its
    is filled from +// PLAN_FEATURES[tier]. Idempotent: safe to run more than once. +function renderPlanFeatureLists() { + document.querySelectorAll('.pm-card[data-tier]').forEach((card) => { + const tier = card.dataset.tier + const rows = planFeatures[tier] + if (!rows) return + const ul = card.querySelector('ul.pm-features') + if (!ul) return + ul.innerHTML = '' + for (const row of rows) { + const li = document.createElement('li') + li.textContent = row + ul.appendChild(li) + } + }) +} + function updatePricingDisplay() { const currency = detectUserCurrency() const proEl = document.getElementById('pro-price') const powerEl = document.getElementById('power-price') + const plansProEl = document.getElementById('plans-pro-price') + const plansPowerEl = document.getElementById('plans-power-price') const proNote = document.getElementById('pro-price-note') const powerNote = document.getElementById('power-price-note') + const plansProNote = document.getElementById('plans-pro-price-note') + const plansPowerNote = document.getElementById('plans-power-price-note') if (proEl) proEl.textContent = formatPrice(BASE_PRICES_AUD.professional, currency) if (powerEl) powerEl.textContent = formatPrice(BASE_PRICES_AUD.power, currency) + if (plansProEl) plansProEl.textContent = formatPrice(BASE_PRICES_AUD.professional, currency) + if (plansPowerEl) plansPowerEl.textContent = formatPrice(BASE_PRICES_AUD.power, currency) const note = 'billed monthly' if (proNote) proNote.textContent = note if (powerNote) powerNote.textContent = note + if (plansProNote) plansProNote.textContent = note + if (plansPowerNote) plansPowerNote.textContent = note } function openPricingModal() { updatePricingDisplay() const modal = document.getElementById('pricing-modal') - if (modal) modal.classList.add('open') + if (modal) openModal(modal) fetchAudExchangeRates().then(() => updatePricingDisplay()) } function closePricingModal(event) { if (event && event.target !== event.currentTarget) return const modal = document.getElementById('pricing-modal') - if (modal) modal.classList.remove('open') + if (modal) closeModal(modal) } function showToast(message, type = 'info') { @@ -5018,6 +7167,12 @@ function showToast(message, type = 'info') { // --- INITIALIZATION --- document.addEventListener("DOMContentLoaded", async () => { + initializeModalShells(); + + // The holding window's regions display in a different order per breakpoint; + // reorder them in the DOM so focus never travels against the screen. + initPipelinePanelOrder(); + // Initialize highlight.js hljs.configure({ tabReplace: " ", @@ -5027,11 +7182,38 @@ document.addEventListener("DOMContentLoaded", async () => { // Initialize welcome video initializeWelcomeVideo(); - await initializeAuth(); - handleCheckoutRedirect(); - await fetchSubscription(); + // Decorative hero mark field (WebGL with 2D fallback); no dependency on generation state. + window.__heroField = initHeroMarkField(); + + // Decorative pipeline logo loop (120 s authored mark motion in the pipeline + // arena). Self-managed: pauses when hidden/offscreen/reduced-motion and is + // cleanup-safe on view transition; completion never depends on it. + window.__pipelineLogo = createPipelineLogoLoop(); + + // Bind the composer before the first awaited startup call so the send + // button's listener exists while auth/subscription requests are still in + // flight; runThinkingPipeline waits on sessionReadiness before checking + // entitlements. + initExactShell(); + composerControls = initComposer({ onSubmit: runThinkingPipeline }); + + // Startup auth + subscription share one promise: the pipeline awaits it so + // an early submission sees the resolved session instead of free defaults. + // It always resolves — a failed init must not hang a waiting run. + sessionReadiness = (async () => { + try { + await initializeAuth(); + handleCheckoutRedirect(); + await fetchSubscription(); + } catch (err) { + console.warn("Startup auth/subscription initialization failed:", err); + } + })(); + await sessionReadiness; + confirmCheckoutAfterReconcile(); updateSubscriptionUI(); updatePricingDisplay(); + renderPlanFeatureLists(); // Initialize API keys and check connection await checkConnection(); @@ -5065,7 +7247,7 @@ document.addEventListener("DOMContentLoaded", async () => { pipelineInput.addEventListener("blur", () => { const walkthroughModal = document.getElementById("walkthrough-modal"); if (walkthroughStep === 2 && walkthroughModal) { - walkthroughModal.classList.add("open"); + openModal(walkthroughModal); } }); @@ -5074,7 +7256,7 @@ document.addEventListener("DOMContentLoaded", async () => { const walkthroughModal = document.getElementById("walkthrough-modal"); if (walkthroughStep === 2 && walkthroughModal) { setTimeout(() => { - walkthroughModal.classList.add("open"); + openModal(walkthroughModal); }, 100); } } @@ -5090,15 +7272,24 @@ document.addEventListener("DOMContentLoaded", async () => { state === CommitState.VALIDATING || state === CommitState.PUSHING ) { + // A hide still pending from the previous commit's terminal state must + // not close the overlay this commit just opened. + cancelCommitProgressHide(); // Only open the overlay for flows that didn't open it themselves; // re-opening mid-commit would reset the progress back to step one. if (!commitProgress.phaseId) showCommitProgress(); updateProgressFromState(state); } else if (state === CommitState.SUCCESS || state === CommitState.ERROR) { updateProgressFromState(state); - setTimeout(hideCommitProgress, 1000); + if (commitProgressHideTimer) clearTimeout(commitProgressHideTimer); + commitProgressHideTimer = setTimeout(() => { + commitProgressHideTimer = null; + hideCommitProgress(); + }, 1000); } }); + + restoreViewFromHash(); }); // --- WELCOME VIDEO FUNCTIONS --- @@ -5151,7 +7342,13 @@ async function populateConfirmProjectSelect() { // closed and reopened while this is in flight, its token falls behind and it // bails instead of resetting the selection with stale data. const token = ++confirmProjectToken; + const order = ++ffRequestOrderSeq; const isCurrent = () => token === confirmProjectToken; + const generation = ffEndpointGeneration; + + // The options are replaced by the loading placeholder below, so the previous + // list is no longer on screen and nothing may be read from it. + confirmProjectListIdentity = null; const apiKey = await getApiKey("flutterflow"); const storedId = await getApiKey("flutterflow_project_id"); @@ -5167,9 +7364,31 @@ async function populateConfirmProjectSelect() { select.disabled = false; select.innerHTML = ''; try { - const client = new FlutterFlowApiClient(apiKey, ""); + const client = new FlutterFlowApiClient( + apiKey, + "", + "main", + getFlutterFlowEndpoint(), + ); const projects = await client.listProjects(); if (!isCurrent()) return; + // The response describes the endpoint + key it was issued under. If either + // moved while the request was in flight, its options belong to a different + // identity than the deploy would use — repopulate for the current one + // rather than filling the modal with stale, undeployable projects. + if (generation !== ffEndpointGeneration || apiKey !== flutterflowApiKey) { + return populateConfirmProjectSelect(); + } + + // A completed response for the current key is authoritative: it re-confirms + // the stored selection when it lists it and strips its confirmation when it + // does not, so the stored fallback can never target a project this key's + // list did not offer. The confirmation write is shared connection state, + // so it applies only while no newer request has already applied an outcome. + if (order > ffAppliedConfirmationOrder) { + ffAppliedConfirmationOrder = order; + reconcileStoredProjectSelection(projects, apiKey, generation); + } if (!projects || projects.length === 0) { select.innerHTML = ''; @@ -5185,9 +7404,16 @@ async function populateConfirmProjectSelect() { select.appendChild(option); }); + // Only now do the options belong to this key + endpoint generation and may + // a value read from them be used as the deploy target. + confirmProjectListIdentity = { key: apiKey, generation }; + if (storedId) select.value = storedId; } catch (error) { if (!isCurrent()) return; + if (generation !== ffEndpointGeneration || apiKey !== flutterflowApiKey) { + return populateConfirmProjectSelect(); + } console.error("Failed to load projects for deploy:", error); select.innerHTML = ''; @@ -5195,13 +7421,26 @@ async function populateConfirmProjectSelect() { } /** - * Reads the project chosen in the confirm modal, falling back to the stored - * API Keys default when none was selected. + * Reads the project chosen in the confirm modal. A target is only returned + * while the dropdown still holds a list a completed fetch produced for the + * current key + endpoint: a value that survives a key or endpoint change is not + * a confirmed target. Returns null when no confirmed choice exists, so the + * caller falls back to the stored selection (itself identity-gated) or fails + * rather than deploying to an unconfirmed project. */ function readCommitTargetProjectId() { const select = document.getElementById("confirm-project-select"); const chosen = select?.value?.trim(); - return chosen || null; + if (!chosen) return null; + const identity = confirmProjectListIdentity; + if ( + !identity || + identity.key !== flutterflowApiKey || + identity.generation !== ffEndpointGeneration + ) { + return null; + } + return chosen; } /** @@ -5261,7 +7500,7 @@ function openCommitConfirmModal(codeInfo, checks, deps, bundlePlan = null) { const modal = document.getElementById("commit-confirm-modal"); if (modal) { - modal.classList.add("open"); + openModal(modal); } } @@ -5273,7 +7512,7 @@ function closeCommitConfirmModal(event) { if (event && event.target !== event.currentTarget) return; const modal = document.getElementById("commit-confirm-modal"); if (modal) { - modal.classList.remove("open"); + closeModal(modal); } pendingCommitData = null; } @@ -5286,7 +7525,7 @@ function closeCommitSuccessModal(event) { if (event && event.target !== event.currentTarget) return; const modal = document.getElementById("commit-success-modal"); if (modal) { - modal.classList.remove("open"); + closeModal(modal); } // Reset success fields @@ -5347,14 +7586,25 @@ function showCommitSuccessModal(result) { const warningsSection = document.getElementById("success-warnings-section"); const warningsList = document.getElementById("success-warnings-list"); // A class that could not be compiled before the push is reported here rather - // than left implicit, so "deployed" never reads as "checked". + // than left implicit, so "deployed" never reads as "checked". The + // approximate list rides alongside: empty under the current planner, which + // skips rather than compiles on a reduced graph, but rendered whenever a + // result carries it so the check is never mistaken for a full-graph one. const unverified = result.unverified || []; + const approximate = result.approximate || []; const fileWarnings = result.warnings || []; - if ((fileWarnings.length > 0 || unverified.length > 0) && warningsSection && warningsList) { + if ( + (fileWarnings.length > 0 || unverified.length > 0 || approximate.length > 0) && + warningsSection && + warningsList + ) { warningsList.innerHTML = [ ...unverified.map((reason) => `
  • Not verified before deploying: ${escapeHtml(String(reason))}
  • ` ), + ...approximate.map((notice) => + `
  • Verified approximately: ${escapeHtml(String(notice))}
  • ` + ), ...fileWarnings.map(([file, errs]) => `
  • ${escapeHtml(file)}: ${escapeHtml(String(errs))}
  • ` ), @@ -5363,12 +7613,156 @@ function showCommitSuccessModal(result) { } const modal = document.getElementById("commit-success-modal"); - if (modal) modal.classList.add("open"); + if (modal) openModal(modal); } +// #step3-output lives inside permanently-hidden legacy containers, so writing +// the failure only there shows the user nothing — the overlay closes and no +// terminal appears. A definitive refusal therefore also populates the shared +// terminal modal; the hidden render stays for the regenerate wiring and any +// legacy surface still reading it. function showCommitFailureModal(result) { hideCommitProgress(); showCommitError(result); + // Only a remote refusal is FlutterFlow's answer — a local failure (missing + // credentials, validation) never reached the server, so it must not be + // labelled a refusal. Either way a FAILED outcome is provably pre-write: + // nothing was applied and retrying after a fix is safe. + const remote = result.remoteRefusal === true; + populateCommitTerminalModal(result, { + heading: "Deploy failed", + title: remote + ? "FlutterFlow refused this deploy — nothing was confirmed written." + : "The deploy failed before FlutterFlow confirmed anything.", + guidance: remote + ? "Review the error and any per-file outcomes above, fix them in your code or in FlutterFlow, then deploy again. " + + "A refusal is definitive: no part of this deploy was applied, so retrying is safe once the problem is fixed." + : "Review the error above, fix it, then deploy again. The deploy stopped before a write was confirmed, so nothing was applied.", + }); +} + +/** + * Populates the shared terminal modal for every outcome that is not a clean + * success: PARTIAL (some custom classes were written, the remaining sync + * failed), UNCONFIRMED (the remote outcome is unknown because the client + * stopped waiting or the stream dropped), and FAILED (a definitive refusal — + * nothing confirmed written). It always shows the same target identity the + * user confirmed, the per-file outcomes when the runner/push reported them, + * and reconciliation guidance that never hides the manual FlutterFlow step of + * checking the project. + */ +function populateCommitTerminalModal(result, { heading, title, guidance }) { + const identity = result.targetIdentity || {}; + const modal = document.getElementById("commit-terminal-modal"); + if (!modal) return false; + + const set = (id, val) => { + const el = document.getElementById(id); + if (el) el.textContent = val || ""; + }; + + set("terminal-heading", heading); + set("terminal-title", title); + set("terminal-message", result.error || result.message || ""); + + const idList = document.getElementById("terminal-identity-list"); + if (idList) { + const rows = [ + ["Project", identity.projectId || result.metadata?.projectId], + ["Endpoint", identity.endpoint], + ["File", identity.fileName || result.metadata?.fileName], + ["Artifact", identity.artifactType || result.metadata?.artifactType], + ]; + idList.innerHTML = rows + .map( + ([label, value]) => + `
    ${escapeHtml( + label, + )}:${escapeHtml( + String(value ?? "—"), + )}
    `, + ) + .join(""); + } + + const fileList = document.getElementById("terminal-file-outcomes"); + let errorMap = result.errorMap; + if (errorMap && !(errorMap instanceof Map)) { + errorMap = new Map(Object.entries(errorMap)); + } + const fileOutcomeItems = fileList?.querySelector("ul"); + if (fileList && fileOutcomeItems && errorMap && errorMap.size > 0) { + fileOutcomeItems.innerHTML = [...errorMap.entries()] + .map( + ([file, info]) => + `
  • ${escapeHtml( + file, + )}: ${escapeHtml(formatFlutterFlowFileError(info))}
  • `, + ) + .join(""); + fileList.classList.remove("hidden"); + } else if (fileList) { + if (fileOutcomeItems) fileOutcomeItems.innerHTML = ""; + fileList.classList.add("hidden"); + } + + const guidanceEl = document.getElementById("terminal-guidance"); + if (guidanceEl) guidanceEl.innerHTML = guidance; + + const ffLink = document.getElementById("terminal-open-ff-link"); + const projectId = identity.projectId || result.metadata?.projectId; + if (ffLink) { + ffLink.href = projectId + ? `https://app.flutterflow.io/project/${projectId}` + : "https://app.flutterflow.io/"; + } + + openModal(modal); + return true; +} + +/** + * Terminal outcome: some custom classes were written to FlutterFlow, but the + * remaining sync was rejected. "Committed" would lie — part of the deploy did + * land, but part failed. + */ +function showCommitPartialModal(result) { + populateCommitTerminalModal(result, { + heading: "Deploy partially applied", + title: + "Some custom classes reached FlutterFlow, but the deploy did not fully complete.", + guidance: + "The custom classes the runner confirmed are already in your project and are not lost. " + + "Review the per-file errors above, fix them in FlutterFlow or regenerate, then deploy again. " + + "Open the project to see exactly what landed.", + }); +} + +/** + * Terminal outcome: the client stopped waiting (bounded UI timeout) or the + * connection dropped before the runner reported a result. The remote outcome + * is unknown — this is never reported as committed or as failed, and the + * in-flight write is never cancelled. + */ +function showCommitUnconfirmedModal(result) { + populateCommitTerminalModal(result, { + heading: "Deploy outcome not yet known", + title: + "This browser stopped waiting before the FlutterFlow server reported a result.", + guidance: + "The deploy may still be finishing on the server — it was not cancelled. " + + "Open your FlutterFlow project and confirm whether the class landed before retrying, so you do not " + + "push a duplicate or build on top of an unknown state.", + }); +} + +/** + * Closes the shared terminal modal (partial / unconfirmed outcomes). + * @param {Event} [event] - Optional click event + */ +function closeCommitTerminalModal(event) { + if (event && event.target !== event.currentTarget) return; + closeModal(document.getElementById("commit-terminal-modal")); } /** @@ -5423,6 +7817,15 @@ const PROVISION_SUBSTATUS = [ { after: 100, text: "Still working — this can take a couple of minutes..." }, ]; +// The delayed hide a terminal commit state schedules. A commit that starts +// before it fires still needs the overlay, so opening cancels it. +let commitProgressHideTimer = null; + +function cancelCommitProgressHide() { + if (commitProgressHideTimer) clearTimeout(commitProgressHideTimer); + commitProgressHideTimer = null; +} + const commitProgress = { sequence: [], phaseId: null, @@ -5438,12 +7841,16 @@ const commitProgress = { * provisioning step, which is only run for CodeFile artifacts. */ start({ withProvisioning = false } = {}) { + cancelCommitProgressHide(); this.sequence = ["prepare", "validate", "project"]; if (withProvisioning) this.sequence.push("provision"); this.sequence.push("package", "push", "done"); const overlay = document.getElementById("commit-progress-overlay"); - if (overlay) overlay.classList.add("open"); + if (overlay) { + setModalPending(overlay, true, "Deploying to FlutterFlow"); + openModal(overlay); + } this.set("prepare"); }, @@ -5519,7 +7926,10 @@ const commitProgress = { this.timer = null; this.phaseId = null; const overlay = document.getElementById("commit-progress-overlay"); - if (overlay) overlay.classList.remove("open"); + if (overlay) { + setModalPending(overlay, false); + closeModal(overlay, { force: true, restoreFocus: false }); + } }, }; @@ -5614,19 +8024,68 @@ function commitNeedsProvisioning(commitData) { /** * Confirms the commit after modal review. */ +// A deploy is in flight. The confirm action and the deploy toggle are disabled +// for its whole run, so a user clicking twice cannot start a second push and a +// second modal cannot be opened over a live one. +let deployInFlight = false; + +function setDeployBusy(busy) { + deployInFlight = busy; + // The modal's confirm button and every deploy trigger are disabled for the + // whole run so a second click cannot start an overlapping push. + const confirm = document.querySelector( + "#commit-confirm-modal button[data-deploy-confirm]", + ); + if (confirm) confirm.disabled = busy; + const triggers = [ + ...document.querySelectorAll("[data-deploy-start]"), + ...document.querySelectorAll("#btn-deploy-to-ff"), + ]; + triggers.forEach((el) => { + el.disabled = busy; + }); +} + +/** + * Dispatches a deploy result to the single truthful terminal presentation. + * Every outcome releases the UI busy state; only COMMITTED reaches the success + * modal. Partial and unconfirmed get their own truthful modals. + * @param {Object} result - A deploy result (see deployOutcome.classifyDeployResult) + */ +function renderCommitTerminal(result) { + hideCommitProgress(); + setDeployBusy(false); + const outcome = classifyDeployResult(result); + if (outcome === DeployOutcome.COMMITTED) { + showCommitSuccessModal(result); + } else if (outcome === DeployOutcome.PARTIAL) { + showCommitPartialModal(result); + } else if (outcome === DeployOutcome.UNCONFIRMED) { + showCommitUnconfirmedModal(result); + } else { + showCommitFailureModal(result); + } +} + async function confirmCommitToFlutterFlow() { if (!pendingCommitData) { console.error("No pending commit data"); return; } + if (deployInFlight) { + console.warn("Deploy already in flight; ignoring duplicate confirm."); + return; + } // Null the pending data before any await: it is only cleared at the end of // this function otherwise, so a second confirm click landing mid-commit - // would read the same data and push twice concurrently. + // would read the same data and push twice concurrently. The deploy-in-flight + // guard above makes this doubly safe. const commitData = pendingCommitData; pendingCommitData = null; commitTargetProjectId = readCommitTargetProjectId(); closeCommitConfirmModal(); + setDeployBusy(true); showCommitProgress({ withProvisioning: commitNeedsProvisioning(commitData) }); if (commitData.bundlePlan) { @@ -5638,14 +8097,7 @@ async function confirmCommitToFlutterFlow() { }); commitTargetProjectId = null; - hideCommitProgress(); - - if (result.success) { - showCommitSuccessModal(result); - } else { - showCommitFailureModal(result); - } - + renderCommitTerminal(result); return; } @@ -5664,13 +8116,7 @@ async function confirmCommitToFlutterFlow() { }); commitTargetProjectId = null; - hideCommitProgress(); - - if (result.success) { - showCommitSuccessModal(result); - } else { - showCommitFailureModal(result); - } + renderCommitTerminal(result); } // Global exports @@ -5682,12 +8128,16 @@ window.copyCode = copyCode; window.retryWithDifferentModel = retryWithDifferentModel; window.openApiKeysModal = openApiKeysModal; window.closeApiKeysModal = closeApiKeysModal; +window.openComposerSettings = openComposerSettings; +window.closeComposerSettings = closeComposerSettings; +window.walkthroughConnectAccount = walkthroughConnectAccount; window.closeWalkthroughModal = closeWalkthroughModal; window.openWalkthroughModal = openWalkthroughModal; window.advanceWalkthrough = advanceWalkthrough; window.commitToFlutterFlow = commitToFlutterFlow; function focusPromptInput() { + if (!pipelineState.isRunning) setGenerationStageVisible(false); const input = document.getElementById("pipeline-input"); if (input) { input.focus(); @@ -5695,9 +8145,8 @@ function focusPromptInput() { } function openModelSelector() { - const details = document.getElementById("advanced-settings"); - if (details) details.open = true; - const select = document.getElementById("code-generator-model"); + openComposerSettings(); + const select = document.getElementById("composer-settings-model"); if (select) { select.scrollIntoView({ behavior: "smooth", block: "center" }); select.focus(); @@ -5710,14 +8159,19 @@ window.openModelSelector = openModelSelector; window.handlePromptImageSelect = handlePromptImageSelect; window.removePromptImage = removePromptImage; window.saveApiKeys = saveApiKeys; +window.validateFlutterFlowConnection = validateFlutterFlowConnection; window.clearAllApiKeys = clearAllApiKeys; window.toggleKeyVisibility = toggleKeyVisibility; window.handleWelcomeVideoEnd = handleWelcomeVideoEnd; window.dismissWelcomeVideo = dismissWelcomeVideo; window.initiateCommitToFlutterFlow = initiateCommitToFlutterFlow; window.updateFlutterFlowCredentialStatus = updateFlutterFlowCredentialStatus; +window.openCommitConfirmModal = openCommitConfirmModal; window.closeCommitConfirmModal = closeCommitConfirmModal; window.closeCommitSuccessModal = closeCommitSuccessModal +window.closeCommitTerminalModal = closeCommitTerminalModal +window.showCommitPartialModal = showCommitPartialModal +window.showCommitUnconfirmedModal = showCommitUnconfirmedModal window.showCommitSuccessModal = showCommitSuccessModal window.showCommitFailureModal = showCommitFailureModal; window.toggleCodePreview = toggleCodePreview; @@ -5733,17 +8187,350 @@ window.openSignInModal = openSignInModal; window.closeSignInModal = closeSignInModal; window.handleMagicLinkRequest = handleMagicLinkRequest; window.handleSignOut = handleSignOut; +window.handleSendNewLink = handleSendNewLink; +window.handleClearCache = handleClearCache; +window.handleDeleteAccount = handleDeleteAccount; +window.closeDeleteUnavailableModal = closeDeleteUnavailableModal; window.startCheckout = startCheckout; window.openCustomerPortal = openCustomerPortal; window.openPricingModal = openPricingModal; window.closePricingModal = closePricingModal; // --- PIPELINE PROGRESS BAR & RESULTS VIEW --- -let pipelineProgressTimer = null; +// +// The three-stage view is bound to the real Architect -> Generator -> Review +// events, so nothing here invents an outcome: the track advances only when a +// stage actually reports, a stage that never ran is never drawn as completed, +// and a failure never falls through to a result. The run's one timer drives +// both the elapsed counter (real time) and the fill's in-slice easing (an +// estimate that never completes a stage ahead of its response). +let pipelineElapsedTimer = null; let pipelineStartTime = null; -const PIPELINE_ESTIMATED_DURATION = 120; // seconds +// Every view update carries the run it belongs to (pipelineState.runId), so a +// response that arrives after the user started a newer run is discarded +// instead of overwriting the newer run's state. +let pipelineStageStates = { 1: "pending", 2: "pending", 3: "pending" }; +let pipelineActiveStage = 1; +// When the active stage's slice of the track started easing; each stage +// entry re-arms it. +let pipelineStageStartedAt = null; +let pipelineSelectedStage = null; + +const PIPELINE_STAGE_LABELS = { + 1: "Prompt Architect", + 2: "Code Generator", + 3: "Code Review", +}; +const PIPELINE_STAGE_TITLES = { + 1: "Understanding your prompt", + 2: "Generating Dart code", + 3: "Running the code audit", +}; +const PIPELINE_STAGE_DONE_TITLES = { + 1: "Prompt understood", + 2: "Dart code generated", + 3: "Code audit complete", +}; + +function startPipelineRun() { + pipelineState.runId += 1; + return pipelineState.runId; +} -function showPipelineProgress() { +function isCurrentPipelineRun(runId) { + return runId === undefined || runId === pipelineState.runId; +} + +/** + * Abandon the current run: its captured id stops matching + * pipelineState.runId, so every isCurrentPipelineRun check discards whatever + * it still has in flight. Used when the user leaves the run mid-flight. + */ +function invalidatePipelineRun() { + pipelineState.runId += 1; +} + +function pipelineStageButton(step) { + return document.getElementById(`pdot-${step}`); +} + +/** + * Keep the holding window's DOM order equal to its displayed order so + * sequential focus never travels backwards across the panel. The two regions + * lead at different widths: the prompt recap is the desktop panel's left + * sidebar, while the workflow leads the stacked (<=920px) layout. Focus + * follows the DOM, so the recap is moved ahead of the view on wide screens + * and back after it on narrow ones; grid auto-placement then paints the + * regions in the same order it reads them. + */ +const pipelinePanelStacked = window.matchMedia("(max-width: 920px)"); + +function syncPipelinePanelOrder() { + const progress = document.getElementById("pipeline-progress"); + const view = progress?.querySelector(":scope > .pipeline-view"); + const recap = progress?.querySelector(":scope > .pipeline-prompt-recap"); + if (!view || !recap) return; + const wantRecapAfterView = pipelinePanelStacked.matches; + const recapAfterView = + (view.compareDocumentPosition(recap) & Node.DOCUMENT_POSITION_FOLLOWING) !== + 0; + if (recapAfterView === wantRecapAfterView) return; + // Reparenting blurs a focused descendant; carry it across the move. + const focused = document.activeElement; + progress.insertBefore(recap, wantRecapAfterView ? view.nextSibling : view); + if (focused instanceof HTMLElement && recap.contains(focused)) { + focused.focus({ preventScroll: true }); + } +} + +function initPipelinePanelOrder() { + syncPipelinePanelOrder(); + pipelinePanelStacked.addEventListener("change", syncPipelinePanelOrder); +} + +/** + * The supporting line under the stage title, taken verbatim from the canonical + * pipeline view's stage copy (custom-code-connect-hero.html stageCopy). + */ +function pipelineStageDescription(step) { + const descriptions = { + 1: "Turning your idea into a clear FlutterFlow specification.", + 2: "Building the Dart source, widget parameters and animation.", + 3: "Checking the generated code and preparing the file review.", + }; + return descriptions[step] || ""; +} + +/** + * Busy feedback on the control that started the run, and - just as important - + * a usable control again when the run terminates, however it terminated. + * The redesigned shell submits from the composer's send button; the legacy id + * is still honoured so nothing depends on which shell is mounted. + */ +function setRunPipelineButtonBusy(busy) { + const button = + document.getElementById("btn-run-pipeline") || + document.getElementById("hero-send"); + if (!button) return; + button.disabled = busy; + button.classList.toggle("is-busy", busy); + if (busy) button.setAttribute("aria-busy", "true"); + else button.removeAttribute("aria-busy"); +} + +function setPipelineRunState(state) { + const progress = document.getElementById("pipeline-progress"); + if (progress) progress.dataset.runState = state; +} + +/** + * Paint one stage's state. `pending` stages stay unreachable, and a stage that + * was never reached is never painted `done`. + * @param {number} step + * @param {"pending"|"active"|"done"|"failed"|"skipped"} state + */ +function setPipelineStageState(step, state) { + pipelineStageStates[step] = state; + const button = pipelineStageButton(step); + if (!button) return; + button.dataset.state = state; + // A stage that never ran is reported as such; there is nothing to select. + button.disabled = state === "pending" || state === "skipped"; + const stageName = PIPELINE_STAGE_LABELS[step]; + const stateLabels = { + pending: "not started", + active: "in progress", + done: "complete", + failed: "failed", + skipped: "not run", + }; + button.setAttribute( + "aria-label", + `Step ${step} of 3, ${stageName}: ${stateLabels[state] || state}`, + ); + if (state === "active") button.setAttribute("aria-current", "step"); + else button.removeAttribute("aria-current"); +} + +function completedPipelineStageCount() { + return [1, 2, 3].filter((step) => pipelineStageStates[step] === "done").length; +} + +function renderPipelineTrack() { + const fillEl = document.getElementById("pipeline-progress-fill"); + if (fillEl) { + if (pipelineStageStates[pipelineActiveStage] === "failed") { + // Pin the fill where it visibly is. Read the rendered width BEFORE + // disabling the transition — disabling it first snaps the element to + // its pending target — and freeze as a track percentage so a later + // resize keeps the same proportion instead of a stale pixel count. + const rendered = getComputedStyle(fillEl).width; + const track = fillEl.parentElement; + const trackPx = track ? track.getBoundingClientRect().width : 0; + const renderedPx = parseFloat(rendered) || 0; + fillEl.style.transition = "none"; + fillEl.style.width = trackPx ? `${(renderedPx / trackPx) * 100}%` : rendered; + } else { + fillEl.style.transition = ""; + fillEl.style.width = `${pipelineTrackPercent()}%`; + } + } + const countEl = document.getElementById("progress-stage-count"); + if (countEl) countEl.textContent = `Step ${pipelineActiveStage} of 3`; +} + +/** + * Each stage owns a third of the track. While a stage runs the fill eases + * asymptotically toward 95% of its slice, so a slow stage still looks alive + * without the bar ever claiming the stage finished ahead of its response. + * A finished stage sits on its own boundary — a stage-2 re-entry (refine, + * pasted errors) whose Review completes lands on 100%, not the count of + * stages that ran. + */ +function pipelineTrackPercent() { + const span = 100 / 3; + const state = pipelineStageStates[pipelineActiveStage]; + if (state === "active" && pipelineStageStartedAt !== null) { + const elapsed = (Date.now() - pipelineStageStartedAt) / 1000; + return ( + (pipelineActiveStage - 1) * span + + span * 0.95 * (1 - Math.exp(-elapsed / 12)) + ); + } + return state === "done" + ? (pipelineActiveStage / 3) * 100 + : (completedPipelineStageCount() / 3) * 100; +} + +/** + * Write the status line. It lives inside a polite live region, so writing it is + * also how the run is announced to assistive technology. + */ +function renderPipelineStatus(step, { done = false } = {}) { + const titleEl = document.getElementById("progress-title-text"); + const descriptionEl = document.getElementById("progress-description-text"); + const substepEl = document.getElementById("progress-substep-text"); + const state = pipelineStageStates[step]; + const finished = done || state === "done"; + if (titleEl) { + titleEl.textContent = finished + ? PIPELINE_STAGE_DONE_TITLES[step] + : PIPELINE_STAGE_TITLES[step]; + } + // The visible supporting line follows the mock; the step/stage/state line + // stays in the live region for assistive technology. + if (descriptionEl) descriptionEl.textContent = pipelineStageDescription(step); + if (substepEl) { + const suffix = finished ? " \u2014 complete" : state === "failed" ? " \u2014 stopped" : ""; + substepEl.textContent = `Step ${step} of 3 \u2014 ${PIPELINE_STAGE_LABELS[step]}${suffix}`; + } +} + +/** + * Pin the status line to a stage the user chose. Only stages this run actually + * reached are reachable, so the control can never report an invented state. + */ +function selectPipelineStage(step) { + if (pipelineStageStates[step] === "pending" || pipelineStageStates[step] === "skipped") return; + pipelineSelectedStage = step; + [1, 2, 3].forEach((candidate) => { + const button = pipelineStageButton(candidate); + if (button) button.setAttribute("aria-pressed", String(candidate === step)); + }); + renderPipelineStatus(step); +} + +function clearPipelineStageSelection() { + pipelineSelectedStage = null; + [1, 2, 3].forEach((step) => { + const button = pipelineStageButton(step); + if (button) button.removeAttribute("aria-pressed"); + }); +} + +function setPipelineNote(text) { + const note = document.getElementById("pipeline-note"); + if (!note) return; + note.textContent = text || ""; + note.hidden = !text; +} + +/** + * A model fallback is a real service event, so it is reported rather than + * hidden - but the run is still in flight, so it is a note, not a failure. + */ +function notePipelineFallback(primaryModel, fallbackModel, runId) { + if (!isCurrentPipelineRun(runId)) return; + setPipelineNote( + `${getModelLabel(primaryModel)} did not answer. Continuing on ${getModelLabel(fallbackModel)}.`, + ); +} + +function hidePipelineFailure() { + const panel = document.getElementById("pipeline-failure"); + if (!panel) return; + panel.hidden = true; + const actions = document.getElementById("pipeline-failure-actions"); + if (actions) actions.replaceChildren(); +} + +// --- COMPOSER -> PIPELINE -> RESULTS OUTLINE MORPH --- +// +// The authored hand-off: a coral outline leaves the composer's rect and grows +// into the generation panel's, then the panel's into the expanded Results +// view, on the 1120ms --t-morph clock. It is decorative only - the real view +// is already in place underneath before the outline moves, so the animation +// can never delay, gate or invent a service outcome. It is skipped under +// reduced motion and torn down on resize, navigation and interruption. +const PIPELINE_MORPH_FALLBACK_MS = 1120; + +/** The authored morph clock, read from the --t-morph design token. */ +function pipelineMorphDurationMs() { + const token = getComputedStyle(document.documentElement) + .getPropertyValue("--t-morph") + .trim(); + const parsed = Number.parseFloat(token); + return Number.isFinite(parsed) && parsed > 0 ? parsed : PIPELINE_MORPH_FALLBACK_MS; +} + +function prefersReducedMotion() { + return window.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true; +} + +function cancelPipelineMorph() { + cancelSurfaceMotion(); +} + +function pipelineRevealNodes() { + return [".pipeline-prompt-kicker", "#pipeline-submitted-prompt", "#pipeline-edit-prompt", ".pipeline-glyph", "#progress-title-text", "#progress-description-text", ".progress-track", ".progress-meta"].map((selector) => document.querySelector(selector)); +} + +function togglePipelineStageNavigation() { + const nav = document.getElementById("pipeline-stage-nav"); + const open = nav.classList.toggle("is-open"); + document.getElementById("progress-stage-count").setAttribute("aria-expanded", String(open)); +} +window.togglePipelineStageNavigation = togglePipelineStageNavigation; + +/** Composer -> generation panel. */ +function morphComposerToPipeline(from, heroRect) { + morphSurface(from, document.getElementById("main-stage-container"), pipelineRevealNodes()); + exitHero(document.getElementById("hero"), heroRect); +} + +// Navigating away abandons the hand-off rather than leaving an orphaned +// outline floating over another surface. +window.addEventListener("hashchange", cancelPipelineMorph); +window.addEventListener("popstate", cancelPipelineMorph); + +function showPipelineProgress(options = {}) { + const { prompt = null, runId } = options; + if (!isCurrentPipelineRun(runId)) return; + // A previous run's delayed hide must not blank this run's panel. + cancelPipelineHideTimer(); + cancelPipelineMorph(); + + setGenerationStageVisible(true); const progress = document.getElementById("pipeline-progress"); const resultsView = document.getElementById("results-view"); const readyState = document.getElementById("ready-state"); @@ -5752,85 +8539,224 @@ function showPipelineProgress() { if (resultsView) resultsView.classList.remove("visible"); document.body.classList.remove("results-fullscreen", "results-with-sidebar"); if (progress) progress.classList.add("visible"); + document.getElementById("pipeline-stage-nav")?.classList.remove("is-open"); + document.getElementById("progress-stage-count")?.setAttribute("aria-expanded", "false"); + setPipelineRunState("running"); - pipelineStartTime = Date.now(); - - // Reset dots - for (let i = 1; i <= 3; i++) { - const dot = document.getElementById(`pdot-${i}`); - if (dot) { dot.className = "progress-dot"; } + if (prompt !== null) { + const promptEl = document.getElementById("pipeline-submitted-prompt"); + if (promptEl) promptEl.textContent = prompt; } - updatePipelineProgressStep(1); + pipelineStartTime = Date.now(); + // The elapsed counter is the only time-driven element: start each run at + // zero rather than showing the previous run's final reading until the + // first tick lands. + const elapsedEl = document.getElementById("progress-elapsed"); + if (elapsedEl) elapsedEl.textContent = "0s"; + pipelineStageStates = { 1: "pending", 2: "pending", 3: "pending" }; + clearPipelineStageSelection(); + hidePipelineFailure(); + setPipelineNote(""); + [1, 2, 3].forEach((step) => setPipelineStageState(step, "pending")); + + updatePipelineProgressStep(1, runId); startProgressTimer(); } -function updatePipelineProgressStep(step) { - const titles = { - 1: "Analyzing your prompt...", - 2: "Generating Dart code...", - 3: "Running code audit..." - }; - const substeps = { - 1: "Step 1 of 3 \u2014 Prompt Architect", - 2: "Step 2 of 3 \u2014 Code Generator", - 3: "Step 3 of 3 \u2014 Code Review" - }; +/** + * Enter a stage. Stages before it that never ran stay `skipped` - the refine + * and fix-from-errors flows re-enter at stage 2, and their untouched Architect + * stage must not read as completed work. + */ +function updatePipelineProgressStep(step, runId) { + if (!isCurrentPipelineRun(runId)) return; + pipelineActiveStage = step; + pipelineStageStartedAt = Date.now(); + clearPipelineStageSelection(); + + [1, 2, 3].forEach((candidate) => { + if (candidate === step) { + setPipelineStageState(candidate, "active"); + } else if (candidate < step && pipelineStageStates[candidate] !== "done") { + setPipelineStageState(candidate, "skipped"); + } else if (candidate > step) { + setPipelineStageState(candidate, "pending"); + } + }); - const titleEl = document.getElementById("progress-title-text"); - const substepEl = document.getElementById("progress-substep-text"); - if (titleEl) titleEl.textContent = titles[step] || titles[1]; - if (substepEl) substepEl.textContent = substeps[step] || substeps[1]; + renderPipelineStatus(step); + renderPipelineTrack(); +} - // Update dots - for (let i = 1; i <= 3; i++) { - const dot = document.getElementById(`pdot-${i}`); - if (!dot) continue; - if (i < step) { - dot.className = "progress-dot completed"; - } else if (i === step) { - dot.className = "progress-dot active"; - } else { - dot.className = "progress-dot"; +/** Mark a stage complete. Only a real stage response calls this. */ +function completePipelineStage(step, runId) { + if (!isCurrentPipelineRun(runId)) return; + setPipelineStageState(step, "done"); + if (pipelineSelectedStage === null) renderPipelineStatus(step, { done: true }); + renderPipelineTrack(); +} + +/** Render the persistent failure state for a terminated run. */ +function showPipelineFailure(error, { stage = 1, runId, retry = retryPipelineRun } = {}) { + if (!isCurrentPipelineRun(runId)) return; + + stopProgressTimer(); + cancelPipelineHideTimer(); + cancelPipelineMorph(); + setPipelineRunState("failed"); + setGenerationStageVisible(true); + const progress = document.getElementById("pipeline-progress"); + if (progress) progress.classList.add("visible"); + const resultsView = document.getElementById("results-view"); + if (resultsView) resultsView.classList.remove("visible"); + document.body.classList.remove("results-fullscreen", "results-with-sidebar"); + + setPipelineStageState(stage, "failed"); + [1, 2, 3].forEach((step) => { + if (step > stage) setPipelineStageState(step, "pending"); + }); + pipelineActiveStage = stage; + clearPipelineStageSelection(); + renderPipelineStatus(stage); + renderPipelineTrack(); + + const failure = classifyPipelineError(error); + const panel = document.getElementById("pipeline-failure"); + const titleEl = document.getElementById("pipeline-failure-title"); + const messageEl = document.getElementById("pipeline-failure-message"); + const hintEl = document.getElementById("pipeline-failure-hint"); + const actionsEl = document.getElementById("pipeline-failure-actions"); + if (!panel || !titleEl || !messageEl || !actionsEl) return; + + panel.dataset.kind = failure.kind; + // The stage is named in the panel too, so a failure reads as "this stage + // stopped", never as an ambiguous whole-run outcome. + titleEl.textContent = `${PIPELINE_STAGE_LABELS[stage]}: ${failure.title}`; + messageEl.textContent = failure.message; + if (hintEl) { + const hint = failure.detail && failure.detail !== failure.message ? failure.detail : ""; + hintEl.textContent = hint; + hintEl.hidden = !hint; + } + + actionsEl.replaceChildren(); + // Only offer what can actually help: a blocked safety decision or an + // exhausted allowance will not change on a bare retry. + const actions = [ + failure.canUpgrade && { id: "upgrade", label: "View plans", variant: "primary", onClick: () => openPricingModal() }, + failure.canRetry && { id: "retry", label: "Retry", variant: failure.canUpgrade ? "secondary" : "primary", onClick: retry }, + failure.canEdit && { id: "edit", label: "Edit prompt", variant: "secondary", onClick: editPipelinePrompt }, + ].filter(Boolean); + // A terminated run must always leave a way back to usable controls, even + // when neither retrying nor editing can fix what happened. + if (!failure.canEdit && !failure.canRetry) { + actions.push({ id: "edit", label: "Back to prompt", variant: "secondary", onClick: editPipelinePrompt }); + } + actions.forEach((action) => { + const button = document.createElement("button"); + button.type = "button"; + button.textContent = action.label; + button.dataset.action = action.id; + button.dataset.variant = action.variant; + button.addEventListener("click", action.onClick); + actionsEl.appendChild(button); + }); + + panel.hidden = false; + // A terminated run must leave a usable, focused control behind. + const firstAction = actionsEl.querySelector("button"); + if (firstAction) firstAction.focus({ preventScroll: true }); +} + +/** + * Return to the composer with the submitted prompt intact. Editing abandons + * the in-flight run: its id is invalidated so a late response is discarded, + * its request is cancelled, and the send control is usable again — the run + * can never finish behind the composer's back and reopen Results. + */ +function editPipelinePrompt() { + invalidatePipelineRun(); + abortPipelineRequests(); + pipelineState.isRunning = false; + setRunPipelineButtonBusy(false); + updateDeployButtonVisibility(); + setPipelineRunState("settled"); + cancelPipelineMorph(); + stopProgressTimer(); + cancelPipelineHideTimer(); + hidePipelineFailure(); + const progress = document.getElementById("pipeline-progress"); + if (progress) progress.classList.remove("visible"); + setGenerationStageVisible(false); + const input = document.getElementById("pipeline-input"); + if (input) { + if (pipelineState.submittedPrompt) { + input.value = pipelineState.submittedPrompt; + // Programmatic restores emit no input event; dispatch one so the + // composer's ghost text, chip selection and send state resync. + input.dispatchEvent(new Event("input", { bubbles: true })); } + input.focus({ preventScroll: true }); + input.setSelectionRange(input.value.length, input.value.length); + } +} + +/** Re-run the prompt and images the user submitted, unchanged. */ +function retryPipelineRun() { + const input = document.getElementById("pipeline-input"); + if (input && pipelineState.submittedPrompt) { + input.value = pipelineState.submittedPrompt; + // Same resync as the composer-restore path above. + input.dispatchEvent(new Event("input", { bubbles: true })); } + promptImages = pipelineState.submittedImages.slice(); + renderPromptImages(); + hidePipelineFailure(); + runThinkingPipeline(); } function startProgressTimer() { - if (pipelineProgressTimer) clearInterval(pipelineProgressTimer); + stopProgressTimer(); - pipelineProgressTimer = setInterval(() => { + pipelineElapsedTimer = setInterval(() => { const elapsed = (Date.now() - pipelineStartTime) / 1000; const elapsedEl = document.getElementById("progress-elapsed"); - const fillEl = document.getElementById("pipeline-progress-fill"); - if (elapsedEl) elapsedEl.textContent = `${Math.floor(elapsed)}s`; - - // Ease toward ~95% over the estimated duration, never quite reaching 100% - const rawPct = (elapsed / PIPELINE_ESTIMATED_DURATION) * 100; - const easedPct = Math.min(95, rawPct * (1 - Math.exp(-elapsed / (PIPELINE_ESTIMATED_DURATION * 0.6))) * 1.2); - if (fillEl) fillEl.style.width = `${easedPct}%`; + // The same tick drives the fill's in-slice easing. + renderPipelineTrack(); }, 250); } -function hidePipelineProgress() { - if (pipelineProgressTimer) { - clearInterval(pipelineProgressTimer); - pipelineProgressTimer = null; +function stopProgressTimer() { + if (pipelineElapsedTimer) { + clearInterval(pipelineElapsedTimer); + pipelineElapsedTimer = null; } +} - // Snap to 100% - const fillEl = document.getElementById("pipeline-progress-fill"); - if (fillEl) fillEl.style.width = "100%"; +// The settled run's panel lingers 400ms before it hides; a run that starts +// inside that window must not be blanked by the previous run's timer. +let pipelineHideTimer = null; - // Mark all dots completed - for (let i = 1; i <= 3; i++) { - const dot = document.getElementById(`pdot-${i}`); - if (dot) dot.className = "progress-dot completed"; +function cancelPipelineHideTimer() { + if (pipelineHideTimer) { + clearTimeout(pipelineHideTimer); + pipelineHideTimer = null; } +} + +function hidePipelineProgress() { + stopProgressTimer(); + cancelPipelineHideTimer(); + setPipelineRunState("settled"); + renderPipelineTrack(); + + const fillEl = document.getElementById("pipeline-progress-fill"); // Brief pause then hide - setTimeout(() => { + pipelineHideTimer = setTimeout(() => { + pipelineHideTimer = null; const progress = document.getElementById("pipeline-progress"); if (progress) progress.classList.remove("visible"); if (fillEl) fillEl.style.width = "0%"; @@ -5918,19 +8844,32 @@ function renderSummaryDetail(presentation) {
` : ""; + // Bundle-level warnings (deploy ordering, compatibility findings) belong on + // the summary surface as a distinct class of message. They are NOT + // per-file issues and must never leak into a selected artifact's review. + const bundleWarnings = presentation.warnings.length + ? ` +
+

${reviewStatusIcon("warning")} Bundle

+
    + ${presentation.warnings.map((warning) => `
  • ${escapeHtml(warning)}
  • `).join("")} +
+
+ ` + : ""; const manualSteps = presentation.manualSteps.length ? `
-

${reviewStatusIcon("info")} Complete in FlutterFlow

-

For your information — these don't block the deploy. Finish them by hand in the FlutterFlow editor once the code is pushed.

-
    +

    Complete in FlutterFlow

    +

    For your information — these don't block the deploy. Finish them by hand in the FlutterFlow editor once the code is pushed.

    +
      ${presentation.manualSteps.map((step) => `
    1. ${escapeHtml(step.title)} ${step.detail && step.detail !== step.title ? `${escapeHtml(step.detail)}` : ""}
    2. `).join("")} -
+
` : ""; @@ -5938,9 +8877,16 @@ function renderSummaryDetail(presentation) { summaryDetail.innerHTML = `
+

${escapeHtml(presentation.title)}

${escapeHtml(presentation.summary)}

+
+
Artifact${presentation.artifacts.length === 1 ? "" : "s"}
${presentation.artifacts.map((artifact) => escapeHtml(artifact.artifactType || artifact.type || artifact.name)).join(" · ")}
+
Public API
${presentation.artifacts.flatMap((artifact) => artifact.publicApi || []).map(escapeHtml).join(" · ") || "No parameters returned"}
+
Manual Steps Required
${manualSteps || "None reported"}
+
Review
${escapeHtml(presentation.status || "Not reported")}
+
${findings} - ${manualSteps} + ${bundleWarnings}
@@ -6065,12 +9012,22 @@ function renderBundleControls(presentation) { const tabs = document.getElementById("artifact-tabs"); const count = document.getElementById("results-file-count"); if (summaryTab) { - summaryTab.classList.toggle("active", pipelineState.resultsViewMode === "summary"); + const isSummary = pipelineState.resultsViewMode === "summary"; + summaryTab.classList.toggle("active", isSummary); + summaryTab.setAttribute("role", "tab"); + summaryTab.setAttribute("aria-selected", String(isSummary)); + summaryTab.setAttribute("aria-controls", "results-summary-detail"); + summaryTab.tabIndex = isSummary ? 0 : -1; + } + if (tabs) { + tabs.setAttribute("role", "tablist"); + tabs.setAttribute("aria-label", "Artifacts in this bundle"); } if (!presentation.artifacts.length) { if (count) count.textContent = "0 files"; if (strip) strip.classList.remove("visible"); if (tabs) tabs.innerHTML = ""; + ensureResultsTabKeyboard(); return; } @@ -6079,11 +9036,19 @@ function renderBundleControls(presentation) { count.textContent = `${fileCount} ${fileCount === 1 ? "file" : "files"}`; } if (tabs) { - tabs.innerHTML = presentation.artifacts.map((artifact) => ` + tabs.innerHTML = presentation.artifacts.map((artifact) => { + const isSelected = pipelineState.resultsViewMode === "file" + && artifact.id === pipelineState.selectedArtifactId; + return ` - `).join(""); + `; + }).join(""); tabs.onclick = (event) => { const tab = event.target.closest(".artifact-tab"); if (tab?.dataset?.artifactId) { selectArtifact(tab.dataset.artifactId); } }; + ensureResultsTabKeyboard(); } if (strip) strip.classList.add("visible"); } +// WAI-ARIA tabs pattern: ArrowRight/ArrowLeft move focus through the tablist, +// Home/End jump to the first/last tab. The selected tab is activated and focus +// is re-applied after the render so keyboard focus survives the re-render that +// refreshArtifactTabs performs on selection change. +function ensureResultsTabKeyboard() { + const tablist = document.getElementById("bundle-strip"); + if (!tablist || tablist.dataset.tabKeyboard === "bound") return; + tablist.dataset.tabKeyboard = "bound"; + tablist.addEventListener("keydown", (event) => { + if (event.defaultPrevented) return; + const tabs = [ + document.getElementById("results-summary-tab"), + ...Array.from(document.querySelectorAll("#artifact-tabs .artifact-tab")), + ].filter(Boolean); + if (!tabs.length || !tabs.includes(document.activeElement)) return; + + let targetIndex = -1; + const currentIndex = tabs.indexOf(document.activeElement); + if (event.key === "ArrowRight") targetIndex = (currentIndex + 1) % tabs.length; + else if (event.key === "ArrowLeft") targetIndex = (currentIndex - 1 + tabs.length) % tabs.length; + else if (event.key === "Home") targetIndex = 0; + else if (event.key === "End") targetIndex = tabs.length - 1; + else return; + + event.preventDefault(); + const target = tabs[targetIndex]; + if (!target) return; + if (target.id === "results-summary-tab") { + selectResultsSummary(); + } else { + const artifactId = target.dataset.artifactId; + if (artifactId) selectArtifact(artifactId); + } + // Re-apply focus to the freshly rendered tab after the selection re-render. + const freshTab = target.id === "results-summary-tab" + ? document.getElementById("results-summary-tab") + : document.querySelector(`#artifact-tabs .artifact-tab[data-artifact-id="${target.dataset.artifactId}"]`); + if (freshTab) freshTab.focus(); + }); +} + function updateSelectedArtifactPanels() { document.body.classList.add("results-fullscreen"); document.body.classList.add("results-with-sidebar"); @@ -6115,13 +9123,41 @@ function updateSelectedArtifactPanels() { const presentation = getReviewPresentation(); const selectedCode = getSelectedArtifactCode(); + // Harden the summary/file tabpanel semantics for the WAI-ARIA tabs pattern. + if (summaryDetail) { + summaryDetail.setAttribute("role", "tabpanel"); + summaryDetail.setAttribute("aria-labelledby", "results-summary-tab"); + } + if (artifactSplit) { + artifactSplit.setAttribute("role", "tabpanel"); + const selectedArtifact = presentation?.artifacts?.find( + (artifact) => artifact.id === pipelineState.selectedArtifactId, + ); + artifactSplit.setAttribute( + "aria-labelledby", + selectedArtifact ? `artifact-tab-${selectedArtifact.id}` : "results-summary-tab", + ); + } + renderSummaryDetail(presentation); renderBundleControls(presentation); if (codeOutput) codeOutput.textContent = ""; if (codeOutput) { - const highlighted = highlightCode(selectedCode); - codeOutput.innerHTML = highlighted; // eslint-disable-line -- highlight.js output + // Highlight each raw line independently, preserving exact copied source. + // Line presentation never writes back into the artifact bundle. + codeOutput.replaceChildren(); + selectedCode.split("\n").forEach((line, index) => { + const span = document.createElement("span"); + span.className = "code-line"; + span.innerHTML = highlightCode(line); // highlight.js escapes source + if (!prefersReducedMotion() && pipelineState.resultsViewMode === "file") { + span.classList.add("is-in"); + span.style.setProperty("--d", `${index * 10}ms`); + span.addEventListener("animationend", () => span.classList.remove("is-in"), { once:true }); + } + codeOutput.appendChild(span); + }); } if (auditOutput) { auditOutput.innerHTML = renderSelectedArtifactReview(presentation); @@ -6136,6 +9172,12 @@ function updateSelectedArtifactPanels() { } function showResultsView(codeContent, auditContent) { + const panel = document.getElementById("main-stage-container"); + const from = currentSurfaceRect(panel); + const wasResults = document.body.classList.contains("results-fullscreen"); + cancelPipelineHideTimer(); + document.getElementById("pipeline-progress")?.classList.remove("visible"); + setGenerationStageVisible(true); if (!pipelineState.selectedArtifactId) { pipelineState.selectedArtifactId = getPrimaryArtifact(pipelineState.artifactBundle).id; } @@ -6146,11 +9188,35 @@ function showResultsView(codeContent, auditContent) { updateSelectedArtifactPanels(); updateDeployButtonVisibility(); - // Reset feedback buttons + // Reset feedback state for the CURRENT generation: a new run must never + // carry a prior vote (visual, aria-pressed, pending lock or status) into + // code the user has not yet reviewed. + resetResultsFeedbackState(); + if (!wasResults) { + morphSurface(from, panel, ["#bundle-strip", ".summary-heading", ".review-summary-text", ".summary-spec", ".review-score-column", ".results-action-bar"].map((selector) => document.querySelector(selector)), { results:true }); + } +} + +function resetResultsFeedbackState() { const upBtn = document.getElementById("btn-feedback-up"); const downBtn = document.getElementById("btn-feedback-down"); - if (upBtn) upBtn.className = "feedback-btn"; - if (downBtn) downBtn.className = "feedback-btn"; + const statusEl = document.getElementById("results-feedback-status"); + if (upBtn) { + upBtn.className = "feedback-btn"; + upBtn.setAttribute("aria-pressed", "false"); + upBtn.disabled = false; + upBtn.removeAttribute("aria-disabled"); + } + if (downBtn) { + downBtn.className = "feedback-btn"; + downBtn.setAttribute("aria-pressed", "false"); + downBtn.disabled = false; + downBtn.removeAttribute("aria-disabled"); + } + if (statusEl) { + statusEl.textContent = ""; + } + resultsFeedbackPending = false; } function showDebugMultiArtifactResults() { @@ -6259,7 +9325,7 @@ function showDebugMultiArtifactResults() { const paywallEl = document.getElementById("paywall-exhausted"); if (paywallEl) paywallEl.classList.add("hidden"); const walkthroughModal = document.getElementById("walkthrough-modal"); - if (walkthroughModal) walkthroughModal.classList.remove("open"); + if (walkthroughModal) closeModal(walkthroughModal, { restoreFocus: false }); const readyState = document.getElementById("ready-state"); if (readyState) readyState.classList.add("hidden"); const stageContainer = document.getElementById("main-stage-container"); @@ -6279,11 +9345,157 @@ function selectResultsSummary() { updateSelectedArtifactPanels(); } +// Test/diagnostic hook used by the browser suite to render an arbitrary +// bundle + review without running paid generation. Mirrors the debug path so +// the Results Summary / artifact inspection surfaces can be asserted in +// isolation. Gated on import.meta.env.DEV so the hook (and its ability to +// force the results view with arbitrary content) is tree-shaken out of the +// production bundle: it exists only under the Vite dev server, which is what +// the Playwright suite runs against. +if (import.meta.env.DEV) { + function renderResultsPreview(bundle, review) { + const readyState = document.getElementById("ready-state"); + if (readyState) readyState.classList.add("hidden"); + const stageContainer = document.getElementById("main-stage-container"); + if (stageContainer) stageContainer.classList.add("visible"); + hidePipelineProgress?.(); + const paywallEl = document.getElementById("paywall-exhausted"); + if (paywallEl) paywallEl.classList.add("hidden"); + + pipelineState.step3Result = typeof review === "string" ? review : JSON.stringify(review); + pipelineState.step2Result = typeof bundle === "string" ? bundle : JSON.stringify(bundle); + pipelineState.artifactBundle = normalizeArtifactBundle(bundle, { + id: bundle?.id, + title: bundle?.title, + description: bundle?.description, + }); + pipelineState.bundleSpec = pipelineState.artifactBundle; + updateBundleReviewFromReviewResult(); + pipelineState.selectedArtifactId = getPrimaryArtifact(pipelineState.artifactBundle).id; + showResultsView(getSelectedArtifactCode(), renderMarkdownAudit(pipelineState.step3Result)); + } + window.__CCC_RENDER_RESULTS__ = renderResultsPreview; + + // Deterministic test hook for STU-380: drives the exact same terminal + // presentation the real confirm flow uses, against a fixture result, so the + // browser suite can assert truthful outcomes without a real remote write. + window.__CCC_RENDER_DEPLOY_TERMINAL__ = renderCommitTerminal; + // Lets the browser suite start a live deploy progress overlay so it can + // prove a terminal state releases the busy state. + window.__CCC_START_DEPLOY_PROGRESS__ = () => + commitProgress.start({ withProvisioning: true }); + // Lets the browser suite put the deploy into (and out of) its exactly-real + // busied state — the same `setDeployBusy` the confirm flow calls — so a test + // can prove a terminal outcome releases the busy lock on the deploy controls. + window.__CCC_SET_DEPLOY_BUSY__ = setDeployBusy; + // Lets the browser suite open the real commit-confirm modal (and set real + // `pendingCommitData`) with fixture code, so the duplicate-submit guard in + // `confirmCommitToFlutterFlow` can be driven through the real confirm flow + // without a real remote write. + window.__CCC_OPEN_COMMIT_CONFIRM__ = (codeInfo, checks, deps) => + openCommitConfirmModal( + { + fileName: "gauge_widget.dart", + artifactType: "CustomClass", + content: "class GaugeWidget {}", + ...codeInfo, + }, + { warnings: [], ...checks }, + deps || {}, + ); + // Lets the browser suite drive the real provisioning transport — fetch, + // stream read and UI bound — against routed fixtures, so a stalled or + // dropped connection can be proven to resolve as unconfirmed rather than + // hanging or fabricating a failure. + window.__CCC_PROVISION_CUSTOM_CLASSES__ = ({ + fileMap, + remoteFiles, + commitMessage, + pubspecYaml, + uiTimeoutMs, + } = {}) => + provisionMissingCodeFiles( + new FlutterFlowApiClient( + "test-key", + "ff-proj-0007", + "main", + FF_API_ENDPOINTS.production, + ), + new Map(Object.entries(fileMap || {})), + new Map(Object.entries(remoteFiles || {})), + commitMessage || "Provision test class", + pubspecYaml || "", + uiTimeoutMs, + ); + // Lets the browser suite drive the real retry loop against routed endpoints, + // so transport-error exhaustion vs a definitive HTTP refusal can each be + // proven to produce their truthful outcome. + window.__CCC_PUSH_CODE_WITH_RETRY__ = (pushCodeRequest, maxRetries) => + new FlutterFlowApiClient( + "test-key", + "ff-proj-0007", + "main", + FF_API_ENDPOINTS.production, + ).pushCodeWithRetry(pushCodeRequest, maxRetries); + // Lets the browser suite feed a crafted Response into the real sync-response + // parser, so a body that drops mid-read can be proven to classify on the + // received status instead of leaking the raw read error. + window.__CCC_PARSE_PUSH_RESPONSE__ = (response, bodyTimeoutMs) => + parsePushCodeResponse(response, bodyTimeoutMs); + // Lets the browser suite drive the bounded push (fetch + parse under the UI + // timeout) with a short bound, so a stalled request provably settles as + // unconfirmed instead of hanging the deploy. + window.__CCC_PUSH_CODE_WITH_TIMEOUT__ = (pushCodeRequest, uiTimeoutMs) => + pushCodeWithUiTimeout( + new FlutterFlowApiClient( + "test-key", + "ff-proj-0007", + "main", + FF_API_ENDPOINTS.production, + ), + pushCodeRequest, + uiTimeoutMs, + ); + // Lets the browser suite seed/observe the project-source cache: a deploy + // that lost its provisioning result must leave the cache empty so the next + // one re-reads the project instead of re-provisioning written classes. + window.__CCC_RESOLVE_PROJECT_PUBSPEC__ = async (deps) => { + const result = await resolveProjectPubspec( + new FlutterFlowApiClient( + "test-key", + "ff-proj-0007", + "main", + FF_API_ENDPOINTS.production, + ), + deps || {}, + ); + return { + remoteFilePaths: [...result.remoteFiles.keys()], + added: result.added, + }; + }; +} + function copyResultsCode() { const btn = document.getElementById("btn-copy-results"); + const statusEl = document.getElementById("results-copy-status"); const rawCode = getSelectedArtifactCode(); + const setStatus = (message, ok) => { + if (!statusEl) return; + statusEl.textContent = message; + statusEl.classList.toggle("ok", Boolean(ok)); + statusEl.classList.toggle("fail", !ok); + }; + + if (!navigator.clipboard?.writeText) { + // The Clipboard API is unavailable (non-secure context or unsupported). + // Surface a non-blocking notice; the results view stays usable. + setStatus("Copying isn't supported in this browser.", false); + return; + } navigator.clipboard.writeText(rawCode).then(() => { + setStatus("Copied to clipboard", true); if (btn) { btn.classList.add("copied"); const label = btn.querySelector("span"); @@ -6296,25 +9508,77 @@ function copyResultsCode() { }, 2000); } } + }).catch(() => { + // Permission denied or transient clipboard failure. This must never block + // the results view — the user can still read and select the code. + setStatus("Clipboard permission was denied. Select the code to copy it manually.", false); }); } -function submitResultsFeedback(direction) { +let resultsFeedbackPending = false; + +async function submitResultsFeedback(direction) { const upBtn = document.getElementById("btn-feedback-up"); const downBtn = document.getElementById("btn-feedback-down"); + const statusEl = document.getElementById("results-feedback-status"); + if (!upBtn || !downBtn) return; + // Ignore a rapid double-click (or a second direction) while a submission is + // still in flight so we never send a duplicate vote for the same generation. + if (resultsFeedbackPending) return; + + const announce = (message) => { + if (!statusEl) return; + statusEl.textContent = ""; + void statusEl.offsetWidth; // force reflow so repeated announcements re-fire + statusEl.textContent = message; + }; - // Toggle - if (direction === "up") { - upBtn.classList.toggle("active-up"); - downBtn.classList.remove("active-down"); - } else { - downBtn.classList.toggle("active-down"); - upBtn.classList.remove("active-up"); - } + const setPending = (pending) => { + resultsFeedbackPending = pending; + [upBtn, downBtn].forEach((btn) => { + btn.disabled = pending; + btn.setAttribute("aria-disabled", String(pending)); + }); + }; const feedbackType = direction === "up" ? "thumbsUp" : "thumbsDown"; - callEndpoint(feedbackType, pipelineState.step2Result, pipelineState.step1Result); - trackEvent("Generation Feedback", { feedback: feedbackType }); + setPending(true); + announce("Submitting review feedback…"); + + // Capture the CURRENT generation up front so a retry always sends the exact + // bundle + input the user reviewed — never a prior generation's payload. + const payload = { type: feedbackType, code: pipelineState.step2Result, input: pipelineState.step1Result }; + try { + const result = await callEndpoint(payload.type, payload.code, payload.input); + // A vote is only claimed as saved after the endpoint positively confirms + // success. Requiring the explicit `success: true` the backend contract + // returns means a 2xx carrying an error-shaped body ({"error":"quota + // exceeded"} or {"ok":false}, with no truthy success field) is never + // announced as saved — a failed submission must stay retry-able instead + // of silently clearing the pending lock. + if (!result || result.success !== true) { + // A non-2xx response, network failure, or unconfirmed 2xx is never shown + // as saved. + setPending(false); + announce("Review feedback could not be sent. Tap again to retry."); + return; + } + + // Only a confirmed submission marks the vote saved; the chosen direction + // becomes pressed and the other is cleared (mutually exclusive). + upBtn.classList.toggle("active-up", direction === "up"); + downBtn.classList.toggle("active-down", direction === "down"); + upBtn.setAttribute("aria-pressed", String(direction === "up")); + downBtn.setAttribute("aria-pressed", String(direction === "down")); + setPending(false); + announce("Review feedback saved."); + trackEvent("Generation Feedback", { feedback: feedbackType }); + } catch (error) { + // callEndpoint swallows its own/rejection errors into { success:false }, + // but a hard throw must also fail open without showing a saved vote. + setPending(false); + announce("Review feedback could not be sent. Tap again to retry."); + } } function showErrorInputPanel() { @@ -6335,9 +9599,177 @@ function hideErrorInputPanel() { } } +// --- VIEW ROUTER & SHELL UI (STU-375) --- + +function initExactShell() { + const stage = document.getElementById("shell-stage"); + const panel = document.getElementById("main-stage-container"); + const sidebar = panel?.querySelector(".pipeline-prompt-recap"); + const mobile = window.matchMedia("(max-width: 920px)"); + const fit = () => stage?.style.setProperty("--fit", Math.min(1, document.documentElement.clientWidth / 1920)); + const order = () => { + if (!sidebar) return; + const focused = sidebar.contains(document.activeElement) ? document.activeElement : null; + // Use the same persistent node; DOM, screen-reader and keyboard order agree + // with the reference's desktop sidebar and mobile workflow-first layout. + if (mobile.matches) panel.appendChild(sidebar); + else panel.prepend(sidebar); + focused?.focus({ preventScroll:true }); + }; + fit(); order(); + window.addEventListener("resize", fit); + mobile.addEventListener("change", order); +} + +function setGenerationStageVisible(visible) { + const stage = document.getElementById("generation-stage"); + if (!stage) return; + const hero = document.getElementById("hero"); + if (hero) { hero.hidden = visible; hero.inert = visible; } + if (visible) { + stage.hidden = false; + stage.inert = false; + stage.classList.add("is-active"); + } else { + cancelPipelineMorph(); + document.body.classList.remove("results-fullscreen", "results-with-sidebar"); + stage.classList.remove("is-active"); + stage.inert = true; + stage.hidden = true; + } +} + +function updateShellUI() { + const signedIn = authState.isVerified && !!authState.email; + const tier = subscriptionState.tier || "free"; + const loading = signedIn && isSubscriptionLoading(); + const resolved = !signedIn || isSubscriptionResolved(); + + const labels = planLabels; + const planLabel = loading ? "Checking…" : resolved ? labels[tier] || "Free" : "—"; + + const topbarPlan = document.getElementById("topbar-plan"); + if (topbarPlan) topbarPlan.textContent = planLabel; + + const avatar = document.getElementById("topbar-avatar"); + if (avatar) avatar.textContent = (authState.email || "?")[0].toUpperCase(); + + renderUsageSurfaces(); + + // Plans view current-plan indicators + const freeCurrent = document.getElementById("plans-free-current"); + if (freeCurrent) freeCurrent.classList.toggle("hidden", tier !== "free" || !resolved); + + const proBtn = document.getElementById("plans-checkout-btn-professional"); + if (proBtn) { + const isCurrent = tier === "professional" && resolved; + proBtn.disabled = isCurrent; + proBtn.textContent = isCurrent ? "Current plan" : "Subscribe"; + } + const powerBtn = document.getElementById("plans-checkout-btn-power"); + if (powerBtn) { + const isCurrent = tier === "power" && resolved; + powerBtn.disabled = isCurrent; + powerBtn.textContent = isCurrent ? "Current plan" : "Subscribe"; + } +} + +function openCreditsModal() { + updateShellUI(); + const modal = document.getElementById("credits-modal"); + if (modal) openModal(modal); +} + +function closeCreditsModal(event) { + if (event && event.target !== event.currentTarget) return; + const modal = document.getElementById("credits-modal"); + if (modal) closeModal(modal); +} + +function switchView(view, pushState = true, moveFocus = true) { + view = ["home", "account", "plans"].includes(view) ? view : "home"; + document.body.dataset.shellView = view; + if (view !== "home") { + cancelPipelineMorph(); composerControls?.cancelTyping?.(); + if (pipelineState.isRunning) { + invalidatePipelineRun(); abortPipelineRequests(); + pipelineState.isRunning = false; + setRunPipelineButtonBusy(false); + // The abandoned run has nothing left to resume: dismiss its progress + // panel and return the stage to settled content — the previous result + // when one exists, otherwise the ready state — so coming back home + // can't resurrect a panel for a run that no longer exists. + hidePipelineProgress(); + if (pipelineState.artifactBundle) { + updateSelectedArtifactPanels(); + } else { + document.getElementById("results-view")?.classList.remove("visible"); + document.getElementById("ready-state")?.classList.remove("hidden"); + } + } + } + const views = document.querySelectorAll(".view[data-view]"); + views.forEach((el) => { + const isTarget = el.dataset.view === view; + if (isTarget) { + el.hidden = false; + el.removeAttribute("inert"); + requestAnimationFrame(() => { + el.classList.add("is-active"); + // Land keyboard focus in the revealed surface once it is visible. + if (moveFocus) el.focus({ preventScroll: true }); + }); + } else { + el.classList.remove("is-active"); + el.setAttribute("inert", "true"); + setTimeout(() => { + if (!el.classList.contains("is-active")) el.hidden = true; + }, 260); + } + }); + + // Generation overlay only belongs to the home surface. + if (view !== "home") setGenerationStageVisible(false); + else { + const stage = document.getElementById("main-stage-container"); + if (stage && stage.classList.contains("visible")) setGenerationStageVisible(true); + } + + if (pushState) { + const hash = view === "home" ? "" : `#${view}`; + if (window.location.hash !== hash) window.history.pushState({ view }, "", hash || "#"); + } +} + +let hasRestoredInitialView = false; +function restoreViewFromHash() { + const raw = window.location.hash.replace(/^#/, ""); + // The first restore is the initial page load, so focus stays wherever the + // browser put it; every later hash change is user-driven navigation and + // may move focus into the revealed surface. + switchView(raw || "home", false, hasRestoredInitialView); + hasRestoredInitialView = true; +} + +window.addEventListener("popstate", (event) => { + restoreViewFromHash(); +}); + +window.addEventListener("hashchange", () => { + restoreViewFromHash(); +}); + window.copyResultsCode = copyResultsCode; window.selectArtifact = selectArtifact; window.selectResultsSummary = selectResultsSummary; window.submitResultsFeedback = submitResultsFeedback; window.showErrorInputPanel = showErrorInputPanel; window.hideErrorInputPanel = hideErrorInputPanel; +window.setGenerationStageVisible = setGenerationStageVisible; +window.switchView = switchView; +// Pipeline view controls used by the generation panel's inline handlers. +window.selectPipelineStage = selectPipelineStage; +window.editPipelinePrompt = editPipelinePrompt; +window.retryPipelineRun = retryPipelineRun; +window.openCreditsModal = openCreditsModal; +window.closeCreditsModal = closeCreditsModal; diff --git a/cloud-run/ffai-runner/bin/server.dart b/cloud-run/ffai-runner/bin/server.dart index 141b3bc..c33a5fa 100644 --- a/cloud-run/ffai-runner/bin/server.dart +++ b/cloud-run/ffai-runner/bin/server.dart @@ -5,6 +5,8 @@ import 'dart:io'; const maxClassesPerRequest = 20; const maxCodeBytes = 500000; const maxDependenciesPerRequest = 200; +// pub.dev's own ceiling on a package name. +const maxPackageNameLength = 64; const analysisPackageName = 'ccc_custom_code_analysis'; const defaultSdkConstraint = '>=3.0.0 <4.0.0'; @@ -52,23 +54,46 @@ Future _handle(HttpRequest request) async { await channel.result(HttpStatus.notFound, { 'success': false, 'error': 'Not found.', + 'preWrite': true, }); return; } - final payload = await _readJson(request); - final apiKey = _stringField(payload, 'apiKey', maxLength: 10000); - final projectId = _stringField(payload, 'projectId', maxLength: 200); - final baseUrl = _stringField(payload, 'baseUrl', maxLength: 500, required: false); - final commitMessage = _stringField( - payload, - 'commitMessage', - maxLength: 300, - required: false, - ); - final dryRun = payload['dryRun'] == true; - final classes = _normalizeClasses(payload['customClasses']); - final verification = _normalizeVerification(payload['verification']); + // Only request parsing/validation throws FormatException here — those are + // provably pre-write. Decoding CLI output can raise the same exception + // AFTER the deploy began, so it must fall to the generic catch below, + // which does not claim preWrite. + Map payload; + String apiKey; + String projectId; + String baseUrl; + String commitMessage; + bool dryRun; + List classes; + _VerificationRequest? verification; + try { + payload = await _readJson(request); + apiKey = _stringField(payload, 'apiKey', maxLength: 10000); + projectId = _stringField(payload, 'projectId', maxLength: 200); + baseUrl = _stringField(payload, 'baseUrl', maxLength: 500, required: false); + commitMessage = _stringField( + payload, + 'commitMessage', + maxLength: 300, + required: false, + ); + dryRun = payload['dryRun'] == true; + classes = _normalizeClasses(payload['customClasses']); + verification = _normalizeVerification(payload['verification']); + } on FormatException catch (error) { + await channel.result(HttpStatus.badRequest, { + 'success': false, + 'error': error.message, + // Request validation precedes any work against the project. + 'preWrite': true, + }); + return; + } // Only stream for callers that asked for it, so older clients keep getting // the single JSON response they parse. @@ -89,6 +114,8 @@ Future _handle(HttpRequest request) async { : 'FlutterFlow AI workspace initialization failed.', 'details': _trimOutput(initResult.output), 'exitCode': initResult.exitCode, + // Workspace setup precedes any write to FlutterFlow. + 'preWrite': true, }); return; } @@ -106,6 +133,8 @@ Future _handle(HttpRequest request) async { 'deployed to FlutterFlow.', 'details': analysis.report, 'analyzerErrors': analysis.errors, + // The compile gate runs before the deploy script starts. + 'preWrite': true, }); return; } @@ -153,6 +182,8 @@ Future _handle(HttpRequest request) async { 'success': false, 'error': 'FlutterFlow AI DSL deploy timed out.', 'details': _trimOutput(result.output), + // The CLI may already have uploaded classes before timing out. + 'preWrite': false, }); return; } @@ -163,6 +194,7 @@ Future _handle(HttpRequest request) async { 'error': 'FlutterFlow AI DSL deploy failed.', 'details': _trimOutput(result.output), 'exitCode': result.exitCode, + 'preWrite': false, }); return; } @@ -180,17 +212,16 @@ Future _handle(HttpRequest request) async { 'verified': analysis?.verifiedFiles ?? const [], 'verificationSkipped': analysis?.skippedReason, }); - } on FormatException catch (error) { - await channel.result(HttpStatus.badRequest, { - 'success': false, - 'error': error.message, - }); } catch (error, stackTrace) { stderr.writeln(error); stderr.writeln(stackTrace); await channel.result(HttpStatus.internalServerError, { 'success': false, 'error': '$error', + // The stage is unknown — a FormatException from decoding CLI output can + // land here after the upload began — so the write cannot be proven not + // to have run. + 'preWrite': false, }); } } @@ -495,7 +526,8 @@ _VerificationRequest? _normalizeVerification(Object? value) { value['dependencyOverrides'], 'dependencyOverrides', ), - sdkPackages: _normalizeSdkPackages(value['sdkPackages']), + sdkPackages: _normalizeSdkPackages(value['sdkPackages'], 'sdkPackages'), + sdkOverrides: _normalizeSdkPackages(value['sdkOverrides'], 'sdkOverrides'), sources: sources, ); } @@ -522,7 +554,7 @@ Map _normalizeDependencyMap(Object? value, String field) { final result = {}; for (final entry in value.entries) { final name = '${entry.key}'; - if (!_packageNamePattern.hasMatch(name)) { + if (!_isValidPackageName(name)) { throw FormatException('Invalid package name in verification.$field: $name.'); } final constraint = '${entry.value}'.trim(); @@ -543,23 +575,32 @@ Map _normalizeDependencyMap(Object? value, String field) { /// `pub get` with an honest error, whereas a list refuses correct deploys the /// moment it falls behind the SDK. The pattern is the load-bearing check - each /// name becomes a key in the generated pubspec. -List _normalizeSdkPackages(Object? value) { +List _normalizeSdkPackages(Object? value, String field) { if (value == null) return const []; if (value is! List) { - throw const FormatException('verification.sdkPackages must be an array.'); + throw FormatException('verification.$field must be an array.'); + } + // Bounded like the dependency maps: each entry expands into the generated + // pubspec, so an unbounded array is caller-controlled work before pub get + // ever sees it. + if (value.length > maxDependenciesPerRequest) { + throw FormatException('Too many entries in verification.$field.'); } - final result = []; + final result = {}; for (final raw in value) { final name = '$raw'; - if (!_packageNamePattern.hasMatch(name)) { + if (!_isValidPackageName(name)) { throw FormatException('Invalid SDK package name: $name.'); } - if (!result.contains(name)) result.add(name); + result.add(name); } - return result; + return result.toList(); } +bool _isValidPackageName(String name) => + name.length <= maxPackageNameLength && _packageNamePattern.hasMatch(name); + String _validateConstraint( String field, String value, { @@ -951,6 +992,7 @@ final class _VerificationRequest { required this.dependencies, required this.overrides, required this.sdkPackages, + required this.sdkOverrides, required this.sources, }) : unavailableReason = null; @@ -960,6 +1002,7 @@ final class _VerificationRequest { dependencies = const {}, overrides = const {}, sdkPackages = const [], + sdkOverrides = const [], sources = const <_VerificationSource>[]; /// Why this request cannot be compiled, or null when it can. @@ -969,6 +1012,7 @@ final class _VerificationRequest { final Map dependencies; final Map overrides; final List sdkPackages; + final List sdkOverrides; final List<_VerificationSource> sources; /// Builds the pubspec the scratch package is compiled from. @@ -1005,13 +1049,21 @@ final class _VerificationRequest { lines.add(' $name: ${_yamlScalar(dependencies[name]!)}'); } - if (overrides.isNotEmpty) { + // SDK-sourced overrides belong in dependency_overrides, not in + // `dependencies` with sdkPackages: an override can share its name with a + // direct dependency, and emitting both under one map writes the key twice. + if (overrides.isNotEmpty || sdkOverrides.isNotEmpty) { lines ..add('') ..add('dependency_overrides:'); for (final name in overrides.keys.toList()..sort()) { lines.add(' $name: ${_yamlScalar(overrides[name]!)}'); } + for (final name in sdkOverrides.toList()..sort()) { + lines + ..add(' $name:') + ..add(' sdk: flutter'); + } } return '${lines.join('\n')}\n'; diff --git a/dist/assets/flutterflow-icon.svg b/dist/assets/flutterflow-icon.svg new file mode 100644 index 0000000..120a202 --- /dev/null +++ b/dist/assets/flutterflow-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dist/assets/index-BQUorxWE.css b/dist/assets/index-BQUorxWE.css new file mode 100644 index 0000000..9c08fec --- /dev/null +++ b/dist/assets/index-BQUorxWE.css @@ -0,0 +1 @@ +@font-face{font-family:Delight;src:url(/assets/Delight-VF-CnVpVuQk.ttf) format("truetype");font-weight:100 900;font-display:swap}:root{--bg: oklch(96.65% .0074 260.73);--surface: oklch(100% 0 0);--surface-translucent: oklch(100% 0 0 / .65);--surface-glass: oklch(100% 0 0 / .72);--surface-sunken: oklch(98.4% .004 260);--fg: oklch(20.77% .0398 265.75);--muted: oklch(48% .02 260);--muted-2: oklch(68% .018 260);--on-dark: oklch(100% 0 0);--border: oklch(90% .012 260);--border-strong: oklch(80% .02 260);--fill-hover: color-mix(in oklch, var(--fg) 5%, var(--surface));--fill-subtle: color-mix(in oklch, var(--fg) 6%, var(--surface));--fill-selected: color-mix(in oklch, var(--fg) 4%, var(--surface));--track: color-mix(in oklch, var(--fg) 7%, var(--surface));--avatar: oklch(88% .02 260);--accent: oklch(63% .22 32);--accent-soft: oklch(from var(--accent) l c h / .18);--accent-ring: oklch(from var(--accent) l c h / .45);--fx-ink: oklch(70% .13 250);--ok: oklch(52% .11 165);--ok-soft: oklch(52% .11 165 / .12);--warn: oklch(66% .13 70);--warn-soft: oklch(66% .13 70 / .14);--bad: oklch(55% .19 25);--bad-soft: oklch(55% .19 25 / .1);--disabled-bg: oklch(88% .015 260);--disabled-fg: oklch(58% .02 260);--font-display: "Delight", "Outfit", "DM Sans", system-ui, sans-serif;--font-body: "Delight", "Outfit", "DM Sans", system-ui, sans-serif;--font-mono: "DM Mono", ui-monospace, SFMono-Regular, Menlo, monospace;--fw-ui: 560;--fw-bold: 620;--fw-black: 700;--ls-display: -.04em;--ls-heading: -.03em;--ls-mono: .13em;--fs-display: 54px;--fs-h2: 28px;--fs-h3: 22px;--fs-h4: 18px;--fs-lead: 17px;--fs-body: 14.5px;--fs-small: 13.5px;--fs-caption: 12.5px;--fs-mono: 11.5px;--fs-micro: 10.5px;--lh-display: 1.04;--lh-heading: 1.15;--lh-body: 1.6;--radius-xl: 22px;--radius-lg: 20px;--radius-md: 16px;--radius-sm: 14px;--radius-control: 12px;--radius-nav: 11px;--radius-icon: 10px;--radius-chip: 999px;--radius-badge: 7px;--shadow-sm: 0 1px 2px oklch(20% .03 260 / .06);--shadow-md: 0 1px 2px oklch(20% .03 260 / .06), 0 18px 46px -22px oklch(20% .03 260 / .3);--shadow-control: 0 2px 6px oklch(20% .03 260 / .22);--shadow-composer: 0 0 0 3px var(--accent-soft), 0 1px 2px oklch(20% .03 260 / .06), 0 0 44px -8px oklch(63% .22 32 / .16), 0 20px 52px -20px oklch(63% .22 32 / .18);--blur-chrome: 14px;--ease: cubic-bezier(.2, 0, 0, 1);--ease-overshoot: cubic-bezier(.32, 1.38, .5, 1);--t-fast: .15s;--t-enter: .22s;--t-reveal: .5s;--t-progress: .7s;--t-ring: .9s;--t-morph: 1.12s;--touch: 44px;--control-h: 46px;--stage-w: 1920px;--stage-h: 1080px;--measure-prose: 62ch;--measure-lead: 68ch}:focus-visible{outline:2px solid var(--accent);outline-offset:2px}@media(prefers-reduced-motion:reduce){*,*:before,*:after{scroll-behavior:auto!important;transition-duration:.01ms!important;transition-delay:0ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important}}:where(button,[role=button],input,select,textarea,a){-webkit-tap-highlight-color:transparent}:where(button,[role=button],.control-button,.icon-button){min-height:44px;border-radius:var(--radius-md, 12px);transition:color var(--motion-fast, .16s) ease,background-color var(--motion-fast, .16s) ease,border-color var(--motion-fast, .16s) ease,box-shadow var(--motion-fast, .16s) ease,transform var(--motion-fast, .16s) ease,opacity var(--motion-fast, .16s) ease}:where(.icon-button,.modal-close,button:has(>svg:only-child)){min-width:44px;min-height:44px;display:inline-flex;align-items:center;justify-content:center}:where(button,[role=button],input,select,textarea,a[href]):focus-visible{outline:3px solid color-mix(in srgb,var(--accent, #3b82f6) 45%,transparent);outline-offset:2px}:where(button,[role=button]):active:not(:disabled){transform:scale(.98)}:where(button,[role=button]):disabled,:where(button,[role=button])[aria-disabled=true]{cursor:not-allowed;opacity:.5;box-shadow:none}:where(button,[role=button])[aria-busy=true]{cursor:progress;pointer-events:none}:where(button,[role=button])[aria-busy=true]:after{content:"";width:1em;height:1em;margin-inline-start:.55em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:shared-control-spin .7s linear infinite}:where(input,select,textarea,.control-field){min-height:44px;border:1px solid var(--border, #dfe3ea);border-radius:var(--radius-md, 12px);background:var(--surface-sunken, #f8fafc)}:where(.badge,.sb-section-badge,.results-file-count,.pm-popular-badge){display:inline-flex;align-items:center;border-radius:999px;font-weight:600}:where(.panel,.results-panel,.pm-card){border:1px solid var(--border, #dfe3ea);border-radius:var(--radius-lg, 16px);background:var(--surface, #fff)}.modal-overlay{overflow:auto;overscroll-behavior:contain;padding:max(16px,env(safe-area-inset-top)) max(16px,env(safe-area-inset-right)) max(16px,env(safe-area-inset-bottom)) max(16px,env(safe-area-inset-left))}.modal-overlay.open .modal-content{transform:scale(1) translateY(0)!important}.modal-overlay[aria-hidden=true]{pointer-events:none}.modal-overlay[aria-busy=true]{cursor:progress}.modal-content{width:min(100%,680px);max-height:calc(100dvh - 32px)!important;overflow:auto!important;overscroll-behavior:contain}.modal-content>:is(.border-t,.wt-footer){position:sticky;bottom:0;z-index:2;background:#fff}.modal-content>:is(.border-b,.pm-header){position:sticky;top:0;z-index:2;background:#fff}@media(max-width:480px),(max-height:600px){.modal-overlay{align-items:flex-start;padding:8px}.modal-content{max-height:calc(100dvh - 16px)!important;border-radius:14px}}@media(hover:hover){:where(button,[role=button]):hover:not(:disabled):not([aria-disabled=true]){filter:brightness(.97)}}@media(prefers-reduced-motion:reduce){*,*:before,*:after{scroll-behavior:auto!important;animation-duration:.01ms!important;transition-duration:.01ms!important}}@keyframes shared-control-spin{to{transform:rotate(360deg)}}.hero-field{position:absolute;inset:0;overflow:hidden;z-index:-2;pointer-events:none}.fx-grid{position:absolute;inset:0;width:100%;height:100%;display:block;z-index:-2;pointer-events:none;opacity:0;transition:opacity var(--t-reveal) var(--ease)}.fx-grid.is-ready{opacity:1}.fx-mask{position:absolute;z-index:-1;pointer-events:none;background:var(--bg);filter:blur(46px)}.fx-mask-hero{left:50%;top:50%;width:980px;height:520px;transform:translate(-50%,-54%)}.fx-mask-top{left:-48px;right:-48px;top:-48px;height:132px}.fx-mask-bottom{left:-48px;right:-48px;bottom:-48px;height:132px}@media(max-width:920px){.fx-mask{filter:blur(36px)}.fx-mask-hero{width:92%;height:62%;top:50%;transform:translate(-50%,-50%)}.fx-mask-top{height:104px}.fx-mask-bottom{height:124px}}@media(prefers-reduced-motion:reduce){.hero-field,.fx-grid,.fx-mask{display:none}}.pipeline-glyph.logo-loop{position:relative;width:100%;height:88px;margin:0 0 24px;overflow:hidden;pointer-events:none;color:var(--muted)}.loop-mark,.loop-shadow{position:absolute}.loop-mark{left:0;top:50%;width:52px;height:52px;margin:-26px 0 0;will-change:transform}.loop-piece{position:absolute;inset:0;display:block;will-change:transform,opacity}.loop-piece svg{display:block;width:100%;height:100%;overflow:visible}.loop-halo{position:absolute;left:50%;top:50%;width:74px;height:74px;margin:-37px 0 0 -37px;border-radius:50%;background:radial-gradient(circle,color-mix(in oklch,var(--accent) 60%,transparent),transparent 64%);filter:blur(5px);opacity:.09;will-change:transform,opacity}.loop-shadow{left:var(--mark-c, 26px);bottom:13px;width:46px;height:6px;margin-left:-23px;border-radius:50%;background:color-mix(in oklch,var(--fg) 26%,transparent);opacity:0;will-change:transform,opacity}@media(max-width:920px){.pipeline-glyph.logo-loop{height:66px;margin-bottom:16px}.loop-mark{width:40px;height:40px;margin:-20px 0 0}.loop-halo{width:58px;height:58px;margin:-29px 0 0 -29px}.loop-shadow{bottom:6px}}.shell-frame{display:flex;justify-content:center;align-items:flex-start;width:100%}.shell-stage{position:relative;flex:none;width:1920px;height:1080px;overflow:hidden;background:var(--bg);transform-origin:top center;transform:scale(var(--fit,1));margin-bottom:calc(1080px * (var(--fit,1) - 1));isolation:isolate}.shell-stage .topbar{position:absolute;inset:0 0 auto;height:88px;padding:0 40px;background:transparent;border:0}.shell-stage .brand{width:246px;max-width:calc(100% - 140px);min-height:44px}.shell-stage .brand-mark{display:block;width:100%;height:auto;overflow:visible}.shell-stage .topbar-account{gap:10px}.shell-stage .topbar{gap:0}.shell-stage .topbar-credits{height:32px;min-height:32px;padding:0 10px 0 8px;gap:5px}.shell-stage .topbar-credits{display:inline-flex}.shell-stage .topbar-plan{text-transform:uppercase}.shell-stage .topbar-plan{height:22px;min-height:22px;padding:0 8px;border-radius:6px;cursor:pointer}.shell-stage .topbar-avatar{width:32px;height:32px;min-height:32px;min-width:32px}.shell-stage .viewport{position:static;top:auto;min-height:0}.shell-stage .view-home{min-height:1080px;transform:none;transition:none}.shell-stage .hero-field{z-index:-1}.glow{position:absolute;left:50%;top:55%;width:1360px;height:760px;transform:translate(-50%,-50%);background:radial-gradient(ellipse at 28% 46%,oklch(from var(--bg) calc(l - .07) calc(c + .035) h / .42),transparent 62%),radial-gradient(ellipse at 72% 56%,oklch(from var(--accent) l c h / .09),transparent 58%);filter:blur(64px);pointer-events:none}.shell-stage .hero{position:absolute;left:50%;top:50%;transform:translate(-50%,-52%);width:1280px;padding:0;flex:none;z-index:1}.shell-stage #hero.is-exiting{display:flex!important;pointer-events:none}.shell-stage .headline{font-size:80px;line-height:1.05}.shell-stage .sub{margin-top:28px;font-size:20px}.shell-stage .composer{margin-top:46px;width:760px;height:148px;flex:none}.shell-stage .composer .field,.shell-stage .composer .ghost{left:23px;right:23px;top:19px;width:auto;height:58px;min-height:0;font-size:18px;line-height:1.5}.shell-stage .composer .field{overflow-y:auto;box-shadow:none}.shell-stage .composer .ghost .suggest{color:var(--muted)}.shell-stage .composer .tools{left:15px;bottom:12px}.shell-stage .icon-btn,.shell-stage .send{width:44px;height:44px;min-width:44px;min-height:44px}.shell-stage .send{right:15px;bottom:15px}.shell-stage .send:disabled{opacity:1}.shell-stage .composer .tab-hint{right:74px;bottom:13px;min-height:44px;margin:-4px -6px}.shell-stage .chips{max-width:none}.shell-stage .chip{min-height:44px;background:#ffffffb3}.composer.is-pointer-focus{outline:none}.composer.is-demo-streaming .ghost .typed:after{content:"";display:inline-block;width:2px;height:1.05em;margin-right:-2px;vertical-align:-.15em;background:var(--accent);box-shadow:0 0 7px 1px var(--accent-soft);animation:caret-blink 1.05s step-end infinite}#generation-stage{position:absolute;inset:164px auto auto 50%;width:1420px;transform:translate(-50%);padding:0;background:transparent;opacity:1;transition:none}#generation-stage.is-active,body.results-fullscreen #generation-stage{display:block}#generation-stage.is-active #main-stage-container{opacity:1;pointer-events:auto}#main-stage-container[data-morphing],#main-stage-container[data-morphing] *{visibility:hidden!important}#main-stage-container{position:relative;inset:auto;display:grid;grid-template-columns:310px minmax(0,1fr);width:100%;height:auto;min-height:590px;border:2px solid oklch(from var(--accent) l c h / .85);border-radius:20px;background:var(--surface);box-shadow:var(--shadow-composer);overflow:hidden}#main-stage{min-width:0;padding:0;display:grid;grid-template-columns:minmax(0,1fr);grid-template-areas:"stack";overflow:visible}#main-stage>*{grid-area:stack}#main-stage-container .pipeline-prompt-recap{grid-area:auto;padding:30px}#main-stage-container .pipeline-prompt-text{margin:12px 0 32px;font-size:17px;line-height:1.5}#pipeline-progress{grid-area:stack;height:auto;padding:0;overflow:visible;align-self:center}#pipeline-progress.visible{display:block}#pipeline-progress .pipeline-view{display:block;padding:48px 64px}#pipeline-stage-nav{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%)}#pipeline-stage-nav:focus-within,#pipeline-stage-nav.is-open{position:relative;width:auto;height:auto;margin:20px 0 0;clip-path:none}#progress-stage-count{position:relative;min-height:0;padding:0;border:0;border-radius:0;font:inherit;line-height:normal;color:inherit;background:none;text-align:left}#progress-stage-count:after{content:"";position:absolute;inset:-15px 0}#progress-elapsed{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}.composer-morph{background:var(--surface);border:2px solid oklch(from var(--accent) l c h / .85);border-radius:20px;box-shadow:var(--shadow-composer)}.panel-in{animation:fidelity-rise .5s var(--ease) both}@keyframes fidelity-rise{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}body.results-fullscreen #generation-stage{inset:104px 40px auto;width:auto;transform:none}body.results-fullscreen #main-stage-container{height:936px;min-height:0}body.results-fullscreen #main-stage{height:100%;min-height:0;grid-template-rows:1fr}body.results-fullscreen .pipeline-prompt-edit{margin-bottom:10px}#results-view{min-width:0;min-height:0;height:100%;padding:40px 48px;overflow:hidden}#results-view.visible{display:flex;flex-direction:column}#results-view .results-header{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%)}#bundle-strip{flex:none;gap:10px;margin:0 0 22px;padding:0 0 14px;border:0;border-bottom:1px solid var(--border);background:transparent;overflow-x:auto}#bundle-strip.visible{display:flex;align-items:center}#artifact-tabs{display:flex;gap:10px;flex:none;width:auto;padding:0}#bundle-strip .results-summary-tab{flex:none;min-height:38px;padding:0 13px;border-radius:9px;font:700 13px var(--font-display)}#bundle-strip .artifact-tab{min-width:172px;max-width:260px;padding:8px 11px;border-radius:9px;background:var(--surface)}#bundle-strip .artifact-tab-name{font:700 13px var(--font-display)}#bundle-strip .artifact-tab-meta{font:11px var(--font-mono);margin-top:3px}#bundle-strip .artifact-tab.active{border-color:var(--fg);box-shadow:inset 0 0 0 1px var(--fg)}#bundle-strip .artifact-tab-status.status-pass{color:var(--ok);background:var(--ok-soft)}#bundle-strip .artifact-tab-status.status-warning{color:var(--warn);background:var(--warn-soft)}#bundle-strip .artifact-tab-status.status-fail{color:var(--bad);background:var(--bad-soft)}#results-summary-detail{flex:1;min-height:0;max-height:none;padding:16px 4px;overflow:auto;border:0;background:transparent}#results-summary-detail .review-summary{display:flex;align-items:flex-start;justify-content:space-between;gap:32px;padding:0;border:0;background:none;box-shadow:none}#results-summary-detail .review-summary-copy{flex:1;min-width:0}.summary-heading{font:500 28px/1.2 var(--font-display);margin:0 0 16px;letter-spacing:normal}#results-summary-detail .review-summary-text{max-width:var(--measure-prose);font-size:14px;line-height:1.6;color:var(--muted)}.summary-spec{margin-top:24px;display:grid;gap:16px}.summary-spec>div{display:flex;gap:20px;justify-content:space-between;border-top:1px solid var(--border);padding-top:12px;font-size:14px}.summary-spec dt{color:var(--muted)}.summary-spec dd{text-align:right;overflow-wrap:anywhere}.summary-spec .summary-manual-callout{padding:0;margin:0;border:0;background:none;color:var(--fg);text-align:left}.summary-spec .summary-manual-callout ol{padding-left:1.4em;display:grid;gap:4px}.summary-spec .summary-manual-callout li{display:list-item;font-size:14px;font-weight:400}.summary-spec .summary-manual-callout li strong{font-weight:400}#results-summary-detail .review-score-column{width:184px;flex:none}#results-summary-detail .review-score{min-height:164px;padding:18px 16px;border-radius:12px;background:var(--surface-sunken)}#results-summary-detail .review-score strong{font:700 58px/.95 var(--font-display);margin-top:3px;letter-spacing:-.05em}#results-summary-detail .review-score-feedback{font-size:11px}#results-summary-detail .review-score-pass{color:var(--ok);border-color:var(--ok-soft)}#results-summary-detail .review-score-warning{color:var(--warn);border-color:var(--warn-soft)}#results-summary-detail .review-score-fail{color:var(--bad);border-color:var(--bad-soft)}#results-summary-detail .review-score-label{font:700 11px/1 var(--font-mono)}#results-summary-detail .review-score-status{font:800 11px/1 var(--font-mono);letter-spacing:.08em}#results-summary-detail .review-score-feedback{font-weight:600;color:var(--muted);line-height:normal}#results-summary-detail .feedback-btn{width:36px;height:36px;min-width:36px;min-height:36px;border-radius:8px}#results-summary-detail .feedback-btn svg{width:16px;height:16px}#results-view .flutterflow-deploy-icon{display:block;width:18px;height:18px;filter:none;mix-blend-mode:normal}#results-view .results-action-bar{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;flex:none;margin:20px 0 0;padding:12px 0 0;border-top:1px solid var(--border);background:transparent}#results-view .results-action{display:contents}#results-view .results-action-scope{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}#results-view .results-action-bar .btn-header-action{min-height:44px;padding:9px 16px;border:1px solid var(--border);border-radius:12px;font:600 12.5px var(--font-display);letter-spacing:-.01em;background:var(--surface);color:var(--fg);box-shadow:none}#results-view .results-action-bar .btn-deploy-results{background:var(--fg);color:var(--surface);border-color:var(--fg);box-shadow:0 2px 8px -2px oklch(from var(--accent) l c h / .4)}#results-view .results-action-bar .btn-error-regen{border-color:color-mix(in oklch,var(--warn) 45%,var(--surface));color:oklch(from var(--warn) 48% c h)}#artifact-results-split{flex:1;min-height:0;gap:22px;grid-template-columns:minmax(0,1.3fr) minmax(0,1fr)}#artifact-results-split .results-panel{min-width:0;min-height:0;border:1px solid var(--border);border-radius:14px;overflow:hidden}#artifact-results-split .panel-body{min-height:0;overflow:auto}#artifact-results-split .panel-code-wrap{height:100%;min-height:0;background:var(--surface-sunken)}#results-code-output{color:var(--fg);background:var(--surface-sunken);font:12px/1.8 var(--font-mono);white-space:pre-wrap;overflow-wrap:anywhere}#results-code-output .hljs-keyword,#results-code-output .hljs-meta{color:oklch(from var(--accent) 46% calc(c*.7) h)!important}#results-code-output .hljs-string{color:var(--fg)!important}#results-code-output .hljs-comment{color:var(--muted)!important;font-style:normal}#results-code-output .hljs-number,#results-code-output .hljs-type,#results-code-output .hljs-built_in,#results-code-output .hljs-title{color:oklch(from var(--fg) 45% c h)!important}.code-line{display:block;min-height:1.8em}.code-line.is-in{animation:code-land .52s var(--ease) both;animation-delay:var(--d)}@keyframes code-land{0%{opacity:0;transform:translateY(6px);background:var(--accent-soft)}42%{opacity:1;transform:translateY(0);background:var(--accent-soft)}to{opacity:1;transform:none;background:transparent}}body[data-shell-view=account] .shell-stage,body[data-shell-view=plans] .shell-stage{width:100%;height:auto;min-height:100vh;transform:none;margin:0;overflow:visible}body[data-shell-view=account] .viewport,body[data-shell-view=plans] .viewport{padding-top:88px}@media(max-width:920px){.shell-frame{display:block}.shell-stage{display:flex;flex-direction:column;width:100%;height:auto;min-height:100svh;transform:none;margin:0}.shell-stage .topbar{position:relative;flex:none;height:64px;padding:0 20px}.shell-stage .topbar-credits{height:30px;min-height:30px;padding:0 9px 0 7px;font-size:12px}.shell-stage .topbar-avatar{width:30px;height:30px;min-width:30px;min-height:30px}.shell-stage .viewport,.shell-stage .view-home{flex:1;display:flex;flex-direction:column;min-height:0}.shell-stage .hero{position:relative;left:auto;top:auto;transform:none;width:100%;padding:24px 20px 32px;flex:1}.shell-stage .headline{font-size:clamp(34px,6.8vw,56px);line-height:1.08;letter-spacing:-.03em;text-wrap:balance}.shell-stage .sub{margin-top:18px;font-size:16px;max-width:34ch}.shell-stage .composer{margin-top:32px;width:100%;max-width:520px;height:148px;border-radius:16px}.shell-stage .composer .field,.shell-stage .composer .ghost{left:18px;right:18px;top:16px;height:94px;font-size:16px;line-height:1.45}.shell-stage .composer .tools{left:10px;bottom:12px}.shell-stage .send{right:10px;bottom:10px}.shell-stage .composer .tab-hint{right:63px;bottom:12px}.shell-stage .chips{max-width:520px}.shell-stage .chips .chip{height:auto;padding-block:10px}.glow{width:140vw;height:60vh;top:48%;filter:blur(40px)}#generation-stage,body.results-fullscreen #generation-stage{position:relative;inset:auto;width:100%;transform:none;padding:28px 20px;flex:1}#main-stage-container,body.results-fullscreen #main-stage-container{grid-template-columns:minmax(0,1fr);min-height:0;height:auto;border-radius:18px}#main-stage-container .pipeline-prompt-recap{padding:22px;border-right:0;border-top:1px solid var(--border)}#main-stage-container .pipeline-prompt-text{margin:8px 0 20px;font-size:15px;max-height:100px}body.results-fullscreen .pipeline-prompt-edit{margin-bottom:0}#pipeline-progress .pipeline-view{padding:34px 24px;min-height:300px}#results-view{height:auto;padding:22px;overflow:visible}#results-summary-detail .review-summary{flex-direction:column;gap:22px}#results-summary-detail .review-score-column{width:100%}#results-summary-detail{overflow:visible}.summary-spec>div{flex-wrap:wrap;gap:6px}#results-view .results-action-bar,#artifact-results-split{grid-template-columns:1fr}#results-code-output{height:260px}body[data-shell-view=account] .viewport,body[data-shell-view=plans] .viewport{padding-top:0}}@media(prefers-reduced-motion:reduce){.panel-in,.code-line.is-in,.composer.is-demo-streaming .ghost .typed:after{animation:none}} diff --git a/dist/assets/index-CodKApzz.js b/dist/assets/index-CodKApzz.js deleted file mode 100644 index c3f64c6..0000000 --- a/dist/assets/index-CodKApzz.js +++ /dev/null @@ -1,320 +0,0 @@ -(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))r(n);new MutationObserver(n=>{for(const i of n)if(i.type==="childList")for(const o of i.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&r(o)}).observe(document,{childList:!0,subtree:!0});function s(n){const i={};return n.integrity&&(i.integrity=n.integrity),n.referrerPolicy&&(i.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?i.credentials="include":n.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function r(n){if(n.ep)return;n.ep=!0;const i=s(n);fetch(n.href,i)}})();var v=typeof window<"u"?window:void 0,we=typeof globalThis<"u"?globalThis:v,ke=we?.navigator,C=we?.document,re=we?.location,Mo=we?.fetch,$i=we!=null&&we.XMLHttpRequest&&"withCredentials"in new we.XMLHttpRequest?we.XMLHttpRequest:void 0,Ma=we?.AbortController,lh=we?.CompressionStream,Pe=ke?.userAgent;function kc(){return!(!v||v.navigator.onLine===!1)}var Cs=typeof globalThis<"u"?globalThis:v;Cs&&typeof self>"u"&&(Cs.self=Cs),Cs&&typeof File>"u"&&(Cs.File=function(){});var $=v??{},Y={DEBUG:!1,LIB_VERSION:"0.5.0",LIB_NAME:"browser-common"};function La(t,e,s,r,n,i,o){try{var a=t[i](o),l=a.value}catch(u){return void s(u)}a.done?e(l):Promise.resolve(l).then(r,n)}function X(t){return function(){var e=this,s=arguments;return new Promise((function(r,n){var i=t.apply(e,s);function o(l){La(i,r,n,o,a,"next",l)}function a(l){La(i,r,n,o,a,"throw",l)}o(void 0)}))}}function b(){return b=Object.assign?Object.assign.bind():function(t){for(var e=1;arguments.length>e;e++){var s=arguments[e];for(var r in s)({}).hasOwnProperty.call(s,r)&&(t[r]=s[r])}return t},b.apply(null,arguments)}function Ic(t,e){if(t==null)return{};var s={};for(var r in t)if({}.hasOwnProperty.call(t,r)){if(e.indexOf(r)!==-1)continue;s[r]=t[r]}return s}var Oa=t=>{if(typeof t!="string")return t;try{return JSON.parse(t)}catch{return t}};function Da(t){return typeof t=="string"||t}function Ba(t){return typeof t=="string"?t:void 0}var Fs,ch=["$feature_flag","$feature_flag_response","$feature_flag_has_experiment","$feature_flag_id","$feature_flag_version","$feature_flag_reason","$feature_flag_request_id","$feature_flag_evaluated_at","$feature_flag_error","locally_evaluated","$groups","$process_person_profile","$geoip_disable","$current_url","$pathname","$referring_domain","utm_source","utm_medium","utm_campaign","utm_content","utm_term","gad_source","mc_cid","gclid","gclsrc","dclid","gbraid","wbraid","fbclid","msclkid","twclid","li_fat_id","igshid","ttclid","rdt_cid","epik","qclid","sccid","irclid","_kx","$session_id","$window_id","$lib","$lib_version","$device_id","$is_server"],ut=(function(t){return t.AnonymousId="anonymous_id",t.DistinctId="distinct_id",t.Props="props",t.EnablePersonProcessing="enable_person_processing",t.PersonMode="person_mode",t.FeatureFlagDetails="feature_flag_details",t.FeatureFlags="feature_flags",t.FeatureFlagPayloads="feature_flag_payloads",t.BootstrapFeatureFlagDetails="bootstrap_feature_flag_details",t.BootstrapFeatureFlags="bootstrap_feature_flags",t.BootstrapFeatureFlagPayloads="bootstrap_feature_flag_payloads",t.OverrideFeatureFlags="override_feature_flags",t.Queue="queue",t.AiQueue="ai_queue",t.LogsQueue="logs_queue",t.OptedOut="opted_out",t.SessionId="session_id",t.SessionStartTimestamp="session_start_timestamp",t.SessionLastTimestamp="session_timestamp",t.PersonProperties="person_properties",t.GroupProperties="group_properties",t.InstalledAppBuild="installed_app_build",t.InstalledAppVersion="installed_app_version",t.SessionReplay="session_replay",t.PushRegistered="push_registered",t.SessionReplayEventTriggerActivatedSession="session_replay_event_trigger_activated_session",t.SurveyLastSeenDate="survey_last_seen_date",t.SurveysSeen="surveys_seen",t.Surveys="surveys",t.RemoteConfig="remote_config",t.FlagsEndpointWasHit="flags_endpoint_was_hit",t.DeviceId="device_id",t})({}),ja=(function(t){return t.GZipJS="gzip-js",t.Base64="base64",t})({}),uh=["$snapshot","$pageview","$pageleave","$set","survey dismissed","survey sent","survey shown","$identify","$groupidentify","$create_alias","$$client_ingestion_warning","$web_experiment_applied","$feature_enrollment_update","$feature_flag_called"],dh=["token"],Cc="NativeGzipValidationError",Ri=t=>t.length>=2&&t[0]===31&&t[1]===139,Ua=(t,e)=>t===ja.GZipJS||e===ja.GZipJS||e==="gzip",Ha=t=>!(!t||typeof t!="object")&&("name"in t?String(t.name):"")==="NotReadableError",yr=t=>{var e=new Error("Native gzip produced invalid output: "+t);throw e.name=Cc,e},hh=(function(){var t=X((function*(e,s){18>e.size&&yr("too-short");var r=new Uint8Array(yield e.slice(0,10).arrayBuffer());Ri(r)&&r[2]===8||yr("invalid-header");var n=new DataView(yield e.slice(e.size-8).arrayBuffer());n.getUint32(0,!0)!==(o=>{for(var a=(()=>{if(Fs)return Fs;Fs=[];for(var c=0;256>c;c++){for(var d=c,h=0;8>h;h++)d=1&d?3988292384^d>>>1:d>>>1;Fs[c]=d>>>0}return Fs})(),l=4294967295,u=0;o.length>u;u++)l=a[255&(l^o[u])]^l>>>8;return(4294967295^l)>>>0})(s)&&yr("invalid-crc");var i=s.length>>>0;n.getUint32(4,!0)!==i&&yr("invalid-size")}));return function(e,s){return t.apply(this,arguments)}})();function Ti(){return Ti=X((function*(t,e,s){e===void 0&&(e=!0);try{var r=new TextEncoder().encode(t),n=new globalThis.CompressionStream("gzip"),i=n.writable.getWriter(),o=i.write(r).then((()=>i.close())).catch((function(){var u=X((function*(c){try{yield i.abort(c)}catch{}throw c}));return function(c){return u.apply(this,arguments)}})()),a=new Response(n.readable).blob(),l=(yield Promise.all([a,o]))[0];return yield hh(l,r),l}catch(u){if(s!=null&&s.rethrow)throw u;return e&&console.error("Failed to gzip compress data",u),null}})),Ti.apply(this,arguments)}var ph=["amazonbot","amazonproductbot","app.hypefactors.com","applebot","archive.org_bot","awariobot","backlinksextendedbot","baiduspider","bingbot","bingpreview","chrome-lighthouse","dataforseobot","deepscan","duckduckbot","facebookexternal","facebookcatalog","http://yandex.com/bots","hubspot","ia_archiver","leikibot","linkedinbot","meta-externalagent","mj12bot","msnbot","nessus","petalbot","pinterest","prerender","rogerbot","screaming frog","sebot-wa","sitebulb","slackbot","slurp","trendictionbot","turnitin","twitterbot","vercel-screenshot","vercelbot","yahoo! slurp","yandexbot","zoombot","bot.htm","bot.php","(bot;","bot/","crawler","ahrefsbot","ahrefssiteaudit","semrushbot","siteauditbot","splitsignalbot","gptbot","oai-searchbot","chatgpt-user","perplexitybot","better uptime bot","sentryuptimebot","uptimerobot","headlesschrome","cypress","google-hoteladsverifier","adsbot-google","apis-google","duplexweb-google","feedfetcher-google","google favicon","google web preview","google-read-aloud","googlebot","googleother","google-cloudvertexbot","googleweblight","mediapartners-google","storebot-google","google-inspectiontool","bytespider"],Wa=function(t,e){if(e===void 0&&(e=[]),!t)return!1;var s=t.toLowerCase();return ph.concat(e).some((r=>{var n=r.toLowerCase();return s.indexOf(n)!==-1}))};function M(t,e){return t.indexOf(e)!==-1}var Pn=function(t){return t.trim()},Ni=function(t){return t.replace(/^\$/,"")};function Fc(t){var e,s=[];return(e=JSON.stringify(t,(function(r,n){if(typeof n=="bigint")return n.toString();if(typeof n!="function"&&typeof n!="symbol"){if(n instanceof Error)return{name:n.name,message:n.message,stack:n.stack};if(n&&typeof n=="object"){for(;s.length>0&&s[s.length-1]!==this;)s.pop();if(s.includes(n))return"[Circular]";s.push(n)}return n}})))!==null&&e!==void 0?e:"null"}var Pc=Object.prototype,Ac=Pc.hasOwnProperty,An=Pc.toString,L=Array.isArray||function(t){return An.call(t)==="[object Array]"},Se=t=>typeof t=="function",te=t=>t===Object(t)&&!L(t),mt=t=>{if(te(t)){for(var e in t)if(Ac.call(t,e))return!1;return!0}return!1},x=t=>t===void 0,W=t=>An.call(t)=="[object String]",Mi=t=>W(t)&&t.trim().length===0,$e=t=>t===null,D=t=>x(t)||$e(t),he=t=>An.call(t)=="[object Number]"&&t==t,lt=t=>he(t)&&t>0,Ke=t=>An.call(t)==="[object Boolean]",fh=t=>t instanceof FormData,gh=t=>M(uh,t),mh=t=>M(dh,t);function $c(t){return t===null||typeof t!="object"}function qr(t,e){return{}.toString.call(t)==="[object "+e+"]"}function Lo(t){return typeof Event<"u"&&Rc(t,Event)}function Rc(t,e){try{return t instanceof e}catch{return!1}}var vh=[!0,"true",1,"1","yes"],Zn=t=>M(vh,t),_h=[!1,"false",0,"0","no"];function rt(t,e,s,r,n){return e>s&&(r.warn("min cannot be greater than max."),e=s),he(t)?t>s?(r.warn(" cannot be greater than max: "+s+". Using max value instead."),s):e>t?(r.warn(" cannot be less than min: "+e+". Using min value instead."),e):t:(r.warn(" must be a number. using max or fallback. max: "+s+", fallback: "+n),rt(n||s,e,s,r))}class yh{constructor(e){this.tt={},this.et=e.et,this.it=rt(e.bucketSize,0,100,e.rt),this.nt=rt(e.refillRate,0,this.it,e.rt),this.st=rt(e.refillInterval,0,864e5,e.rt)}ot(e,s){var r=Math.floor((s-e.lastAccess)/this.st);r>0&&(e.tokens=Math.min(e.tokens+r*this.nt,this.it),e.lastAccess=e.lastAccess+r*this.st)}consumeRateLimit(e){var s,r=Date.now(),n=String(e),i=this.tt[n];return i?this.ot(i,r):this.tt[n]=i={tokens:this.it,lastAccess:r},i.tokens===0||(i.tokens--,i.tokens===0&&((s=this.et)==null||s.call(this,e)),i.tokens===0)}stop(){this.tt={}}}var Oe="Mobile",Vr="iOS",vt="Android",ps="Tablet",Tc=vt+" "+ps,Nc="iPad",Mc="Apple",Lc=Mc+" Watch",qs="Safari",fs="BlackBerry",Oc="Samsung",Dc=Oc+"Browser",Bc=Oc+" Internet",Vt="Chrome",wh=Vt+" OS",jc=Vt+" "+Vr,Oo="Internet Explorer",Uc=Oo+" "+Oe,Do="Opera",bh=Do+" Mini",Bo="Edge",Hc="Microsoft "+Bo,us="Firefox",Wc=us+" "+Vr,er="Nintendo",tr="PlayStation",ds="Xbox",zc=vt+" "+Oe,qc=Oe+" "+qs,Ds="Windows",Li=Ds+" Phone",za="Nokia",Oi="Ouya",Vc="Generic",Eh=Vc+" "+Oe.toLowerCase(),Gc=Vc+" "+ps.toLowerCase(),Di="Konqueror",Kc="Oculus Browser",Gr="Vivaldi",Jc="Yandex",Kr="Whale",Bi="DuckDuckGo",Yc="Pale Moon",Jr="Waterfox",Vs="Brave",Zc="Google Search App",le="(\\d+(\\.\\d+)?)",Xn=new RegExp("Version/"+le),Sh=new RegExp(ds,"i"),xh=new RegExp(tr+" \\w+","i"),kh=new RegExp(er+" \\w+","i"),jo=new RegExp(fs+"|PlayBook|BB10","i"),Ih={"NT3.51":"NT 3.11","NT4.0":"NT 4.0","5.0":"2000",5.1:"XP",5.2:"XP","6.0":"Vista",6.1:"7",6.2:"8",6.3:"8.1",6.4:"10","10.0":"10"},Xc=function(t,e,s,r){e=e||"";var n=(function(i){return i!=null&&i.brave?Vs:null})(s);return n||(r!=null&&r.detectGoogleSearchApp&&M(t,"GSA/")?Zc:M(t," OPR/")&&M(t,"Mini")?bh:M(t," OPR/")?Do:jo.test(t)?fs:M(t,"IE"+Oe)||M(t,"WPDesktop")?Uc:M(t,"OculusBrowser")?Kc:M(t,Dc)?Bc:M(t,Bo)||M(t,"Edg/")?Hc:M(t,Gr+"/")?Gr:M(t,"YaBrowser/")?Jc:M(t,Kr+"/")?Kr:M(t,Bi+"/")||M(t,"Ddg/")?Bi:M(t,"FBIOS")?"Facebook "+Oe:M(t,"UCWEB")||M(t,"UCBrowser")?"UC Browser":M(t,"CriOS")?jc:M(t,"CrMo")||M(t,Vt)?Vt:M(t,vt)&&M(t,qs)?zc:M(t,"FxiOS")?Wc:M(t.toLowerCase(),Di.toLowerCase())?Di:M(t,Vs+"/")?Vs:((i,o)=>o&&M(o,Mc)||(function(a){return M(a,qs)&&!M(a,Vt)&&!M(a,vt)})(i))(t,e)?M(t,Oe)?qc:qs:M(t,"PaleMoon/")?Yc:M(t,Jr+"/")?Jr:M(t,us)?us:M(t,"MSIE")||M(t,"Trident/")?Oo:M(t,"Gecko")?us:"")},Ch={[Uc]:[new RegExp("rv:"+le)],[Hc]:[new RegExp(Bo+"?\\/"+le)],[Vt]:[new RegExp("("+Vt+"|CrMo)\\/"+le)],[jc]:[new RegExp("CriOS\\/"+le)],"UC Browser":[new RegExp("(UCBrowser|UCWEB)\\/"+le)],[qs]:[Xn],[qc]:[Xn],[Do]:[new RegExp("(Opera|OPR)\\/"+le)],[us]:[new RegExp(us+"\\/"+le)],[Wc]:[new RegExp("FxiOS\\/"+le)],[Di]:[new RegExp("Konqueror[:/]?"+le,"i")],[fs]:[new RegExp(fs+" "+le),Xn],[zc]:[new RegExp("android\\s"+le,"i")],[Bc]:[new RegExp(Dc+"\\/"+le)],[Kc]:[new RegExp("OculusBrowser\\/"+le)],[Gr]:[new RegExp(Gr+"\\/"+le)],[Jc]:[new RegExp("YaBrowser\\/"+le)],[Kr]:[new RegExp(Kr+"\\/"+le)],[Vs]:[new RegExp(Vs+"\\/"+le)],[Bi]:[new RegExp("(DuckDuckGo|Ddg)\\/"+le)],[Yc]:[new RegExp("PaleMoon\\/"+le)],[Jr]:[new RegExp(Jr+"\\/"+le)],[Zc]:[new RegExp("GSA\\/"+le)],[Oo]:[new RegExp("(rv:|MSIE )"+le)],Mozilla:[new RegExp("rv:"+le)]},Fh=function(t,e,s,r){var n=Xc(t,e,s,r),i=Ch[n];if(x(i))return null;for(var o=0;i.length>o;o++){var a=t.match(i[o]);if(a)return parseFloat(a[a.length-2])}return null},qa=[[new RegExp(ds+"; "+ds+" (.*?)[);]","i"),t=>[ds,t&&t[1]||""]],[new RegExp(er,"i"),[er,""]],[new RegExp(tr,"i"),[tr,""]],[jo,[fs,""]],[new RegExp(Ds,"i"),(t,e)=>{if(/Phone/.test(e)||/WPDesktop/.test(e))return[Li,""];if(new RegExp(Oe).test(e)&&!/IEMobile\b/.test(e))return[Ds+" "+Oe,""];var s=/Windows NT ([0-9.]+)/i.exec(e);if(s&&s[1]){var r=Ih[s[1]]||"";return/arm/i.test(e)&&(r="RT"),[Ds,r]}return[Ds,""]}],[/((iPhone|iPad|iPod).*?OS (\d+)_(\d+)_?(\d+)?|iPhone)/,t=>t&&t[3]?[Vr,[t[3],t[4],t[5]||"0"].join(".")]:[Vr,""]],[/(watch.*\/(\d+\.\d+\.\d+)|watch os,(\d+\.\d+),)/i,t=>{var e="";return t&&t.length>=3&&(e=x(t[2])?t[3]:t[2]),["watchOS",e]}],[new RegExp("("+vt+" (\\d+)\\.(\\d+)\\.?(\\d+)?|"+vt+")","i"),t=>t&&t[2]?[vt,[t[2],t[3],t[4]||"0"].join(".")]:[vt,""]],[/Mac OS X (\d+)[_.](\d+)[_.]?(\d+)?/i,t=>{var e=["Mac OS X",""];return t&&t[1]&&(e[1]=[t[1],t[2],t[3]||"0"].join(".")),e}],[/Mac/i,["Mac OS X",""]],[/CrOS/,[wh,""]],[/Linux|debian/i,["Linux",""]]],Va=function(t){return kh.test(t)?er:xh.test(t)?tr:Sh.test(t)?ds:new RegExp(Oi,"i").test(t)?Oi:new RegExp("("+Li+"|WPDesktop)","i").test(t)?Li:/iPad/.test(t)?Nc:/iPod/.test(t)?"iPod Touch":/iPhone/.test(t)?"iPhone":/(watch)(?: ?os[,/]|\d,\d\/)[\d.]+/i.test(t)?Lc:jo.test(t)?fs:/(kobo)\s(ereader|touch)/i.test(t)?"Kobo":new RegExp(za,"i").test(t)?za:/(kf[a-z]{2}wi|aeo[c-r]{2})( bui|\))/i.test(t)||/(kf[a-z]+)( bui|\)).+silk\//i.test(t)?"Kindle Fire":/(Android|ZTE)/i.test(t)?new RegExp(Oe).test(t)&&!/(9138B|TB782B|Nexus [97]|pixel c|HUAWEISHT|BTV|noble nook|smart ultra 6)/i.test(t)||/pixel[\daxl ]{1,6}/i.test(t)&&!/pixel c/i.test(t)||/(huaweimed-al00|tah-|APA|SM-G92|i980|zte|U304AA)/i.test(t)||/lmy47v/i.test(t)&&!/QTAQZ3/i.test(t)?vt:Tc:new RegExp("(pda|"+Oe+")","i").test(t)?Eh:new RegExp(ps,"i").test(t)&&!new RegExp(ps+" pc","i").test(t)?Gc:""},Ph=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function Ga(t,e){return typeof(s=t)=="string"&&Ph.test(s)?t:e();var s}function Ct(t){return t&&t.split("#")[0]}function Uo(t,e){var s=setTimeout(t,e);return s?.unref&&s?.unref(),s}function Ka(t,e,s){return Qc.apply(this,arguments)}function Qc(){return(Qc=X((function*(t,e,s){var r;try{return yield Promise.race([t,new Promise(((n,i)=>{r=Uo((()=>{try{s?.(),n()}catch(o){i(o)}}),e)}))])}finally{clearTimeout(r)}}))).apply(this,arguments)}var Ah=t=>t instanceof Error,eu={trace:{text:"TRACE",number:1},debug:{text:"DEBUG",number:5},info:{text:"INFO",number:9},warn:{text:"WARN",number:13},error:{text:"ERROR",number:17},fatal:{text:"FATAL",number:21}},$h=eu.info;function tu(t){if(Ke(t))return{boolValue:t};if(typeof t=="number")return Number.isFinite(t)?Number.isInteger(t)?{intValue:t}:{doubleValue:t}:{stringValue:String(t)};if(typeof t=="string")return{stringValue:t};if(L(t))return{arrayValue:{values:t.map((e=>tu(e)))}};try{return{stringValue:JSON.stringify(t)}}catch{return{stringValue:String(t)}}}function Yr(t){var e=[];for(var s in t){var r=t[s];$e(r)||x(r)||e.push({key:s,value:tu(r)})}return e}function Rh(t,e){var s=eu[t.level||"info"]||$h,r=s.text,n=s.number,i=String(Date.now())+"000000",o={};e.distinctId&&(o.posthogDistinctId=e.distinctId),e.sessionId&&(o.sessionId=e.sessionId),e.windowId&&(o["window.id"]=e.windowId),D(e.sessionStartTimestamp)||(o.sessionStartTimestamp=String(e.sessionStartTimestamp)),D(e.lastActivityTimestamp)||(o.lastActivityTimestamp=String(e.lastActivityTimestamp)),e.currentUrl&&(o["url.full"]=e.currentUrl),e.screenName&&(o["screen.name"]=e.screenName),e.appState&&(o["app.state"]=e.appState),e.activeFeatureFlags&&e.activeFeatureFlags.length>0&&(o.feature_flags=e.activeFeatureFlags);var a=b({},o,t.attributes||{}),l={timeUnixNano:i,observedTimeUnixNano:i,severityNumber:n,severityText:r,body:{stringValue:t.body},attributes:Yr(a)};return t.trace_id&&(l.traceId=t.trace_id),t.span_id&&(l.spanId=t.span_id),x(t.trace_flags)||(l.flags=t.trace_flags),l}function su(t,e,s){return b({},t.resourceAttributes,{"service.name":t.serviceName||"unknown_service"},t.environment&&{"deployment.environment":t.environment},t.serviceVersion&&{"service.version":t.serviceVersion},{"telemetry.sdk.name":e,"telemetry.sdk.version":s})}function ru(t,e,s,r){return{resourceLogs:[{resource:{attributes:Yr(e)},scopeLogs:[{scope:{name:s,version:r},logRecords:t}]}]}}let Th=class{constructor(t,e,s,r,n,i,o){var a;i===void 0&&(i=()=>Promise.resolve()),this._instance=t,this.Ne=e,this.rt=s,this.ut=r,this.ht=n,this.dt=i,this.vt=o,this.ct=null,this.ft=0,this.yt=0,this.bt=0,this._t=0,this.wt=!1,this.kt=e.maxBufferSize,this.xt=Math.max((a=e.maxQueueSize)!==null&&a!==void 0?a:e.maxBufferSize,e.maxBufferSize),this.St=e.flushIntervalMs,this.Ct=e.maxBatchRecordsPerPost,this.Mt=e.rateCapWindowMs,this.Tt=e.maxLogsPerInterval}reset(){this.Et(),this.ct=null,this.bt=0,this._t=0,this.wt=!1,this.ft=0,this.yt=0,this.Ct=this.Ne.maxBatchRecordsPerPost}onReconnect(){this.yt=0,this.It()}captureLog(t){if(!this._instance.isDisabled&&!this._instance.optedOut&&t!=null&&t.body){var e=this.Pt(t);if(e!==null)if(e.body){if(this.Rt()){var s={record:Rh(e,this.ut())};this.ht((()=>this.At(s)))}}else this.rt.info("Log was rejected in beforeSend function")}}Pt(t){var e=this.Ne.beforeSend;if(!e)return t;var s=L(e)?e:[e],r=t;for(var n of s)try{var i=n(r);if(!i)return this.rt.info("Log was rejected in beforeSend function"),null;r=i}catch(o){return this.rt.error("Error in beforeSend function for log:",o),null}return r}Rt(){if(this.Tt===void 0)return!0;var t=Date.now(),e=t-this.bt;return this.Mt>e&&e>=0||(this.bt=t,this._t=0,this.wt=!1),this.Tt>this._t?(this._t++,!0):(this.wt||(this.rt.warn("captureLog dropping logs: exceeded "+this.Tt+" logs per "+this.Mt+"ms"),this.wt=!0),!1)}flush(){var t=this;return X((function*(){if(!t._instance.isDisabled)return t.ct||(t.ct=t.Ft().finally((()=>{t.ct=null}))),t.ct}))()}Ft(){var t=this;return X((function*(){var e;t.Et();var s=(e=t._instance.getPersistedProperty(ut.LogsQueue))!==null&&e!==void 0?e:[];if(s.length!==0)for(var r=s.length,n=0;s.length>0&&r>n;){var i,o;t.ft=0;var a=Math.min(s.length,t.Ct),l=s.slice(0,a),u=ru(l.map((d=>d.record)),t.Lt(),(i=t.vt)!==null&&i!==void 0?i:t._instance.getLibraryId(),t._instance.getLibraryVersion()),c=yield t._instance.Ot(u);if(c.kind==="too-large"&&l.length>1)t.Ct=Math.max(1,Math.floor(l.length/2)),t.rt.warn("Received 413 when sending logs batch of size "+l.length+", reducing batch size to "+t.Ct);else if(c.kind==="retry-later"||(c.kind==="too-large"?t.rt.warn("Dropping a single log record after 413 with batch size 1 — the record is larger than the server cap and cannot be split further."):c.kind==="ok"&&t.Ne.maxBatchRecordsPerPost>t.Ct&&(t.Ct=Math.min(t.Ne.maxBatchRecordsPerPost,t.Ct+1)),yield t.Dt(l.length),s=(o=t._instance.getPersistedProperty(ut.LogsQueue))!==null&&o!==void 0?o:[],n+=l.length,c.kind==="fatal"))throw c.error}}))()}Dt(t){var e=this;return X((function*(){var s,r=Math.max(0,t-e.ft),n=(s=e._instance.getPersistedProperty(ut.LogsQueue))!==null&&s!==void 0?s:[];e._instance.setPersistedProperty(ut.LogsQueue,n.slice(r)),yield e.dt()}))()}Lt(){return su(this.Ne,this._instance.getLibraryId(),this._instance.getLibraryVersion())}At(t){var e;if(!this._instance.optedOut){var s=(e=this._instance.getPersistedProperty(ut.LogsQueue))!==null&&e!==void 0?e:[];this.xt>s.length||(s.shift(),this.ft++,this.rt.info("Logs queue is full, dropping oldest record.")),s.push(t),this._instance.setPersistedProperty(ut.LogsQueue,s),this.kt>s.length?this.$t():this.It()}}$t(t){t===void 0&&(t=this.St),this.Nt||(this.Nt=Uo((()=>{this.Nt=void 0,this.It()}),t))}qt(){var t=Math.min(Math.max(0,this.yt-1),6);return this.St*Math.pow(2,t)}jt(){var t=this._instance.getPersistedProperty(ut.LogsQueue);return!!t&&t.length>0}shutdown(t){var e=this;return X((function*(){e.Et();var s=e.flush().catch((()=>{}));t!==void 0?yield Ka(s,t):yield s}))()}flushWithTimeout(t){var e=this;return X((function*(){var s=e.flush();yield Ka(s,t,(()=>{s.catch((()=>{}))}))}))()}It(){this.flush().then((()=>{this.yt=0}),(t=>{this.yt++,this.rt.error("PostHog logs flush failed:",t)})).finally((()=>{!this._instance.isDisabled&&this.jt()&&this.$t(this.qt())}))}Et(){this.Nt&&(clearTimeout(this.Nt),this.Nt=void 0)}};var Qn=[0,5,10,25,50,75,100,250,500,750,1e3,2500,5e3,7500,1e4];function Ja(t){return String(t)+"000000"}function Ya(t,e,s,r){var n="";return r&&(n=Object.keys(r).sort().map((i=>JSON.stringify(i)+":"+JSON.stringify(r[i]))).join(",")),t+"\0"+e+"\0"+(s??"")+"\0"+n}let Nh=class{constructor(t,e,s){this._instance=t,this.Ne=e,this.rt=s,this.Bt=new Map,this.ct=null,this.Ht=!1,this.Ut=new Map,this.zt=new Set,this.Wt=0}count(t,e,s){e===void 0&&(e=1),this.Vt({name:t,type:"count",value:e,unit:s?.unit,attributes:s?.attributes})}gauge(t,e,s){this.Vt({name:t,type:"gauge",value:e,unit:s?.unit,attributes:s?.attributes})}histogram(t,e,s){this.Vt({name:t,type:"histogram",value:e,unit:s?.unit,attributes:s?.attributes})}flush(){var t=this,e=this.ct,s=(function(){var n=X((function*(){e&&(yield e.catch((()=>{}))),yield t.Zt()}));return function(){return n.apply(this,arguments)}})(),r=s().finally((()=>{this.ct===r&&(this.ct=null)}));return this.ct=r,r}drainWindow(){if(this.Bt.size===0)return null;var t=this.Bt;return this.Bt=new Map,this.Ht=!1,this.Ut=new Map,this.zt=new Set,this.Gt(t)}reset(){this.Wt++,this.Et(),this.Bt=new Map,this.ct=null,this.Ht=!1,this.Ut=new Map,this.zt=new Set}Vt(t){if(!this._instance.isDisabled&&!this._instance.optedOut){var e=this.Pt(t);if(e!==null)if(e.name&&typeof e.name=="string")if(typeof e.value=="number"&&Number.isFinite(e.value))if(e.type==="count"&&0>e.value)this.rt.warn("Dropping count '"+e.name+"': counters are monotonic, value must be >= 0");else{var s,r;try{s=e.attributes?b({},e.attributes):void 0,r=Ya(e.type,e.name,e.unit,s)}catch(o){return void this.rt.warn("Dropping metric '"+e.name+"': attributes could not be serialized",o)}var n=this.Bt.get(r);if(!n){if(!this.Qt())return;n={name:e.name,type:e.type,unit:e.unit,attributes:s,windowStartMs:Date.now()},this.Bt.set(r,n)}var i=this.Ut.get(e.name);i===void 0?this.Ut.set(e.name,e.type):i===e.type||this.zt.has(e.name)||(this.zt.add(e.name),this.rt.warn("Metric name '"+e.name+"' is already used as a "+i+"; recording it as a "+e.type+" too will blend both series in charts. Use a distinct name.")),this.Kt(n,e.value),this.$t()}else this.rt.warn("Dropping metric '"+e.name+"': value must be a finite number");else this.rt.warn("Dropping metric with empty name")}}Qt(){return this.Ne.maxSeriesPerFlush>this.Bt.size||(this.Ht||(this.Ht=!0,this.rt.warn("Metric series cap reached ("+this.Ne.maxSeriesPerFlush+" per flush window); dropping new series until the next flush. Reduce attribute cardinality.")),!1)}Kt(t,e){var s;switch(t.type){case"count":t.total=((s=t.total)!==null&&s!==void 0?s:0)+e;break;case"gauge":t.last=e;break;case"histogram":t.hist||(t.hist={count:0,sum:0,min:e,max:e,bucketCounts:new Array(Qn.length+1).fill(0)});var r=t.hist;r.count+=1,r.sum+=e,r.min=Math.min(r.min,e),r.max=Math.max(r.max,e),r.bucketCounts[(function(n,i){for(var o=0;i.length>o;o++)if(i[o]>=n)return o;return i.length})(e,Qn)]+=1}}Pt(t){var e=this.Ne.beforeSend;if(!e)return t;var s=L(e)?e:[e],r=t;for(var n of s)try{var i=n(r);if(!i)return this.rt.info("Metric was rejected in beforeSend function"),null;r=i}catch(o){return this.rt.error("Error in beforeSend function for metric:",o),null}return r}$t(){this.Nt||(this.Nt=Uo((()=>{this.Nt=void 0,this.flush().catch((t=>{this.rt.error("Metrics flush failed:",t)}))}),this.Ne.flushIntervalMs))}Et(){this.Nt&&(clearTimeout(this.Nt),this.Nt=void 0)}Zt(){var t=this;return X((function*(){if(t.Bt.size!==0){var e=t.Bt;t.Bt=new Map,t.Ht=!1,t.Ut=new Map,t.zt=new Set;var s=t.Wt,r=yield t._instance.Jt(t.Gt(e));if(s===t.Wt)switch(r.kind){case"ok":return;case"retry-later":return t.Yt(e),void t.$t();case"too-large":return void t.rt.warn("Metrics batch exceeded the server size limit and was dropped");case"fatal":return void t.rt.error("Failed to send metrics batch:",r.error)}}}))()}Gt(t){return e=this.Xt(t),s=(function(i,o,a){return b({},i.resourceAttributes,{"service.name":i.serviceName||"unknown_service"},i.environment&&{"deployment.environment":i.environment},i.serviceVersion&&{"service.version":i.serviceVersion},{"telemetry.sdk.name":o,"telemetry.sdk.version":a})})(this.Ne,this._instance.getLibraryId(),this._instance.getLibraryVersion()),r=this._instance.getLibraryId(),n=this._instance.getLibraryVersion(),{resourceMetrics:[{resource:{attributes:Yr(s)},scopeMetrics:[{scope:{name:r,version:n},metrics:e}]}]};var e,s,r,n}Xt(t){var e=Ja(Date.now()),s=new Map;for(var r of t.values()){var n,i=Ya(r.type,r.name,r.unit,void 0),o=s.get(i);o||(o=b({name:r.name},r.unit&&{unit:r.unit}),r.type==="count"?o.sum={aggregationTemporality:1,isMonotonic:!0,dataPoints:[]}:r.type==="gauge"?o.gauge={dataPoints:[]}:o.histogram={aggregationTemporality:1,dataPoints:[]},s.set(i,o));var a=Yr((n=r.attributes)!==null&&n!==void 0?n:{}),l=Ja(r.windowStartMs);if(r.type==="count"){var u,c={attributes:a,startTimeUnixNano:l,timeUnixNano:e,asDouble:(u=r.total)!==null&&u!==void 0?u:0};o.sum.dataPoints.push(c)}else if(r.type==="gauge"){var d,h={attributes:a,timeUnixNano:e,asDouble:(d=r.last)!==null&&d!==void 0?d:0};o.gauge.dataPoints.push(h)}else r.hist&&o.histogram.dataPoints.push({attributes:a,startTimeUnixNano:l,timeUnixNano:e,count:r.hist.count,sum:r.hist.sum,min:r.hist.min,max:r.hist.max,bucketCounts:r.hist.bucketCounts,explicitBounds:Qn})}return Array.from(s.values())}Yt(t){var e,s;for(var r of t){var n=r[0],i=r[1],o=this.Bt.get(n);if(o)switch(o.windowStartMs=Math.min(o.windowStartMs,i.windowStartMs),o.type){case"count":o.total=((e=o.total)!==null&&e!==void 0?e:0)+((s=i.total)!==null&&s!==void 0?s:0);break;case"gauge":break;case"histogram":if(i.hist)if(o.hist){o.hist.count+=i.hist.count,o.hist.sum+=i.hist.sum,o.hist.min=Math.min(o.hist.min,i.hist.min),o.hist.max=Math.max(o.hist.max,i.hist.max);for(var a=0;o.hist.bucketCounts.length>a;a++)o.hist.bucketCounts[a]+=i.hist.bucketCounts[a]}else o.hist=i.hist}else this.Qt()&&this.Bt.set(n,i)}}};var wr,Za,ei;function Mh(t){var e=globalThis._posthogChunkIds;if(e){var s=Object.keys(e);return ei&&s.length===Za||(Za=s.length,ei=s.reduce(((r,n)=>{wr||(wr={});var i=wr[n];if(i)r[i[0]]=i[1];else for(var o=t(n),a=o.length-1;a>=0;a--){var l=o[a],u=l?.filename,c=e[n];if(u&&c){r[u]=c,wr[n]=[u,c];break}}return r}),{})),ei}}class Lh{constructor(e,s,r){r===void 0&&(r=[]),this.coercers=e,this.stackParser=s,this.modifiers=r}buildFromUnknown(e,s){s===void 0&&(s={});var r=s&&s.mechanism||{handled:!0,type:"generic"},n=this.buildCoercingContext(r,s,0).apply(e),i=this.buildParsingContext(s),o=this.parseStacktrace(n,i);return{$exception_list:this.convertToExceptionList(o,r),$exception_level:"error"}}modifyFrames(e){var s=this;return X((function*(){for(var r of e)r.stacktrace&&r.stacktrace.frames&&L(r.stacktrace.frames)&&(r.stacktrace.frames=yield s.applyModifiers(r.stacktrace.frames));return e}))()}coerceFallback(e){var s;return{type:"Error",value:"Unknown error",stack:(s=e.syntheticException)==null?void 0:s.stack,synthetic:!0}}parseStacktrace(e,s){var r,n;return e.cause!=null&&(r=this.parseStacktrace(e.cause,s)),e.stack!=""&&e.stack!=null&&(n=this.applyChunkIds(this.stackParser(e.stack,e.synthetic?s.skipFirstLines:0),s.chunkIdMap)),b({},e,{cause:r,stack:n})}applyChunkIds(e,s){return e.map((r=>(r.filename&&s&&(r.chunk_id=s[r.filename]),r)))}applyCoercers(e,s){for(var r of this.coercers)if(r.match(e))return r.coerce(e,s);return this.coerceFallback(s)}applyModifiers(e){var s=this;return X((function*(){var r=e;for(var n of s.modifiers)r=yield n(r);return r}))()}convertToExceptionList(e,s){var r,n,i,o={type:e.type,value:e.value,mechanism:{type:(r=s.type)!==null&&r!==void 0?r:"generic",handled:(n=s.handled)===null||n===void 0||n,synthetic:(i=e.synthetic)!==null&&i!==void 0&&i}};e.stack&&(o.stacktrace={type:"raw",frames:e.stack});var a=[o];return e.cause!=null&&a.push(...this.convertToExceptionList(e.cause,b({},s,{handled:!0}))),a}buildParsingContext(e){var s;return{chunkIdMap:Mh(this.stackParser),skipFirstLines:(s=e.skipFirstLines)!==null&&s!==void 0?s:1}}buildCoercingContext(e,s,r){r===void 0&&(r=0);var n=(i,o)=>{if(4>=o){var a=this.buildCoercingContext(e,s,o);return this.applyCoercers(i,a)}};return b({},s,{syntheticException:r==0?s.syntheticException:void 0,mechanism:e,apply:i=>n(i,r),next:i=>n(i,r+1)})}}var gs="?";function ji(t,e,s,r,n){var i={platform:t,filename:e,function:s===""?gs:s,in_app:!0};return x(r)||(i.lineno=r),x(n)||(i.colno=n),i}var nu=(t,e)=>{var s=t.indexOf("safari-extension")!==-1,r=t.indexOf("safari-web-extension")!==-1;return s||r?[t.indexOf("@")!==-1?t.split("@")[0]:gs,s?"safari-extension:"+e:"safari-web-extension:"+e]:[t,e]},Oh=/^\s*at (\S+?)(?::(\d+))(?::(\d+))\s*$/i,Dh=/^\s*at (?:(.+?\)(?: \[.+\])?|.*?) ?\((?:address at )?)?(?:async )?((?:|[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,Bh=/\((\S*)(?::(\d+))(?::(\d+))\)/,jh=(t,e)=>{var s=Oh.exec(t);if(s)return ji(e,s[1],gs,+s[2],+s[3]);var r=Dh.exec(t);if(r){if(r[2]&&r[2].indexOf("eval")===0){var n=Bh.exec(r[2]);n&&(r[2]=n[1],r[3]=n[2],r[4]=n[3])}var i=nu(r[1]||gs,r[2]);return ji(e,i[1],i[0],r[3]?+r[3]:void 0,r[4]?+r[4]:void 0)}},Uh=/^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:[-a-z]+)?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js)|\/[\w\-. /=]+)(?::(\d+))?(?::(\d+))?\s*$/i,Hh=/(\S+) line (\d+)(?: > eval line \d+)* > eval/i,Wh=(t,e)=>{var s=Uh.exec(t);if(s){if(s[3]&&s[3].indexOf(" > eval")>-1){var r=Hh.exec(s[3]);r&&(s[1]=s[1]||"eval",s[3]=r[1],s[4]=r[2],s[5]="")}var n=s[3],i=s[1]||gs,o=nu(i,n);return ji(e,n=o[1],i=o[0],s[4]?+s[4]:void 0,s[5]?+s[5]:void 0)}},Xa=/\(error: (.*)\)/;class zh{match(e){return this.isDOMException(e)||this.isDOMError(e)}coerce(e,s){var r=W(e.stack);return{type:this.getType(e),value:this.getValue(e),stack:r?e.stack:void 0,cause:e.cause?s.next(e.cause):void 0,synthetic:!1}}getType(e){return this.isDOMError(e)?"DOMError":"DOMException"}getValue(e){var s=e.name||(this.isDOMError(e)?"DOMError":"DOMException");return e.message?s+": "+e.message:s}isDOMException(e){return qr(e,"DOMException")}isDOMError(e){return qr(e,"DOMError")}}class qh{match(e){return(function(s){switch({}.toString.call(s)){case"[object Error]":case"[object Exception]":case"[object DOMException]":case"[object DOMError]":case"[object WebAssembly.Exception]":return!0;default:return Rc(s,Error)}})(e)}coerce(e,s){return{type:this.getType(e),value:this.getMessage(e,s),stack:this.getStack(e),cause:e.cause?s.next(e.cause):void 0,synthetic:!1}}getType(e){return e.name||e.constructor.name}getMessage(e,s){var r=e.message;return String(r.error&&typeof r.error.message=="string"?r.error.message:r)}getStack(e){return e.stacktrace||e.stack||void 0}}class Vh{constructor(){}match(e){return!!qr(e,"ErrorEvent")&&(e.error!=null||this.fe(e))}coerce(e,s){var r;if(e.error!=null)return s.apply(e.error);var n=s.apply(e.message);return b({},n,{stack:(r=this.pe(e))!==null&&r!==void 0?r:n.stack,synthetic:!0})}fe(e){return W(e.message)&&e.message.length>0}pe(e){var s=e;if(W(s.filename)&&s.filename.length>0){var r,n,i=(r=s.lineno)!==null&&r!==void 0?r:0,o=(n=s.colno)!==null&&n!==void 0?n:0;return`Error - at `+s.filename+":"+i+":"+o}}}var Gh=/^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/i;class Kh{match(e){return typeof e=="string"}coerce(e,s){var r,n=this.getInfos(e),i=n[0],o=n[1];return{type:i??"Error",value:o??e,stack:(r=s.syntheticException)==null?void 0:r.stack,synthetic:!0}}getInfos(e){var s="Error",r=e,n=e.match(Gh);return n&&(s=n[1],r=n[2]),[s,r]}}var Jh=["fatal","error","warning","log","info","debug"];function iu(t,e){e===void 0&&(e=40);var s=Object.keys(t);if(s.sort(),!s.length)return"[object has no keys]";for(var r=s.length;r>0;r--){var n=s.slice(0,r).join(", ");if(e>=n.length)return r===s.length?n:n.length>e?n.slice(0,e)+"...":n}return""}class Yh{match(e){return typeof e=="object"&&e!==null}coerce(e,s){var r,n,i=this.getErrorPropertyFromObject(e);return i?s.apply(i):{type:this.getType(e),value:this.getValue(e),stack:(r=this.getStack(e))!==null&&r!==void 0?r:(n=s.syntheticException)==null?void 0:n.stack,level:this.isSeverityLevel(e.level)?e.level:"error",synthetic:!0}}getType(e){return Lo(e)?e.constructor.name:"Error"}getValue(e){if("name"in e&&typeof e.name=="string"){var s="'"+e.name+"' captured as exception";return"message"in e&&typeof e.message=="string"&&(s+=" with message: '"+e.message+"'"),s}if("message"in e&&typeof e.message=="string")return e.message;var r=this.getObjectClassName(e);return(r&&r!=="Object"?"'"+r+"'":"Object")+" captured as exception with keys: "+iu(e)}isSeverityLevel(e){return W(e)&&!Mi(e)&&Jh.indexOf(e)>=0}getStack(e){try{return W(e.stacktrace)&&e.stacktrace.length>0?e.stacktrace:W(e.stack)&&e.stack.length>0?e.stack:void 0}catch{return}}getErrorPropertyFromObject(e){for(var s in e)if({}.hasOwnProperty.call(e,s)){var r=e[s];if(Ah(r))return r}}getObjectClassName(e){try{var s=Object.getPrototypeOf(e);return s?s.constructor.name:void 0}catch{return}}}class Zh{match(e){return Lo(e)}coerce(e,s){var r,n=e.constructor.name;return{type:n,value:n+" captured as exception with keys: "+iu(e),stack:(r=s.syntheticException)==null?void 0:r.stack,synthetic:!0}}}class Xh{match(e){return $c(e)}coerce(e,s){var r;return{type:"Error",value:"Primitive value captured as exception: "+String(e),stack:(r=s.syntheticException)==null?void 0:r.stack,synthetic:!0}}}class Qh{match(e){return qr(e,"PromiseRejectionEvent")||this.isCustomEventWrappingRejection(e)}isCustomEventWrappingRejection(e){if(!Lo(e))return!1;try{var s=e.detail;return s!=null&&typeof s=="object"&&"reason"in s}catch{return!1}}coerce(e,s){var r,n=this.getUnhandledRejectionReason(e);return $c(n)?{type:"UnhandledRejection",value:"Non-Error promise rejection captured with value: "+String(n),stack:(r=s.syntheticException)==null?void 0:r.stack,synthetic:!0}:s.apply(n)}getUnhandledRejectionReason(e){try{if("reason"in e)return e.reason;if("detail"in e&&e.detail!=null&&typeof e.detail=="object"&&"reason"in e.detail)return e.detail.reason}catch{}return e}}var Zr="$message",Xr="$timestamp",ep=new Set([Zr,Xr]),ti={enabled:!0,max_bytes:32768};function Qr(t){var e;return t?{enabled:(e=t.enabled)!==null&&e!==void 0?e:ti.enabled,max_bytes:sp(t.max_bytes,ti.max_bytes)}:b({},ti)}class tp{constructor(e){this.Ke=[],this.Je=0,this.Ne=Qr(e)}setConfig(e){this.Ne=Qr(e),this.Xe()}add(e){var s=(function(n){var i;try{i=Fc(n)}catch{return}try{var o=JSON.parse(i);if(!te(o))return;var a=o,l=a[Zr],u=a[Xr];return!W(l)||l.trim().length===0||!W(u)&&!he(u)?void 0:{step:a,json:i}}catch{return}})(e);if(s){var r=(function(n){if(typeof TextEncoder<"u")return new TextEncoder().encode(n).length;for(var i=encodeURIComponent(n),o=0,a=0;i.length>a;a++)i[a]==="%"?(o+=1,a+=2):o+=1;return o})(s.json);r>this.Ne.max_bytes||(this.Ke.push({step:s.step,bytes:r}),this.Je+=r,this.Xe())}}getAttachable(){return this.Ke.map((e=>e.step))}clear(){this.Ke=[],this.Je=0}size(){return this.Ke.length}Xe(){for(;this.Je>this.Ne.max_bytes&&this.Ke.length>0;){var e=this.Ke.shift();e&&(this.Je-=e.bytes)}}}function sp(t,e){if(!he(t)||t===1/0||t===-1/0)return e;var s=Math.floor(t);return 0>s?e:s}var ou=function(t,e){var s=(e===void 0?{}:e).debugEnabled,r={k(n){if(v&&(Y.DEBUG||v.POSTHOG_DEBUG||s)&&!x(v.console)&&v.console){for(var i=("__rrweb_original__"in v.console[n])?v.console[n].__rrweb_original__:v.console[n],o=arguments.length,a=new Array(o>1?o-1:0),l=1;o>l;l++)a[l-1]=arguments[l];i(t,...a)}},debug(){for(var n=arguments.length,i=new Array(n),o=0;n>o;o++)i[o]=arguments[o];r.k("debug",...i)},info(){for(var n=arguments.length,i=new Array(n),o=0;n>o;o++)i[o]=arguments[o];r.k("log",...i)},warn(){for(var n=arguments.length,i=new Array(n),o=0;n>o;o++)i[o]=arguments[o];r.k("warn",...i)},error(){for(var n=arguments.length,i=new Array(n),o=0;n>o;o++)i[o]=arguments[o];r.k("error",...i)},critical(){for(var n=arguments.length,i=new Array(n),o=0;n>o;o++)i[o]=arguments[o];console.error(t,...i)},uninitializedWarning(n){r.error("You must initialize PostHog before calling "+n)},createLogger:(n,i)=>ou(t+" "+n,i)};return r},k=ou("[PostHog.js]"),se=k.createLogger,rp=se("[ExternalScriptsLoader]"),si=(t,e,s)=>{if(t.config.disable_external_dependency_loading)return rp.warn(e+" was requested but loading of external scripts is disabled."),s("Loading of external scripts is disabled");var r=C?.querySelectorAll("script");if(r){for(var n,i=function(){if(r[o].src===e){var l=r[o];return l.__posthog_loading_callback_fired?{v:s()}:(l.addEventListener("load",(u=>{l.__posthog_loading_callback_fired=!0,s(void 0,u)})),l.onerror=u=>s(u),{v:void 0})}},o=0;r.length>o;o++)if(n=i())return n.v}var a=()=>{if(!C)return s("document not found");var l=C.createElement("script");if(l.type="text/javascript",l.crossOrigin="anonymous",l.src=e,l.onload=d=>{l.__posthog_loading_callback_fired=!0,s(void 0,d)},l.onerror=d=>s(d),t.config.prepare_external_dependency_script&&(l=t.config.prepare_external_dependency_script(l)),!l)return s("prepare_external_dependency_script returned null");if(t.config.external_scripts_inject_target==="head")C.head.appendChild(l);else{var u,c=C.querySelectorAll("body > script");c.length>0?(u=c[0].parentNode)==null||u.insertBefore(l,c[0]):C.body.appendChild(l)}};C!=null&&C.body?a():C?.addEventListener("DOMContentLoaded",a)};$.__PosthogExtensions__=$.__PosthogExtensions__||{},$.__PosthogExtensions__.loadExternalDependency=(t,e,s)=>{if(e!=="remote-config"){var r;if(t.config.strict_script_versioning)r=t.requestRouter.endpointFor("assets","/static/"+t.version+"/"+e+".js");else{var n="/static/"+e+".js?v="+t.version;if(e==="toolbar"){var i=3e5;n=n+"&t="+Math.floor(Date.now()/i)*i}r=t.requestRouter.endpointFor("assets",n)}si(t,r,s)}else{var o=t.requestRouter.endpointFor("assets","/array/"+t.config.token+"/config.js");si(t,o,s)}},$.__PosthogExtensions__.loadSiteApp=(t,e,s)=>{var r=t.requestRouter.endpointFor("api",e);si(t,r,s)};Y.DEBUG=!1,Y.LIB_VERSION="1.415.7",Y.LIB_NAME="web";var au="$people_distinct_id",sr="$device_id",ri="$device_model",Bs="__alias",js="__timers",Ui="$autocapture_disabled_server_side",Hi="$heatmaps_enabled_server_side",Wi="$exception_capture_enabled_server_side",zi="$error_tracking_suppression_rules",qi="$error_tracking_capture_extension_exceptions",Vi="$web_vitals_enabled_server_side",Ho="$dead_clicks_enabled_server_side",Wo="$product_tours_enabled_server_side",Gi="$web_vitals_allowed_metrics",qt="$session_recording_remote_config",lu="$replay_sample_rate",cu="$replay_override_sampling",uu="$replay_override_linked_flag",du="$replay_override_url_trigger",hu="$replay_override_event_trigger",ls="$sesid",zo="$session_is_sampled",Bt="$enabled_feature_flags",Us="$active_feature_flags",Rr="$early_access_features",Ki="$feature_flag_details",Hs="$feature_flag_payloads",Tr="$feature_flag_request_id",en="$minimal_flag_called_events",et="$override_feature_flags",jt="$override_feature_flag_payloads",ct="$stored_person_properties",Ut="$stored_group_properties",Ji="$surveys",tn="$surveys_loaded_at",Yi="$surveys_activated",Nr="$surveys_activated_session",Mr="$surveys_activated_timestamps",Ws="ph_product_tours",Wt="$flag_call_reported",zs="$flag_call_reported_session_id",Lr="$feature_flag_errors",Gs="$feature_flag_evaluated_at",He="$user_state",Zi="$client_session_props",Xi="$capture_rate_limit",Qi="$initial_campaign_params",eo="$initial_referrer_info",sn="$initial_person_info",rn="$epp",br="$posthog_cookieless",pu="$cookieless_mode",fu="$sdk_debug_extensions_init_method",gu="$sdk_debug_extensions_init_time_ms",mu="$sdk_debug_recording_script_not_loaded",qo="PostHog loadExternalDependency extension not found.",Ht="on_reject",ht="always",es="anonymous",Tt="identified",to="identified_only",nn="visibilitychange",on="beforeunload",is="$pageview",ni="$pageleave",ii="$identify",Qa="$groupidentify";function Er(t,e){L(t)&&t.forEach(e)}function Z(t,e){if(!D(t))if(L(t))t.forEach(e);else if(fh(t))t.forEach(((r,n)=>e(r,n)));else for(var s in t)Ac.call(t,s)&&e(t[s],s)}var ee=function(t){for(var e=arguments.length,s=new Array(e>1?e-1:0),r=1;e>r;r++)s[r-1]=arguments[r];for(var n of s)for(var i in n)n[i]!==void 0&&(t[i]=n[i]);return t};function Or(t){for(var e=Object.keys(t),s=e.length,r=new Array(s);s--;)r[s]=[e[s],t[e[s]]];return r}var el=function(t){try{return t()}catch{return}},np=function(t){return function(){try{for(var e=arguments.length,s=new Array(e),r=0;e>r;r++)s[r]=arguments[r];return t.apply(this,s)}catch(n){k.critical("Implementation error. Please turn on debug mode and open a ticket on https://app.posthog.com/home#panel=support%3Asupport%3A."),k.critical(n)}}},Vo=function(t){var e={};return Z(t,(function(s,r){(W(s)&&s.length>0||he(s))&&(e[r]=s)})),e},ip=["herokuapp.com","vercel.app","netlify.app"];function op(t){var e=t?.hostname;if(!W(e))return!1;var s=e.split(".").slice(-2).join(".");for(var r of ip)if(s===r)return!1;return!0}function ne(t,e,s,r){var n=r??{},i=n.capture,o=n.passive;t?.addEventListener(e,s,{capture:i!==void 0&&i,passive:o===void 0||o})}function so(t){return t.name==="ph_toolbar_internal"}var vu=t=>{if(C){try{for(var e=t+"=",s=C.cookie.split(";").filter((i=>i.length)),r=0;s.length>r;r++){for(var n=s[r];n.charAt(0)==" ";)n=n.substring(1,n.length);if(n.indexOf(e)===0)return decodeURIComponent(n.substring(e.length,n.length))}}catch{}return null}};Math.trunc||(Math.trunc=function(t){return 0>t?Math.ceil(t):Math.floor(t)}),Number.isInteger||(Number.isInteger=function(t){return he(t)&&isFinite(t)&&Math.floor(t)===t});class an{constructor(e){if(this.bytes=e,e.length!==16)throw new TypeError("not 128-bit length")}static fromFieldsV7(e,s,r,n){if(!Number.isInteger(e)||!Number.isInteger(s)||!Number.isInteger(r)||!Number.isInteger(n)||0>e||0>s||0>r||0>n||e>0xffffffffffff||s>4095||r>1073741823||n>4294967295)throw new RangeError("invalid field value");var i=new Uint8Array(16);return i[0]=e/Math.pow(2,40),i[1]=e/Math.pow(2,32),i[2]=e/Math.pow(2,24),i[3]=e/Math.pow(2,16),i[4]=e/256,i[5]=e,i[6]=112|s>>>8,i[7]=s,i[8]=128|r>>>24,i[9]=r>>>16,i[10]=r>>>8,i[11]=r,i[12]=n>>>24,i[13]=n>>>16,i[14]=n>>>8,i[15]=n,new an(i)}toString(){for(var e="",s=0;this.bytes.length>s;s++)e=e+(this.bytes[s]>>>4).toString(16)+(15&this.bytes[s]).toString(16),s!==3&&s!==5&&s!==7&&s!==9||(e+="-");if(e.length!==36)throw new Error("Invalid UUIDv7 was generated");return e}clone(){return new an(this.bytes.slice(0))}equals(e){return this.compareTo(e)===0}compareTo(e){for(var s=0;16>s;s++){var r=this.bytes[s]-e.bytes[s];if(r!==0)return Math.sign(r)}return 0}}class ap{generate(){var e=this.generateOrAbort();if(!x(e))return e;this.S=0;var s=this.generateOrAbort();if(x(s))throw new Error("Could not generate UUID after timestamp reset");return s}generateOrAbort(){var e=Date.now();if(e>this.S)this.S=e,this.C();else{if(this.S>=e+1e4)return;this.I++,this.I>4398046511103&&(this.S++,this.C())}return an.fromFieldsV7(this.S,Math.trunc(this.I/Math.pow(2,30)),this.I&Math.pow(2,30)-1,this.A.nextUint32())}C(){this.I=1024*this.A.nextUint32()+(1023&this.A.nextUint32())}constructor(){this.S=0,this.I=0,this.A=new lp}}var tl,_u=t=>{if(typeof UUIDV7_DENY_WEAK_RNG<"u"&&UUIDV7_DENY_WEAK_RNG)throw new Error("no cryptographically strong RNG available");for(var e=0;t.length>e;e++)t[e]=65536*Math.trunc(65536*Math.random())+Math.trunc(65536*Math.random());return t};v&&!x(v.crypto)&&crypto.getRandomValues&&(_u=t=>crypto.getRandomValues(t));class lp{nextUint32(){return this.R.length>this.O||(_u(this.R),this.O=0),this.R[this.O++]}constructor(){this.R=new Uint32Array(8),this.O=1/0}}var dt=()=>cp().toString(),cp=()=>(tl||(tl=new ap)).generate(),Ps="",up=/[a-z0-9][a-z0-9-]+\.[a-z]{2,}$/i,pt={N:()=>!!C,j(t){k.error("cookieStore error: "+t)},P:vu,H(t){var e;try{e=JSON.parse(pt.P(t))||{}}catch{}return e},F(t,e,s,r,n){if(!C)return!1;try{var i="",o="",a=(function(c,d){if(d){var h=(function(f,g){if(g===void 0&&(g=C),Ps)return Ps;if(!g||["localhost","127.0.0.1"].includes(f))return"";for(var m=f.split("."),_=Math.min(m.length,8),w="dmn_chk_"+dt();!Ps&&_--;){var E=m.slice(_).join("."),I=w+"=1;domain=."+E+";path=/";g.cookie=I+";max-age=3",g.cookie.includes(w)&&(g.cookie=I+";max-age=0",Ps=E)}return Ps})(c);if(!h){var p=(f=>{var g=f.match(up);return g?g[0]:""})(c);p!==h&&k.info("Warning: cookie subdomain discovery mismatch",p,h),h=p}return h?"; domain=."+h:""}return""})(C.location.hostname,r);if(s){var l=new Date;l.setTime(l.getTime()+864e5*s),i="; expires="+l.toUTCString()}n&&(o="; secure");var u=t+"="+encodeURIComponent(JSON.stringify(e))+i+"; SameSite=Lax; path=/"+a+o;return u.length>3686.4&&k.warn("cookieStore warning: large cookie, len="+u.length),C.cookie=u,!0}catch{return!1}},q(t,e){if(C!=null&&C.cookie)try{pt.F(t,"",-1,e)}catch{return}}},oi=null,Q={N(){if(!$e(oi))return oi;var t=!0;if(x(v))t=!1;else try{var e="__mplssupport__";Q.F(e,"xyz"),Q.P(e)!=='"xyz"'&&(t=!1),Q.q(e)}catch{t=!1}return t||k.error("localStorage unsupported; falling back to cookie store"),oi=t,t},j(t){k.error("localStorage error: "+t)},P(t){try{return v?.localStorage.getItem(t)}catch(e){Q.j(e)}return null},H(t){try{return JSON.parse(Q.P(t))||{}}catch{}return null},F(t,e){try{return v?.localStorage.setItem(t,JSON.stringify(e)),!0}catch(s){Q.j(s)}return!1},q(t){try{v?.localStorage.removeItem(t)}catch(e){Q.j(e)}}},dp=[sr,"distinct_id",ls,zo,rn,sn,He],Sr={},hp={N:()=>!0,j(t){k.error("memoryStorage error: "+t)},P:t=>Sr[t]||null,H:t=>Sr[t]||null,F:(t,e)=>(Sr[t]=e,!0),q(t){delete Sr[t]}},Nt=null,ce={N(){if(!$e(Nt))return Nt;if(Nt=!0,x(v))Nt=!1;else try{var t="__support__";ce.F(t,"xyz"),ce.P(t)!=='"xyz"'&&(Nt=!1),ce.q(t)}catch{Nt=!1}return Nt},j(t){k.error("sessionStorage error: ",t)},P(t){try{return v?.sessionStorage.getItem(t)}catch(e){ce.j(e)}return null},H(t){try{return JSON.parse(ce.P(t))||null}catch{}return null},F(t,e){try{return v?.sessionStorage.setItem(t,JSON.stringify(e)),!0}catch(s){ce.j(s)}return!1},q(t){try{v?.sessionStorage.removeItem(t)}catch(e){ce.j(e)}}};class pp{constructor(e){this._instance=e}get Ne(){return this._instance.config}get consent(){return this.ti()?0:this.ei}isOptedOut(){return this.Ne.cookieless_mode===ht||this.isRejected()||this.consent===-1&&this.Ne.cookieless_mode===Ht}isOptedIn(){return!this.isOptedOut()}isExplicitlyOptedOut(){return this.consent===0}isRejected(){return this.consent===0||this.consent===-1&&this.Ne.opt_out_capturing_by_default}optInOut(e){this.ii.F(this.ri,e?1:0,this.Ne.cookie_expiration,this.Ne.cross_subdomain_cookie,this.Ne.secure_cookie)}reset(){this.ii.q(this.ri,this.Ne.cross_subdomain_cookie)}get ri(){var e=this._instance.config,s=e.token,r=e.opt_out_capturing_cookie_prefix;return e.consent_persistence_name||(r?r+s:"__ph_opt_in_out_"+s)}get ei(){var e=this.ii.P(this.ri);return Zn(e)?1:M(_h,e)?0:-1}get ii(){var e=this.Ne.opt_out_capturing_persistence_type,s=e==="localStorage"?Q:pt;if(!this.ni||this.ni!==s){this.ni=s;var r=e==="localStorage"?pt:Q;r.P(this.ri)&&(this.ni.P(this.ri)||this.optInOut(Zn(r.P(this.ri))),r.q(this.ri,this.Ne.cross_subdomain_cookie))}return this.ni}ti(){return!!this.Ne.respect_dnt&&[ke?.doNotTrack,ke?.msDoNotTrack,$.doNotTrack].some((e=>Zn(e)))}}function yu(t,e){var s,r=t==null||(s=t.config)==null?void 0:s.get_current_url;if(!Se(r))return e;try{var n=r(e);return W(n)&&n?n:e}catch(i){return k.error("Error in get_current_url, falling back to window.location.href",i),e}}var wu="__POSTHOG_TOOLBAR__",fp=1,gp=3,mp=11;function sl(t){return t instanceof Element&&(t.id===wu||!(t.closest==null||!t.closest(".toolbar-global-fade-container")))}function Ft(t){return!!t&&t.nodeType===fp}function Me(t,e){return!!t&&!!t.tagName&&t.tagName.toLowerCase()===e.toLowerCase()}function bu(t){return!!t&&t.nodeType===gp}function Eu(t){return!!t&&t.nodeType===mp&&Ft(t.host)}var Su=1e3;function Go(t){return t?Pn(t).split(/\s+/):[]}function rl(t,e){var s=(function(r){var n,i=v==null||(n=v.location)==null?void 0:n.href;return x(i)?void 0:yu(r,i)})(e);return!!(s&&t&&t.some((r=>s.match(r))))}function ln(t){var e="";switch(typeof t.className){case"string":e=t.className;break;case"object":e=(t.className&&"baseVal"in t.className?t.className.baseVal:null)||t.getAttribute("class")||"";break;default:e=""}return Go(e)}function xu(t){return D(t)?null:Pn(t).split(/(\s+)/).filter((e=>Ks(e))).join("").replace(/[\r\n]/g," ").replace(/[ ]+/g," ").substring(0,255)}function rr(t){var e="";return no(t)&&!Fu(t)&&t.childNodes&&t.childNodes.length&&Z(t.childNodes,(function(s){var r;bu(s)&&s.textContent&&(e+=(r=xu(s.textContent))!==null&&r!==void 0?r:"")})),Pn(e)}function ai(t){var e;return x(t.target)?t.srcElement||null:(e=t.target)!=null&&e.shadowRoot?t.composedPath()[0]||null:t.target||null}var Ko=["a","button","form","input","select","textarea","label"];function ro(t,e){if(x(e))return!0;var s,r=function(i){if(e.some((o=>(function(a,l){var u=a.matches||a.matchesSelector||a.msMatchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.oMatchesSelector;try{return!!u&&u.call(a,l)}catch{return!1}})(i,o))))return{v:!0}};for(var n of t)if(s=r(n))return s.v;return!1}function ku(t){var e=t.parentNode;return!(!e||!Ft(e))&&e}var vp=[".ph-no-autocapture","[data-ph-no-autocapture]"],Iu=["next","previous","prev",">","<"],_p=[...Iu,"+","-","−","–"],nl=(t,e)=>/[a-z0-9]/i.test(e)?t.includes(e):t===e,il=[".ph-no-rageclick",".ph-no-capture"],yp=["","text","search","email","password","url","tel","number"];function ol(t,e){if(!v||Jo(t))return!1;var s,r,n,i,o;if(Ke(e)?(s=!!e&&il,r=void 0,n=!1):(s=(i=e?.css_selector_ignorelist)!==null&&i!==void 0?i:il,r=e?.content_ignorelist,n=(o=e?.ignore_text_selection)!==null&&o!==void 0&&o),s===!1||n&&(function(l){return!(!l||!Ft(l))&&(!!Me(l,"textarea")||(Me(l,"input")?M(yp,(l.getAttribute("type")||"").toLowerCase()):(function(u){if(u.isContentEditable)return!0;var c=u.getAttribute==null?void 0:u.getAttribute("contenteditable");return c==="true"||c===""})(l)))})(t))return!1;var a=Cu(t,!1).targetElementList;return!(function(l,u){if(l===!1||x(l))return!1;var c;if(l===!0)c=Iu;else{if(!L(l))return!1;if(l.length>10)return k.error("[PostHog] content_ignorelist array cannot exceed 10 items. Use css_selector_ignorelist for more complex matching."),!1;c=l.map((d=>d.toLowerCase()))}return u.some((d=>{var h=d.safeText,p=d.ariaLabel;return c.some((f=>nl(h,f)||nl(p,f)))}))})(r,a.map((l=>{var u;return{safeText:rr(l).toLowerCase(),ariaLabel:((u=l.getAttribute("aria-label"))==null?void 0:u.toLowerCase().trim())||""}})))&&!ro(a,s)}var Jo=t=>!t||Me(t,"html")||!Ft(t),Cu=(t,e)=>{if(!v||Jo(t))return{parentIsUsefulElement:!1,targetElementList:[]};for(var s=!1,r=[t],n=t;n.parentNode&&!Me(n,"body");)if(Eu(n.parentNode))r.push(n.parentNode.host),n=n.parentNode.host;else{var i=ku(n);if(!i)break;if(e||Ko.indexOf(i.tagName.toLowerCase())>-1)s=!0;else try{var o=v.getComputedStyle(i);o&&o.getPropertyValue("cursor")==="pointer"&&(s=!0)}catch{}r.push(i),n=i}return{parentIsUsefulElement:s,targetElementList:r}};function no(t){for(var e=new Set,s=0,r=t;r.parentNode&&!Me(r,"body");r=r.parentNode){if(s++>=Su||e.has(r))return!1;e.add(r);var n=ln(r);if(M(n,"ph-sensitive")||M(n,"ph-no-capture"))return!1}if(M(ln(t),"ph-include"))return!0;var i=t.type||"";if(W(i))switch(i.toLowerCase()){case"hidden":case"password":return!1}var o=t.name||t.id||"";return!W(o)||!/^cc|cardnum|ccnum|creditcard|csc|cvc|cvv|exp|pass|pwd|routing|seccode|securitycode|securitynum|socialsec|socsec|ssn/i.test(o.replace(/[^a-zA-Z0-9]/g,""))}function Fu(t){return!!(Me(t,"input")&&!["button","checkbox","submit","reset"].includes(t.type)||Me(t,"select")||Me(t,"textarea")||t.getAttribute("contenteditable")==="true")}var al=new RegExp("^(?:(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11}))$"),ll=/(^|[^0-9A-Za-z_])([0-9][0-9 -]*[0-9])(?=$|[^0-9A-Za-z_])/g,wp=[16,15,14,13],bp=new RegExp("^(\\d{3}-?\\d{2}-?\\d{4})$"),cl=new RegExp("(^|[^0-9])((?!000|666)[0-9]{3}-?(?!00)[0-9]{2}-?(?!0000)[0-9]{4})(?=$|([^0-9]))","g"),ul=/[0-9A-Za-z_]/;function Ep(t){for(var e=0,s=!1,r=t.length-1;r>=0;r--){var n=t.charCodeAt(r)-48;s&&(n*=2)>9&&(n-=9),e+=n,s=!s}return e%10==0}function Ks(t,e){if(e===void 0&&(e=!0),D(t))return!1;if(W(t)){t=Pn(t);var s=e?al.test((t||"").replace(/[- ]/g,"")):(function(n){var i;for(ll.lastIndex=0;i=ll.exec(n);){var o=i[2];if(o)for(var a=o.replace(/[- ]/g,""),l=0;a.length>l;l++)for(var u of wp){var c=l+u;if(a.length>=c){var d=a.slice(l,c);if(al.test(d)&&Ep(d))return!0}}}return!1})(t);if(s)return!1;var r=e?bp.test(t):(function(n){var i;for(cl.lastIndex=0;i=cl.exec(n);){var o=i[1],a=i[3];if(!(o&&a&&ul.test(o)&&ul.test(a)))return!0}return!1})(t);if(r)return!1}return!0}function dl(t){var e=rr(t);return Ks(e=(e+" "+Pu(t)).trim())?e:""}function Pu(t){var e="";return t&&t.childNodes&&t.childNodes.length&&Z(t.childNodes,(function(s){var r;if(s&&((r=s.tagName)==null?void 0:r.toLowerCase())==="span")try{var n=rr(s);e=(e+" "+n).trim(),s.childNodes&&s.childNodes.length&&(e=(e+" "+Pu(s)).trim())}catch(i){k.error("[AutoCapture]",i)}})),e}function hl(t){return t.replace(/"|\\"/g,'\\"')}function Sp(t){var e=t.attr__class;if(e)return L(e)?e:Go(e)}var xr=se("[Dead Clicks]"),xp=()=>!0,kp=t=>{var e,s=!((e=t.instance.persistence)==null||!e.get_property(Ho)),r=t.instance.config.capture_dead_clicks;return Ke(r)?r:!!te(r)||s};class pl{get lazyLoadedDeadClicksAutocapture(){return this.si}constructor(e,s,r){this.instance=e,this.isEnabled=s,this.onCapture=r,this.startIfEnabledOrStop()}onRemoteConfig(e){if(e.ok){var s=e.config;"captureDeadClicks"in s&&(this.instance.persistence&&this.instance.persistence.register({[Ho]:s.captureDeadClicks}),this.startIfEnabledOrStop())}}startIfEnabledOrStop(){this.isEnabled(this)?this.ai((()=>{this.oi()})):this.stop()}ai(e){var s,r;(s=$.__PosthogExtensions__)!=null&&s.initDeadClicksAutocapture?e():(r=$.__PosthogExtensions__)==null||r.loadExternalDependency==null||r.loadExternalDependency(this.instance,"dead-clicks-autocapture",(n=>{n?xr.error("failed to load script",n):e()}))}oi(){var e;if(C){if(!this.si&&(e=$.__PosthogExtensions__)!=null&&e.initDeadClicksAutocapture){var s=te(this.instance.config.capture_dead_clicks)?b({},this.instance.config.capture_dead_clicks):{};s.__onCapture=this.onCapture,this.onCapture&&(s.capture_dead_swipes=!1),this.si=$.__PosthogExtensions__.initDeadClicksAutocapture(this.instance,s),this.si.start(C),xr.info("starting...")}}else xr.error("`document` not found. Cannot start.")}stop(){this.si&&(this.si.stop(),this.si=void 0,xr.info("stopping..."))}}var li=se("[SegmentIntegration]"),Au="posthog-js";function $u(t,e){var s=e===void 0?{}:e,r=s.organization,n=s.projectId,i=s.prefix,o=s.severityAllowList,a=o===void 0?["error"]:o,l=s.sendExceptionsToPostHog,u=l===void 0||l;return c=>{var d,h,p,f,g;if(a!=="*"&&!a.includes(c.level)||!t.__loaded)return c;c.tags||(c.tags={});var m=t.requestRouter.endpointFor("ui","/project/"+t.config.token+"/person/"+t.get_distinct_id());c.tags["PostHog Person URL"]=m,t.sessionRecordingStarted()&&(c.tags["PostHog Recording URL"]=t.get_session_replay_url({withTimestamp:!0}));var _,w=((d=c.exception)==null?void 0:d.values)||[],E=w.map((F=>b({},F,{stacktrace:F.stacktrace?b({},F.stacktrace,{type:"raw",frames:(F.stacktrace.frames||[]).map((P=>b({},P,{platform:"web:javascript"})))}):void 0}))),I={$exception_message:((h=w[0])==null?void 0:h.value)||c.message,$exception_type:(p=w[0])==null?void 0:p.type,$exception_level:c.level,$exception_list:E,$sentry_event_id:c.event_id,$sentry_exception:c.exception,$sentry_exception_message:((f=w[0])==null?void 0:f.value)||c.message,$sentry_exception_type:(g=w[0])==null?void 0:g.type,$sentry_tags:c.tags};return r&&n&&(I.$sentry_url=(i||"https://sentry.io/organizations/")+r+"/issues/?project="+n+"&query="+c.event_id),u&&((_=t.exceptions)==null||_.sendExceptionEvent(I)),c}}class Ip{constructor(e,s,r,n,i,o){this.name=Au,this.setupOnce=function(a){a($u(e,{organization:s,projectId:r,prefix:n,severityAllowList:i,sendExceptionsToPostHog:o==null||o}))}}}class fl{constructor(e){this.li=(s,r,n)=>{n&&(n.noSessionId||n.activityTimeout||n.sessionPastMaximumLength||n.crossTabAdoption)&&(k.info("[PageViewManager] Session rotated, clearing pageview state",{sessionId:s,changeReason:n}),this.ui=void 0,this._instance.scrollManager.resetContext())},this._instance=e,this.hi()}hi(){var e;this.di=(e=this._instance.sessionManager)==null?void 0:e.onSessionId(this.li)}destroy(){var e;(e=this.di)==null||e.call(this),this.di=void 0}doPageView(e,s){var r,n=this.vi(e,s);return this.ui={pathname:(r=v?.location.pathname)!==null&&r!==void 0?r:"",pageViewId:s,timestamp:e},this._instance.scrollManager.resetContext(),n}doPageLeave(e){var s;return this.vi(e,(s=this.ui)==null?void 0:s.pageViewId)}doEvent(){var e;return{$pageview_id:(e=this.ui)==null?void 0:e.pageViewId}}vi(e,s){var r=this.ui;if(!r)return{$pageview_id:s};var n={$pageview_id:s,$prev_pageview_id:r.pageViewId},i=this._instance.scrollManager.getContext();if(i&&!this._instance.config.disable_scroll_properties){var o=i.maxScrollHeight,a=i.lastScrollY,l=i.maxScrollY,u=i.maxContentHeight,c=i.lastContentY,d=i.maxContentY;if(!(x(o)||x(a)||x(l)||x(u)||x(c)||x(d))){o=Math.ceil(o),a=Math.ceil(a),l=Math.ceil(l),u=Math.ceil(u),c=Math.ceil(c),d=Math.ceil(d);var h=o>1?rt(a/o,0,1,k):1,p=o>1?rt(l/o,0,1,k):1,f=u>1?rt(c/u,0,1,k):1,g=u>1?rt(d/u,0,1,k):1;n=ee(n,{$prev_pageview_last_scroll:a,$prev_pageview_last_scroll_percentage:h,$prev_pageview_max_scroll:l,$prev_pageview_max_scroll_percentage:p,$prev_pageview_last_content:c,$prev_pageview_last_content_percentage:f,$prev_pageview_max_content:d,$prev_pageview_max_content_percentage:g})}}return r.pathname&&(n.$prev_pageview_pathname=r.pathname),r.timestamp&&(n.$prev_pageview_duration=(e.getTime()-r.timestamp.getTime())/1e3),n}}var ci=["flags","surveys"],Cp={[au]:{exposure:"hidden"},[Bs]:{exposure:"hidden"},__cmpns:{exposure:"hidden"},[js]:{exposure:"hidden"},[Ui]:{exposure:"event"},[Hi]:{exposure:"hidden"},[Wi]:{exposure:"event"},[zi]:{exposure:"hidden"},[qi]:{exposure:"event"},[Vi]:{exposure:"event"},[Ho]:{exposure:"event"},[Wo]:{exposure:"hidden"},[Gi]:{exposure:"event"},[qt]:{exposure:"hidden"},$session_recording_enabled_server_side:{exposure:"hidden"},[ls]:{exposure:"hidden"},[zo]:{exposure:"event"},[lu]:{exposure:"event",shouldSkipFromEventProperties:t=>$e(t)},$session_past_minimum_duration:{exposure:"event"},$session_recording_url_trigger_activated_session:{exposure:"event"},$session_recording_event_trigger_activated_session:{exposure:"event"},$debug_first_full_snapshot_timestamp:{exposure:"event"},$sess_rec_flush_size:{exposure:"hidden"},[Bt]:{exposure:"hidden",storageGroup:"flags"},[Us]:{exposure:"hidden",storageGroup:"flags"},[Rr]:{exposure:"hidden"},[Ki]:{exposure:"hidden",storageGroup:"flags"},[Hs]:{exposure:"hidden",storageGroup:"flags"},[Tr]:{exposure:"hidden",storageGroup:"flags",volatile:!0},[en]:{exposure:"hidden",storageGroup:"flags"},[et]:{exposure:"hidden"},[jt]:{exposure:"hidden"},[ct]:{exposure:"hidden"},[Ut]:{exposure:"hidden"},[Ji]:{exposure:"hidden",storageGroup:"surveys"},[tn]:{exposure:"hidden",storageGroup:"surveys",volatile:!0},[Yi]:{exposure:"event"},[Nr]:{exposure:"hidden"},[Mr]:{exposure:"hidden"},[Ws]:{exposure:"hidden"},$product_tours_activated:{exposure:"hidden"},$product_tours_activated_session:{exposure:"hidden"},$conversations_widget_session_id:{exposure:"event"},$conversations_ticket_id:{exposure:"event"},$conversations_widget_state:{exposure:"event"},$conversations_user_traits:{exposure:"event"},[Wt]:{exposure:"hidden"},[zs]:{exposure:"hidden"},[Lr]:{exposure:"hidden"},[Gs]:{exposure:"hidden",storageGroup:"flags",volatile:!0},[He]:{exposure:"hidden"},[Zi]:{exposure:"hidden"},[Xi]:{exposure:"hidden"},[Qi]:{exposure:"hidden"},[eo]:{exposure:"hidden"},[sn]:{exposure:"hidden"},[rn]:{exposure:"hidden"},[cu]:{exposure:"event"},[uu]:{exposure:"event"},[du]:{exposure:"event"},[hu]:{exposure:"event"},[fu]:{exposure:"event"},[gu]:{exposure:"event"},[mu]:{exposure:"event"},$sdk_debug_replay_event_trigger_status:{exposure:"event"},$sdk_debug_replay_linked_flag_trigger_status:{exposure:"event"},$sdk_debug_replay_matched_recording_trigger_groups:{exposure:"event"},$sdk_debug_replay_remote_trigger_matching_config:{exposure:"event"},$sdk_debug_replay_trigger_groups_count:{exposure:"event"},$sdk_debug_replay_url_trigger_status:{exposure:"event"},$session_recording_start_reason:{exposure:"event"}},Fp=[["$posthog_sr_group_event_trigger_",{exposure:"hidden"}],["$posthog_sr_group_url_trigger_",{exposure:"hidden"}],["$posthog_sr_group_sampling_",{exposure:"hidden"}]],Mt=t=>{var e=Cp[t];if(e)return e;for(var s of Fp){var r=s[1];if(t.indexOf(s[0])===0)return r}},cs=(t,e)=>{try{return JSON.stringify(t,((s,r)=>typeof r=="bigint"?r.toString():r),e)}catch{return Fc(t)}},cn=t=>{var e=C?.createElement("a");return x(e)?null:(e.href=t,e)},ms=function(t,e){for(var s,r=((t.split("#")[0]||"").split(/\?(.*)/)[1]||"").replace(/^\?+/g,"").split("&"),n=0;r.length>n;n++){var i=r[n].split("=");if(i[0]===e){s=i;break}}if(!L(s)||2>s.length)return"";var o=s[1];try{o=decodeURIComponent(o)}catch{k.error("Skipping decoding for malformed query param: "+o)}return o.replace(/\+/g," ")},nr=function(t,e,s){if(!t||!e||!e.length)return t;for(var r=t.split("#"),n=r[1],i=(r[0]||"").split("?"),o=i[1],a=i[0],l=(o||"").split("&"),u=[],c=0;l.length>c;c++){var d=l[c].split("=");L(d)&&(e.includes(d[0])?u.push(d[0]+"="+s):u.push(l[c]))}var h=a;return o!=null&&(h+="?"+u.join("&")),n!=null&&(h+="#"+n),h},un=function(t,e){var s=t.match(new RegExp(e+"=([^&]*)"));return s?s[1]:null},Ru=(t,e)=>t>=e&&kc(),Tu=(t,e,s,r)=>{if(t===0){if(kc()){var n=e+1;return n===s&&r(),n}return e}return 0},kr="https?://(.*)",vs=["gclid","gclsrc","dclid","gbraid","wbraid","fbclid","msclkid","twclid","li_fat_id","igshid","ttclid","rdt_cid","epik","qclid","sccid","irclid","_kx"],Pp=["utm_source","utm_medium","utm_campaign","utm_content","utm_term","gad_source","mc_cid",...vs],ir="",Ap=["li_fat_id"];function Nu(t,e,s){if(!C)return{};var r,n=e?[...vs,...s||[]]:[],i=Mu(nr(C.URL,n,ir),t),o=(r={},Z(Ap,(function(a){var l=vu(a);r[a]=l||null})),r);return ee(o,i)}function Mu(t,e){var s=Pp.concat(e||[]),r={};return Z(s,(function(n){var i=ms(t,n);r[n]=i||null})),r}function Lu(t){var e=(function(i){return i?i.search(kr+"google.([^/?]*)")===0?"google":i.search(kr+"bing.com")===0?"bing":i.search(kr+"yahoo.com")===0?"yahoo":i.search(kr+"duckduckgo.com")===0?"duckduckgo":null:null})(t),s=e!="yahoo"?"q":"p",r={};if(!$e(e)){r.$search_engine=e;var n=C?ms(C.referrer,s):"";n.length&&(r.ph_keyword=n)}return r}function gl(){return navigator.language||navigator.userLanguage}var dn="$direct";function Ou(){return C?.referrer||dn}function Du(t,e,s){s===void 0&&(s=!1);var r=t?[...vs,...e||[]]:[],n=s?Ct(re?.href):re?.href,i=n?.substring(0,1e3);return{r:Ou().substring(0,1e3),u:i?nr(i,r,ir):void 0}}function Bu(t,e){var s;e===void 0&&(e=!1);var r=t.r,n=t.u,i=e?Ct(n):n,o={$referrer:r,$referring_domain:r==null?void 0:r==dn?dn:(s=cn(r))==null?void 0:s.host};if(i){o.$current_url=i;var a=cn(i);o.$host=a?.host,o.$pathname=a?.pathname;var l=Mu(i);ee(o,l)}if(r){var u=Lu(r);ee(o,u)}return o}function ju(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone}catch{return}}function $p(){try{return new Date().getTimezoneOffset()}catch{return}}var Rp={flags:Gs,surveys:tn},Tp=["cookie","localstorage","localstorage+cookie","sessionstorage","memory"],ts="main";class ui{constructor(e,s,r){if(r===void 0&&(r=!0),this.ci={},this.fi=!1,this.pi=!1,this.Ne=e,this.gi=r,this.props={},this.mi=void 0,this.yi=(i=>{var o="";return i.token&&(o=i.token.replace(/\+/g,"PL").replace(/\//g,"SL").replace(/=/g,"EQ")),i.persistence_name?"ph_"+i.persistence_name:"ph_"+o+"_posthog"})(e),this.ii=this.bi(e),this.pi=this.wi(e),this.load(),e.debug&&k.info("Persistence loaded",e.persistence,b({},this.props)),this.update_config(e,e,s),this.save(),v){var n=()=>this.flush();ne(v,"beforeunload",n,{capture:!1}),ne(v,"pagehide",n,{capture:!1})}}ki(){var e,s=(e=this.Ne)==null?void 0:e.persistence_save_debounce_ms;return he(s)&&s>0?s:0}isDisabled(){return!!this.xi}bi(e){Tp.indexOf(e.persistence.toLowerCase())===-1&&(k.critical("Unknown persistence type "+e.persistence+"; falling back to localStorage+cookie"),e.persistence="localStorage+cookie");var s,r=(function(o,a){o===void 0&&(o=[]),a===void 0&&(a=!1);var l=[...dp,...o];return b({},Q,{H(u){try{var c={};try{c=pt.H(u)||{}}catch{}var d,h=JSON.parse(Q.P(u)||"{}");if(a){var p={};for(var f in c){var g=c[f];$e(g)||g===""||(p[f]=g)}d=ee(h,p)}else d=ee(c,h);return Q.F(u,d),d}catch{}return null},F(u,c,d,h,p,f){var g=Q.F(u,c,void 0,void 0,f);try{var m={};l.forEach((_=>{c[_]&&(m[_]=c[_])})),Object.keys(m).length&&pt.F(u,m,d,h,p,f)}catch(_){Q.j(_)}return g},q(u,c){try{v?.localStorage.removeItem(u),pt.q(u,c)}catch(d){Q.j(d)}}})})(e.cookie_persisted_properties||[],e.__preview_cookie_wins_on_conflict||!1),n=!1,i=e.persistence.toLowerCase();return i==="localstorage"&&Q.N()?(s=Q,n=!0):i==="localstorage+cookie"&&r.N()?(s=r,n=!0):i==="sessionstorage"&&ce.N()?s=ce:i==="memory"?s=hp:i==="cookie"?s=pt:r.N()?(s=r,n=!0):s=pt,this.fi=n,s}Si(e){return this.yi+"__"+e}wi(e){return this.fi&&!!e.split_storage}properties(){var e={};return Z(this.props,((s,r)=>{var n=Mt(r);if(!n||n.exposure==="event"){if(n!=null&&n.shouldSkipFromEventProperties!=null&&n.shouldSkipFromEventProperties(s))return;e[r]=s}})),e}load(){if(!this.xi){var e=this.ii.H(this.yi);e&&(this.props=ee({},e)),this.pi&&this.Ci()}}Ci(){for(var e of ci){var s=Q.H(this.Si(e));if(s&&!mt(s)){var r=this.Mi(e);r.persisted=!0,this.Ti(e)||(r.fingerprint=this.Ei(s,e)),this.Ii(e,s)||ee(this.props,s)}}}Ti(e){return Object.keys(this.props).some((s=>{var r;return((r=Mt(s))==null?void 0:r.storageGroup)===e}))}Ii(e,s){var r=Rp[e];if(!r)return!1;var n=s[r],i=this.props[r];return he(n)&&he(i)&&i>n}refreshKey(e){var s;if(!this.xi){var r=this.pi?(s=Mt(e))==null?void 0:s.storageGroup:void 0,n=r?Q.H(this.Si(r)):this.ii.H(this.yi);if(n&&e in n)this.Pi(e,n[e]);else{if(r){var i=this.ii.H(this.yi);if(i&&e in i)return void this.Pi(e,i[e])}this.Ri(e)}}}save(){if(!this.xi){var e=this.ki();e>0?x(this.Ai)&&(this.Ai=setTimeout((()=>{this.Ai=void 0,this.Fi()}),e)):this.Fi()}}flush(){x(this.Ai)||(clearTimeout(this.Ai),this.Ai=void 0,this.Fi())}Fi(){this.xi||(this.pi?this.Li():this.Oi(this.ii,this.yi,this.props,ts))}Li(){var e=this.Di(),s=e.main,r=e.groups;for(var n of(this.Oi(this.ii,this.yi,s,ts),ci)){var i,o=r[n];(!mt(o)||(i=this.ci[n])!=null&&i.persisted)&&this.Oi(Q,this.Si(n),o,n)}}Di(){var e={},s={flags:{},surveys:{}};return Z(this.props,((r,n)=>{var i,o=(i=Mt(n))==null?void 0:i.storageGroup;o?s[o][n]=r:e[n]=r})),{main:e,groups:s}}Ei(e,s){if(s===ts)return JSON.stringify(e)+"|"+this.$i+"|"+this.Ni+"|"+this.qi;var r={};return Z(e,((n,i)=>{var o;r[i]=(o=Mt(i))!=null&&o.volatile?"__volatile__":n})),JSON.stringify(r)}Oi(e,s,r,n){var i=this.Mi(n);if(n===ts||i.dirty||x(i.fingerprint)){var o;try{if((o=this.Ei(r,n))===i.fingerprint)return void(i.dirty=!1)}catch{o=void 0}e.F(s,r,this.$i,this.Ni,this.qi,this.Ne.debug)?(i.dirty=!1,n!==ts&&(i.persisted=!0),x(o)||(i.fingerprint=o)):this.Ne.debug&&k.warn('failed to persist storage entry "'+s+'"; will retry on next save')}}remove(e){var s=(e===void 0?{}:e).keepGroupEntries,r=s!==void 0&&s;if(x(this.Ai)||(clearTimeout(this.Ai),this.Ai=void 0),this.ii.q(this.yi,!1),this.ii.q(this.yi,!0),!r&&this.gi)for(var n of ci)Q.q(this.Si(n));r?delete this.ci[ts]:this.ci={}}clear(){this.remove(),this.props={}}register_once(e,s,r){if(te(e)){x(s)&&(s="None"),this.$i=x(r)?this.ji:r;var n=!1;if(Z(e,((i,o)=>{this.props.hasOwnProperty(o)&&this.props[o]!==s||(this.Pi(o,i),n=!0)})),n)return this.save(),!0}return!1}register(e,s){if(te(e)){this.$i=x(s)?this.ji:s;var r=!1;if(Z(e,((n,i)=>{e.hasOwnProperty(i)&&(this.props[i]!==n||te(n)||L(n))&&(this.Pi(i,n),r=!0)})),r)return this.save(),!0}return!1}unregister(e){var s=typeof e=="string"?[e]:e,r=!1;for(var n of s)n in this.props&&(this.Ri(n),r=!0);r&&this.save()}update_campaign_params(){var e=C?.URL;if(e!==this.mi){var s=Nu(this.Ne.custom_campaign_params,this.Ne.mask_personal_data_properties,this.Ne.custom_personal_data_properties);mt(Vo(s))||this.register(s),this.mi=e}}update_search_keyword(){var e;this.register((e=C?.referrer)?Lu(e):{})}update_referrer_info(){var e;this.register_once({$referrer:Ou(),$referring_domain:C!=null&&C.referrer&&((e=cn(C.referrer))==null?void 0:e.host)||dn},void 0)}set_initial_person_info(){this.props[Qi]||this.props[eo]||this.register_once({[sn]:Du(this.Ne.mask_personal_data_properties,this.Ne.custom_personal_data_properties,this.Ne.disable_capture_url_hashes)},void 0)}get_initial_props(){var e={};Z([eo,Qi],(n=>{var i=this.props[n];i&&Z(i,(function(o,a){e["$initial_"+Ni(a)]=o}))}));var s=this.props[sn];if(s){var r=(function(n,i){i===void 0&&(i=!1);var o=Bu(n,i),a={};return Z(o,(function(l,u){a["$initial_"+Ni(u)]=l})),a})(s,this.Ne.disable_capture_url_hashes);ee(e,r)}return e}safe_merge(e){return Z(this.props,(function(s,r){r in e||(e[r]=s)})),e}update_config(e,s,r){this.ji=this.$i=e.cookie_expiration,this.set_disabled(e.disable_persistence||!!r),this.set_cross_subdomain(e.cross_subdomain_cookie),this.set_secure(e.secure_cookie);var n=e.persistence!==s.persistence||!((l,u)=>{if(l.length!==u.length)return!1;var c=[...l].sort(),d=[...u].sort();return c.every(((h,p)=>h===d[p]))})(e.cookie_persisted_properties||[],s.cookie_persisted_properties||[]),i=n?this.bi(e):this.ii,o=this.wi(e);if(n||o!==this.pi){var a=this.props;this.clear(),this.ii=i,this.pi=o,this.props=a,this.save()}}set_disabled(e){this.xi=e,this.xi?this.remove():this.save()}set_cross_subdomain(e){e!==this.Ni&&(this.Ni=e,this.remove({keepGroupEntries:!0}),this.save())}set_secure(e){e!==this.qi&&(this.qi=e,this.remove({keepGroupEntries:!0}),this.save())}set_event_timer(e,s){var r=this.props[js]||{};r[e]=s,this.Pi(js,r),this.save()}remove_event_timer(e){var s=this.props[js]||{},r=s[e];return x(r)||(delete s[e],this.Pi(js,s),this.save()),r}get_property(e){return this.props[e]}set_property(e,s){this.Pi(e,s),this.save()}Pi(e,s){var r;this.props[e]=s,(r=Mt(e))!=null&&r.volatile||this.Bi(e)}Ri(e){delete this.props[e],this.Bi(e)}Bi(e){var s,r=(s=Mt(e))==null?void 0:s.storageGroup;r&&(this.Mi(r).dirty=!0)}Mi(e){return this.ci[e]||(this.ci[e]={})}}function Ir(t){var e=!0;return{dispose(){if(e){e=!1;var s=t();s&&Se(s.then)&&s.then(void 0,(()=>{}))}}}}var xe={GZipJS:"gzip-js",Base64:"base64"},As={Activation:"events",Cancellation:"cancelEvents"},di={Popover:"popover",API:"api",Widget:"widget"},ft={SHOWN:"survey shown",DISMISSED:"survey dismissed",SENT:"survey sent"},hi={SURVEY_ID:"$survey_id",SURVEY_ITERATION:"$survey_iteration",SURVEY_LAST_SEEN_DATE:"$survey_last_seen_date"},io={Popover:"popover",Inline:"inline"},Np={SHOWN:"product tour shown"},ml={TOUR_LAST_SEEN_DATE:"$product_tour_last_seen_date",TOUR_TYPE:"$product_tour_type"},vl=se("[RateLimiter]");class Mp{constructor(e){this.serverLimits={},this.lastEventRateLimited=!1,this.checkForLimiting=s=>{var r=s.text;if(r&&r.length)try{(JSON.parse(r).quota_limited||[]).forEach((n=>{vl.info((n||"events")+" is quota limited."),this.serverLimits[n]=new Date().getTime()+6e4}))}catch(n){return void vl.warn('could not rate limit - continuing. Error: "'+n?.message+'"',{text:r})}},this.instance=e,this.lastEventRateLimited=this.clientRateLimitContext(!0).isRateLimited}get captureEventsPerSecond(){var e;return((e=this.instance.config.rate_limiting)==null?void 0:e.events_per_second)||10}get captureEventsBurstLimit(){var e;return Math.max(((e=this.instance.config.rate_limiting)==null?void 0:e.events_burst_limit)||10*this.captureEventsPerSecond,this.captureEventsPerSecond)}clientRateLimitContext(e){var s,r,n;e===void 0&&(e=!1);var i=this.captureEventsBurstLimit,o=this.captureEventsPerSecond,a=new Date().getTime(),l=(s=(r=this.instance.persistence)==null?void 0:r.get_property(Xi))!==null&&s!==void 0?s:{tokens:i,last:a};l.tokens+=(a-l.last)/1e3*o,l.last=a,l.tokens>i&&(l.tokens=i);var u=1>l.tokens;if(u||e||(l.tokens=Math.max(0,l.tokens-1)),u&&!e){var c=(he(l.dropped)?l.dropped:0)+1;l.dropped=c,!this.lastEventRateLimited&&this.Hi(c)&&(l.dropped=0)}return this.lastEventRateLimited=u,(n=this.instance.persistence)==null||n.set_property(Xi,l),{isRateLimited:u,remainingTokens:l.tokens}}Ui(e){var s=this.instance.config.property_denylist;return!L(s)||!s.includes(e)}zi(){var e;if(this.Ui("$current_url")&&this.Ui("$pathname")&&re!=null&&re.pathname)return""+((e=re.origin)!==null&&e!==void 0?e:"")+re.pathname}Hi(e){var s,r,n=this.captureEventsBurstLimit,i=this.captureEventsPerSecond,o=this.zi(),a=this.Ui("$session_id")?(s=(r=this.instance).get_session_id)==null?void 0:s.call(r):void 0,l=[e+" event(s) dropped since the last warning",o?"triggered on "+o:void 0,a?"session "+a:void 0].filter(Boolean).join(", ");return!!this.instance.capture("$$client_ingestion_warning",{$$client_ingestion_warning_message:"posthog-js client rate limited: "+l+". Config is set to "+i+" events per second and "+n+" events burst limit."},{skip_client_rate_limiting:!0})}isServerRateLimited(e){var s=this.serverLimits[e||"events"]||!1;return s!==!1&&new Date().getTime()e(this.remoteConfig))):e()}Vi(e){this._instance._send_request({method:"GET",url:this._instance.requestRouter.endpointFor("assets","/array/"+this._instance.config.token+"/config"),callback:e})}load(){try{if(this.remoteConfig)return xt.info("Using preloaded remote config",this.remoteConfig),this.Zi(this.remoteConfig),void this.Gi();if(this._instance.Qi())return void xt.warn("Remote config is disabled. Falling back to local config.");this.Wi((e=>{if(!e)return xt.info("No config found after loading remote JS config. Falling back to JSON."),void this.Vi((s=>{this.Zi(s.json,s),this.Gi()}));this.Zi(e),this.Gi()}))}catch(e){xt.error("Error loading remote config",e),this.Zi()}}stop(){this.Ki&&(clearInterval(this.Ki),this.Ki=void 0)}refresh(){!this._instance.Qi()&&C&&C.visibilityState!=="hidden"&&this._instance.reloadFeatureFlags()}Gi(){var e;if(!this.Ki){var s=(e=this._instance.config.remote_config_refresh_interval_ms)!==null&&e!==void 0?e:3e5;s!==0&&(this.Ki=setInterval((()=>{this.refresh()}),s))}}Zi(e,s){!e&&s&&(s.statusCode===0?s.error||xt.warn("Failed to fetch remote config from PostHog."):xt.error("Failed to fetch remote config from PostHog."));try{this._instance.Zi(e?{ok:!0,config:e}:{ok:!1})}catch(n){xt.error("Error applying remote config",n)}if(e?.hasFeatureFlags!==!1&&!this._instance.config.advanced_disable_feature_flags_on_first_load)try{var r;(r=this._instance.featureFlags)==null||r.ensureFlagsLoaded()}catch(n){xt.error("Error loading feature flags",n)}}}var qe=Uint8Array,Ae=Uint16Array,_s=Uint32Array,Yo=new qe([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),Zo=new qe([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),_l=new qe([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Hu=function(t,e){for(var s=new Ae(31),r=0;31>r;++r)s[r]=e+=1<r;++r)for(var i=s[r];s[r+1]>i;++i)n[i]=i-s[r]<<5|r;return[s,n]},Wu=Hu(Yo,2),oo=Wu[1];Wu[0][28]=258,oo[258]=28;for(var yl=Hu(Zo,0)[1],zu=new Ae(32768),ie=0;32768>ie;++ie){var ss=(43690&ie)>>>1|(21845&ie)<<1;zu[ie]=((65280&(ss=(61680&(ss=(52428&ss)>>>2|(13107&ss)<<2))>>>4|(3855&ss)<<4))>>>8|(255&ss)<<8)>>>1}var Js=function(t,e,s){for(var r=t.length,n=0,i=new Ae(e);r>n;++n)++i[t[n]-1];var o,a=new Ae(e);for(n=0;e>n;++n)a[n]=a[n-1]+i[n-1]<<1;for(o=new Ae(r),n=0;r>n;++n)o[n]=zu[a[t[n]-1]++]>>>15-t[n];return o},Kt=new qe(288);for(ie=0;144>ie;++ie)Kt[ie]=8;for(ie=144;256>ie;++ie)Kt[ie]=9;for(ie=256;280>ie;++ie)Kt[ie]=7;for(ie=280;288>ie;++ie)Kt[ie]=8;var hn=new qe(32);for(ie=0;32>ie;++ie)hn[ie]=5;var Lp=Js(Kt,9),Op=Js(hn,5),qu=function(t){return(t/8>>0)+(7&t&&1)},Vu=function(t,e,s){(s==null||s>t.length)&&(s=t.length);var r=new(t instanceof Ae?Ae:t instanceof _s?_s:qe)(s-e);return r.set(t.subarray(e,s)),r},ot=function(t,e,s){var r=e/8>>0;t[r]|=s<<=7&e,t[r+1]|=s>>>8},$s=function(t,e,s){var r=e/8>>0;t[r]|=s<<=7&e,t[r+1]|=s>>>8,t[r+2]|=s>>>16},pi=function(t,e){for(var s=[],r=0;t.length>r;++r)t[r]&&s.push({s:r,f:t[r]});var n=s.length,i=s.slice();if(!n)return[new qe(0),0];if(n==1){var o=new qe(s[0].s+1);return o[s[0].s]=1,[o,1]}s.sort((function(F,P){return F.f-P.f})),s.push({s:-1,f:25001});var a=s[0],l=s[1],u=0,c=1,d=2;for(s[0]={s:-1,f:a.f+l.f,l:a,r:l};c!=n-1;)a=s[s[d].f>s[u].f?u++:d++],l=s[u!=c&&s[d].f>s[u].f?u++:d++],s[c++]={s:-1,f:a.f+l.f,l:a,r:l};var h=i[0].s;for(r=1;n>r;++r)i[r].s>h&&(h=i[r].s);var p=new Ae(h+1),f=ao(s[c-1],p,0);if(f>e){r=0;var g=0,m=f-e,_=1<r;++r){var w=i[r].s;if(e>=p[w])break;g+=_-(1<>>=m;g>0;){var E=i[r].s;e>p[E]?g-=1<=0&&g;--r){var I=i[r].s;p[I]==e&&(--p[I],++g)}f=e}return[new qe(p),f]},ao=function(t,e,s){return t.s==-1?Math.max(ao(t.l,e,s+1),ao(t.r,e,s+1)):e[t.s]=s},wl=function(t){for(var e=t.length;e&&!t[--e];);for(var s=new Ae(++e),r=0,n=t[0],i=1,o=function(l){s[r++]=l},a=1;e>=a;++a)if(t[a]==n&&a!=e)++i;else{if(!n&&i>2){for(;i>138;i-=138)o(32754);i>2&&(o(i>10?i-11<<5|28690:i-3<<5|12305),i=0)}else if(i>3){for(o(n),--i;i>6;i-=6)o(8304);i>2&&(o(i-3<<5|8208),i=0)}for(;i--;)o(n);i=1,n=t[a]}return[s.subarray(0,r),e]},Rs=function(t,e){for(var s=0,r=0;e.length>r;++r)s+=t[r]*e[r];return s},lo=function(t,e,s){var r=s.length,n=qu(e+2);t[n]=255&r,t[n+1]=r>>>8,t[n+2]=255^t[n],t[n+3]=255^t[n+1];for(var i=0;r>i;++i)t[n+i+4]=s[i];return 8*(n+4+r)},bl=function(t,e,s,r,n,i,o,a,l,u,c){ot(e,c++,s),++n[256];for(var d=pi(n,15),h=d[0],p=d[1],f=pi(i,15),g=f[0],m=f[1],_=wl(h),w=_[0],E=_[1],I=wl(g),F=I[0],P=I[1],B=new Ae(19),S=0;w.length>S;++S)B[31&w[S]]++;for(S=0;F.length>S;++S)B[31&F[S]]++;for(var A=pi(B,7),R=A[0],N=A[1],T=19;T>4&&!R[_l[T-1]];--T);var O,J,z,H,oe=u+5<<3,pe=Rs(n,Kt)+Rs(i,hn)+o,Ie=Rs(n,h)+Rs(i,g)+o+14+3*T+Rs(B,R)+(2*B[16]+3*B[17]+7*B[18]);if(pe>=oe&&Ie>=oe)return lo(e,c,t.subarray(l,l+u));if(ot(e,c,1+(pe>Ie)),c+=2,pe>Ie){O=Js(h,p),J=h,z=Js(g,m),H=g;var _e=Js(R,N);for(ot(e,c,E-257),ot(e,c+5,P-1),ot(e,c+10,T-4),c+=14,S=0;T>S;++S)ot(e,c+3*S,R[_l[S]]);c+=3*T;for(var Ce=[w,F],Re=0;2>Re;++Re){var ae=Ce[Re];for(S=0;ae.length>S;++S)ot(e,c,_e[me=31&ae[S]]),c+=R[me],me>15&&(ot(e,c,ae[S]>>>5&127),c+=ae[S]>>>12)}}else O=Lp,J=Kt,z=Op,H=hn;for(S=0;a>S;++S)if(r[S]>255){var me;$s(e,c,O[257+(me=r[S]>>>18&31)]),c+=J[me+257],me>7&&(ot(e,c,r[S]>>>23&31),c+=Yo[me]);var ge=31&r[S];$s(e,c,z[ge]),c+=H[ge],ge>3&&($s(e,c,r[S]>>>5&8191),c+=Zo[ge])}else $s(e,c,O[r[S]]),c+=J[r[S]];return $s(e,c,O[256]),c+J[256]},Dp=new _s([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),Bp=(function(){for(var t=new _s(256),e=0;256>e;++e){for(var s=e,r=9;--r;)s=(1&s&&3988292384)^s>>>1;t[e]=s}return t})(),fi=function(t,e,s){for(;s;++e)t[e]=s,s>>>=8};function jp(t,e){e===void 0&&(e={});var s=(function(){var d=4294967295;return{p(h){for(var p=d,f=0;h.length>f;++f)p=Bp[255&p^h[f]]^p>>>8;d=p},d(){return 4294967295^d}}})(),r=t.length;s.p(t);var n,i,o,a,l,u=(a=10+((n=e).filename&&n.filename.length+1||0),l=8,(function(d,h,p,f,g,m){var _=d.length,w=new qe(f+_+5*(1+Math.floor(_/7e3))+g),E=w.subarray(f,w.length-g),I=0;if(!h||8>_)for(var F=0;_>=F;F+=65535){var P=F+65535;_>P?I=lo(E,I,d.subarray(F,P)):(E[F]=!0,I=lo(E,I,d.subarray(F,_)))}else{for(var B=Dp[h-1],S=B>>>13,A=8191&B,R=(1<F;++F){var me=z(F),ge=32767&F,Ye=T[me];if(N[ge]=Ye,T[me]=ge,F>=Re){var Rt=_-F;if((Ie>7e3||Ce>24576)&&Rt>423){I=bl(d,E,0,H,oe,pe,_e,Ce,ae,F-ae,I),Ce=Ie=_e=0,ae=F;for(var de=0;286>de;++de)oe[de]=0;for(de=0;30>de;++de)pe[de]=0}var Ve=2,St=0,ks=A,Be=ge-Ye&32767;if(Rt>2&&me==z(F-Be))for(var Fe=Math.min(S,Rt)-1,mr=Math.min(32767,F),vr=Math.min(258,Rt);mr>=Be&&--ks&&ge!=Ye;){if(d[F+Ve]==d[F+Ve-Be]){for(var je=0;vr>je&&d[F+je]==d[F+je-Be];++je);if(je>Ve){if(Ve=je,St=Be,je>Fe)break;var _r=Math.min(Be,je-2),Xt=0;for(de=0;_r>de;++de){var Qt=F-Be+de+32768&32767,Is=Qt-N[Qt]+32768&32767;Is>Xt&&(Xt=Is,Ye=Qt)}}}Be+=(ge=Ye)-(Ye=N[ge])+32768&32767}if(St){H[Ce++]=268435456|oo[Ve]<<18|yl[St];var Ta=31&oo[Ve],Na=31&yl[St];_e+=Yo[Ta]+Zo[Na],++oe[257+Ta],++pe[Na],Re=F+Ve,++Ie}else H[Ce++]=d[F],++oe[d[F]]}}I=bl(d,E,!0,H,oe,pe,_e,Ce,ae,F-ae,I)}return Vu(w,0,f+qu(I)+g)})(i=t,(o=e).level==null?6:o.level,o.mem==null?Math.ceil(1.5*Math.max(8,Math.min(13,Math.log(i.length)))):12+o.mem,a,l)),c=u.length;return(function(d,h){var p=h.filename;if(d[0]=31,d[1]=139,d[2]=8,d[8]=2>h.level?4:h.level==9?2:0,d[9]=3,h.mtime!=0&&fi(d,4,Math.floor(new Date(h.mtime||Date.now())/1e3)),p){d[3]=8;for(var f=0;p.length>=f;++f)d[f+10]=p.charCodeAt(f)}})(u,e),fi(u,c-8,s.d()),fi(u,c-4,r),u}var Up=!!$i||!!Mo,Gu="text/plain",Dr=!1,Ku=(t,e)=>{var s=t.split("#"),r=s[1],n=s[0].split("?"),i=n[0],o=n[1];if(!o)return t;var a=o.split("&").filter((l=>l.split("=")[0]!==e)).join("&");return i+(a?"?"+a:"")+(r?"#"+r:"")},$n=function(t,e,s){var r;s===void 0&&(s=!0);var n=t.split("?"),i=n[0],o=n[1],a=b({},e),l=(r=o?.split("&").map((c=>{var d,h=c.split("="),p=h[0],f=s&&(d=a[p])!==null&&d!==void 0?d:h[1];return delete a[p],p+"="+f})))!==null&&r!==void 0?r:[],u=(function(c,d){var h,p;d===void 0&&(d="&");var f=[];return Z(c,(function(g,m){x(g)||x(m)||m==="undefined"||(h=encodeURIComponent((_=>_ instanceof File)(g)?g.name:g.toString()),p=encodeURIComponent(m),f[f.length]=p+"="+h)})),f.join(d)})(a);return u&&l.push(u),l.length>0?i+"?"+l.join("&"):i},gi=t=>{if(t.Ji)return t.Ji;var e=t.data,s=t.compression;if(e){if(s===xe.GZipJS){var r=jp((function(a,l){var u=a.length;if(typeof TextEncoder<"u")return new TextEncoder().encode(a);for(var c=new qe(a.length+(a.length>>>1)),d=0,h=function(m){c[d++]=m},p=0;u>p;++p){if(d+5>c.length){var f=new qe(d+8+(u-p<<1));f.set(c),c=f}var g=a.charCodeAt(p);128>g?h(g):2048>g?(h(192|g>>>6),h(128|63&g)):g>55295&&57344>g?(h(240|(g=65536+(1047552&g)|1023&a.charCodeAt(++p))>>>18),h(128|g>>>12&63),h(128|g>>>6&63),h(128|63&g)):(h(224|g>>>12),h(128|g>>>6&63),h(128|63&g))}return Vu(c,0,d)})(cs(e)),{mtime:0});return{contentType:Gu,body:r.buffer.slice(r.byteOffset,r.byteOffset+r.byteLength),estimatedSize:r.byteLength}}if(s===xe.Base64){var n=(function(a){return a&&btoa(encodeURIComponent(a).replace(/%([0-9A-F]{2})/g,((l,u)=>String.fromCharCode(parseInt(u,16)))))})(cs(e)),i=(a=>"data="+encodeURIComponent(typeof a=="string"?a:cs(a)))(n);return{contentType:"application/x-www-form-urlencoded",body:i,estimatedSize:new Blob([i]).size}}var o=cs(e);return{contentType:"application/json",body:o,estimatedSize:new Blob([o]).size}}},Ju=t=>{var e,s,r=()=>t.transport==="sendBeacon"?{url:$n(t.url,{compression:xe.Base64}),encodedBody:gi(b({},t,{compression:xe.Base64,Ji:void 0}))}:{url:Ku(t.url,"compression"),encodedBody:gi(b({},t,{compression:void 0,Ji:void 0}))};try{e=gi(t)}catch(n){if(Ua(t.compression,ms(t.url,"compression")))return k.error("Failed to gzip request body, sending uncompressed payload",n),r();throw n}return e&&Ua(t.compression,ms(t.url,"compression"))&&!((s=e.body)instanceof ArrayBuffer?Ri(new Uint8Array(s)):ArrayBuffer.isView(s)&&Ri(new Uint8Array(s.buffer,s.byteOffset,s.byteLength)))?(Dr=!0,r()):{url:t.url,encodedBody:e}},Yu=t=>{try{return Ju(t)}catch(e){return k.error(e),void(t.callback==null||t.callback({statusCode:0,error:e}))}},Hp=(function(){var t=X((function*(e){var s=cs(e.data),r=yield(function(i,o,a){return Ti.apply(this,arguments)})(s,Y.DEBUG,{rethrow:!0});if(!r)return e;var n=yield r.arrayBuffer();return b({},e,{Ji:{contentType:Gu,body:n,estimatedSize:n.byteLength}})}));return function(e){return t.apply(this,arguments)}})(),Wp=/Failed to fetch|NetworkError|Load failed/i,Zu=t=>t?.name==="TypeError"&&Wp.test(t?.message||""),Xu=t=>{var e=Yu(t);if(e){var s=e.url,r=e.encodedBody,n=r??{},i=n.contentType,o=n.body,a=n.estimatedSize,l=new Headers;Z(t.headers,(function(f,g){l.append(g,f)})),i&&l.append("Content-Type",i);var u=null,c=!1;if(Ma){var d=new Ma;u={signal:d.signal,timeout:setTimeout((()=>{var f,g;c=!0,d.abort((f=t.timeout,(g=new Error("PostHog request timed out"+(f?" after "+f+"ms":""))).name="AbortError",g))}),t.timeout)}}var h=f=>{c&&f?.name==="AbortError"||Zu(f)?k.warn(f):k.error(f),t.callback==null||t.callback({statusCode:0,error:f})};try{var p;Mo(s,b({method:t?.method||"GET",headers:l,keepalive:t.method==="POST"&&!t.Yi&&52428.8>(a||0),body:o,signal:(p=u)==null?void 0:p.signal},t.fetchOptions)).then((f=>f.text().then((g=>{var m={statusCode:f.status,text:g};if(f.status===200)try{m.json=JSON.parse(g)}catch(_){k.error(_)}t.callback==null||t.callback(m)})))).catch(h).finally((()=>u?clearTimeout(u.timeout):null))}catch(f){u&&clearTimeout(u.timeout),h(f)}}},co=t=>{try{var e,s=Ju(t),r=s.url,n=s.encodedBody,i=n??{},o=i.body,a=i.estimatedSize;if(!o)return;var l=o instanceof Blob?o:new Blob([o],{type:i.contentType});if(ke.sendBeacon(r,l))return;var u=L(t.data)?t.data:(e=t.data)==null?void 0:e.batch;if(L(u)&&u.length>1&&(a??0)>16384){var c=Math.ceil(u.length/2),d=h=>L(t.data)?h:b({},t.data,{batch:h});return co(b({},t,{data:d(u.slice(0,c))})),void co(b({},t,{data:d(u.slice(c))}))}k.warn("Beacon of ~"+(a??0)+" bytes was rejected by the browser, falling back to fetch"),Xu(b({},t,{Yi:!0}))}catch(h){k.warn("Beacon send failed",h)}},El=(t,e,s,r)=>{var n=r==="query"?e==="POST"?"sent_at":"_":void 0;return $n(s===xe.GZipJS?Ku(t,"compression"):t,b({},n?{[n]:Date.now().toString()}:{},s===xe.GZipJS?{}:{compression:s}))},Br=[];Mo&&Br.push({transport:"fetch",method:Xu}),$i&&Br.push({transport:"XHR",method(t){var e=Yu(t);if(e){var s=new $i,r=e.encodedBody;s.open(t.method||"GET",e.url,!0);var n=r??{},i=n.contentType,o=n.body;Z(t.headers,(function(a,l){s.setRequestHeader(l,a)})),i&&s.setRequestHeader("Content-Type",i),t.timeout&&(s.timeout=t.timeout),s.onreadystatechange=()=>{if(s.readyState===4){var a={statusCode:s.status,text:s.responseText};if(s.status===200)try{a.json=JSON.parse(s.responseText)}catch{}t.callback==null||t.callback(a)}},s.send(o)}}}),ke!=null&&ke.sendBeacon&&Br.push({transport:"sendBeacon",method:co});var uo=3e3;class zp{constructor(e,s){this.Xi=!0,this.tr=[],this.er=rt(s?.flush_interval_ms||uo,250,5e3,k.createLogger("flush interval"),uo),this.ir=e}enqueue(e){this.tr.push(e),this.rr||this.nr()}unload(){this.sr();var e=this.tr.length>0?this.ar():{},s=Object.values(e);[...s.filter((r=>r.url.indexOf("/e")===0)),...s.filter((r=>r.url.indexOf("/e")!==0))].map((r=>{this.lr(b({},r,{transport:"sendBeacon"}))}))}enable(){this.Xi=!1,this.nr()}nr(){var e=this;this.Xi||(this.rr=setTimeout((()=>{if(this.sr(),this.tr.length>0){var s=this.ar(),r=function(){var i=s[n],o=new Date().getTime();i.data&&L(i.data)&&Z(i.data,(a=>{a.offset=Math.abs(a.timestamp-o),delete a.timestamp})),e.lr(i)};for(var n in s)r()}}),this.er))}lr(e){try{this.ir(e)}catch(s){k.error(s)}}sr(){clearTimeout(this.rr),this.rr=void 0}ar(){var e={};return Z(this.tr,(s=>{var r,n=s,i=(n?n.batchKey:null)||n.url;x(e[i])&&(e[i]=b({},n,{data:[]})),(r=e[i].data)==null||r.push(n.data)})),this.tr=[],e}}var qp=["retriesPerformedSoFar"];class Vp{constructor(e){this.ur=!1,this.hr=3e3,this.tr=[],this._instance=e,this.tr=[],this.dr=!0,!x(v)&&"onLine"in v.navigator&&(this.dr=v.navigator.onLine,this.vr=()=>{this.dr=!0,this.cr()},this.pr=()=>{this.dr=!1},ne(v,"online",this.vr),ne(v,"offline",this.pr))}get length(){return this.tr.length}retriableRequest(e){var s=e.retriesPerformedSoFar,r=Ic(e,qp);lt(s)&&(r.url=$n(r.url,{retry_count:s})),this._instance._send_request(b({},r,{callback:n=>{if(n.statusCode!==200&&(400>n.statusCode||n.statusCode>=500)){if((n.statusCode===0?3:10)>(s??0))return void this.At(b({retriesPerformedSoFar:s},r));n.statusCode===0&&k.warn("Request failed before receiving an HTTP response; this can happen due to network issues, CORS, browser blocking, or ad blockers. Stopped retrying after "+(s??0)+" retries.")}r.callback==null||r.callback(n)}}))}At(e){var s=e.retriesPerformedSoFar||0;e.retriesPerformedSoFar=s+1;var r=(function(o){var a=3e3*Math.pow(2,o),l=a/2,u=Math.min(18e5,a),c=Math.random()-.5;return Math.ceil(u+c*(u-l))})(s),n=Date.now()+r;this.tr.push({retryAt:n,requestOptions:e});var i="Enqueued failed request for retry in "+r;navigator.onLine||(i+=" (Browser is offline)"),k.warn(i),this.ur||(this.ur=!0,this.gr())}gr(){if(this.mr&&clearTimeout(this.mr),this.tr.length===0)return this.ur=!1,void(this.mr=void 0);this.mr=setTimeout((()=>{this.dr&&this.tr.length>0&&this.cr(),this.gr()}),this.hr)}cr(){var e=Date.now(),s=[],r=this.tr.filter((i=>e>i.retryAt||(s.push(i),!1)));if(this.tr=s,r.length>0)for(var n of r)this.retriableRequest(n.requestOptions)}unload(){for(var e of(this.mr&&(clearTimeout(this.mr),this.mr=void 0),this.ur=!1,x(v)||(this.vr&&(v.removeEventListener("online",this.vr),this.vr=void 0),this.pr&&(v.removeEventListener("offline",this.pr),this.pr=void 0)),this.tr)){var s=e.requestOptions;try{this._instance._send_request(b({},s,{transport:"sendBeacon"}))}catch(r){k.error(r)}}this.tr=[]}}class Gp{constructor(e){this.yr=()=>{var s,r,n,i;this.br||(this.br={});var o=this.scrollElement(),a=this.scrollY(),l=o?Math.max(0,o.scrollHeight-o.clientHeight):0,u=a+(o?.clientHeight||0),c=o?.scrollHeight||0;this.br.lastScrollY=Math.ceil(a),this.br.maxScrollY=Math.max(a,(s=this.br.maxScrollY)!==null&&s!==void 0?s:0),this.br.maxScrollHeight=Math.max(l,(r=this.br.maxScrollHeight)!==null&&r!==void 0?r:0),this.br.lastContentY=u,this.br.maxContentY=Math.max(u,(n=this.br.maxContentY)!==null&&n!==void 0?n:0),this.br.maxContentHeight=Math.max(c,(i=this.br.maxContentHeight)!==null&&i!==void 0?i:0)},this._instance=e}get _r(){return this._instance.config.scroll_root_selector}getContext(){return this.br}resetContext(){var e=this.br;return setTimeout(this.yr,0),e}startMeasuringScrollPosition(){ne(v,"scroll",this.yr,{capture:!0}),ne(v,"scrollend",this.yr,{capture:!0}),ne(v,"resize",this.yr)}scrollElement(){if(!this._r)return v?.document.documentElement;var e=L(this._r)?this._r:[this._r];for(var s of e){var r=v?.document.querySelector(s);if(r)return r}}wr(e){var s=e==="y"?"scrollTop":"scrollLeft";if(this._r){var r=this.scrollElement();return r&&r[s]||0}return v?e==="y"?v.scrollY||v.pageYOffset||v.document.documentElement.scrollTop||0:v.scrollX||v.pageXOffset||v.document.documentElement.scrollLeft||0:0}scrollY(){return this.wr("y")}scrollX(){return this.wr("x")}}var Kp=t=>Du(t?.config.mask_personal_data_properties,t?.config.custom_personal_data_properties,t?.config.disable_capture_url_hashes);class Sl{constructor(e,s,r,n){this.kr=i=>{var o=this.Sr();if(!o||o.sessionId!==i){var a={sessionId:i,props:this.Cr(this._instance)};this.Mr.register({[Zi]:a})}},this._instance=e,this.Tr=s,this.Mr=r,this.Cr=n||Kp,this.Tr.onSessionId(this.kr)}Sr(){return this.Mr.props[Zi]}getSetOnceProps(){var e,s=(e=this.Sr())==null?void 0:e.props;return s?"r"in s?Bu(s,this._instance.config.disable_capture_url_hashes):{$referring_domain:s.referringDomain,$pathname:s.initialPathName,utm_source:s.utm_source,utm_campaign:s.utm_campaign,utm_medium:s.utm_medium,utm_content:s.utm_content,utm_term:s.utm_term}:{}}getSessionProps(){var e={};return Z(Vo(this.getSetOnceProps()),((s,r)=>{r==="$current_url"&&(r="url"),e["$session_entry_"+Ni(r)]=s})),e}}class Xo{on(e,s){return this.Er[e]||(this.Er[e]=[]),this.Er[e].push(s),()=>{this.Er[e]=this.Er[e].filter((r=>r!==s))}}emit(e,s){for(var r of this.Er[e]||[])r(s);for(var n of this.Er["*"]||[])n(e,s)}constructor(){this.Er={}}}var Ts=se("[SessionId]");class xl{on(e,s){return this.Ir.on(e,s)}constructor(e,s,r){var n;if(this.Pr=null,this.Rr=[],this.Ar=void 0,this.Fr=!1,this.Ir=new Xo,this.Lr=(u,c)=>!(!lt(u)||!lt(c))&&Math.abs(u-c)>this.sessionTimeoutMs,!e.persistence)throw new Error("SessionIdManager requires a PostHogPersistence instance");if(e.config.cookieless_mode===ht)throw new Error('SessionIdManager cannot be used with cookieless_mode="always"');this.Ne=e.config,this.Mr=e.persistence,this.Or=void 0,this.Dr=void 0,this._sessionStartTimestamp=null,this._sessionActivityTimestamp=null,this.$r=s||dt,this.Nr=r||dt;var i=this.Ne.persistence_name||this.Ne.token;if(this._sessionTimeoutMs=1e3*rt(this.Ne.session_idle_timeout_seconds||1800,60,36e3,Ts.createLogger("session_idle_timeout_seconds"),1800),e.register({$configured_session_timeout_ms:this._sessionTimeoutMs}),this.qr(),this.jr="ph_"+i+"_window_id",this.Br="ph_"+i+"_primary_window_exists",this.Hr()){var o=ce.H(this.jr),a=ce.H(this.Br);o&&!a?this.Or=o:ce.q(this.jr),ce.F(this.Br,!0)}if((n=this.Ne.bootstrap)!=null&&n.sessionID)try{var l=(u=>{var c=this.Ne.bootstrap.sessionID.replace(/-/g,"");if(c.length!==32)throw new Error("Not a valid UUID");if(c[12]!=="7")throw new Error("Not a UUIDv7");return parseInt(c.substring(0,12),16)})();this.Ur(this.Ne.bootstrap.sessionID,new Date().getTime(),l)}catch(u){Ts.error("Invalid sessionID in bootstrap",u)}this.zr()}get sessionTimeoutMs(){return this._sessionTimeoutMs}onSessionId(e){return x(this.Rr)&&(this.Rr=[]),this.Rr.push(e),this.Dr&&e(this.Dr,this.Or),()=>{this.Rr=this.Rr.filter((s=>s!==e))}}Hr(){return this.Ne.persistence!=="memory"&&!this.Mr.xi&&ce.N()}Wr(e){e!==this.Or&&(this.Or=e,this.Hr()&&ce.F(this.jr,e))}Vr(){return this.Or?this.Or:this.Hr()?ce.H(this.jr):null}Zr(e){var s=this.Pr;return!$e(s)&&!$e(e)&&5e3>Math.abs(e-s)}Ur(e,s,r){var n=s!==this._sessionActivityTimestamp,i=!(e!==this.Dr||r!==this._sessionStartTimestamp);this._sessionStartTimestamp=r,this._sessionActivityTimestamp=s,this.Dr=e,i&&!n||i&&this.Zr(s)||(this.Pr=s,this.Mr.register({[ls]:[s,e,r]}))}Gr(){var e,s=(e=this.Ne)==null?void 0:e.persistence_save_debounce_ms;return lt(s)&&s>0}Qr(){this.Gr()?this.Mr.refreshKey(ls):(this.Mr.flush(),this.Mr.load())}Kr(){var e;if(!$e(this._sessionActivityTimestamp)&&this._sessionActivityTimestamp!==this.Pr){this.Qr();var s=this.Jr();s[1]===this.Dr&&s[2]===this._sessionStartTimestamp&&(this.Pr=this._sessionActivityTimestamp,this.Mr.register({[ls]:[this._sessionActivityTimestamp,(e=this.Dr)!==null&&e!==void 0?e:null,this._sessionStartTimestamp]}),this.Mr.flush())}}Yr(){var e=this.Jr()[0],s=lt(e)?e:0,r=lt(this._sessionActivityTimestamp)?this._sessionActivityTimestamp:0;return Math.max(s,r)}Xr(e){return this.Qr(),this.Lr(e,this.Yr())}Jr(){var e=this.Mr.props[ls];return L(e)&&e.length===2&&e.push(e[0]),e||[0,null,0]}resetSessionId(){this.Pr=null,clearTimeout(this.tn),this.tn=void 0,this.Ur(null,null,null)}destroy(){this.Fr=!0,this.Kr(),clearTimeout(this.tn),this.tn=void 0,this.Ar&&v&&(v.removeEventListener(on,this.Ar,{capture:!1}),this.Ar=void 0),this.Rr=[]}zr(){this.Ar=()=>{this.Kr(),this.Hr()&&ce.q(this.Br)},ne(v,on,this.Ar,{capture:!1})}checkAndGetSessionAndWindowId(e,s){if(e===void 0&&(e=!1),s===void 0&&(s=null),this.Ne.cookieless_mode===ht)throw new Error('checkAndGetSessionAndWindowId should not be called with cookieless_mode="always"');var r=s||new Date().getTime(),n=this.Jr(),i=n[1],o=n[2],a=this.Yr(),l=this.Vr(),u=lt(o)&&Math.abs(r-o)>864e5,c=!1,d=!1,h=!i,p=i,f=!h&&!e&&this.Lr(r,a);if(f){(f=this.Xr(r))||Ts.info("cross-tab refresh kept the session alive",{sessionId:i});var g=this.Jr();i=g[1],o=g[2]}h||f||u?(i=this.$r(),l=this.Nr(),Ts.info("new session ID generated",{sessionId:i,windowId:l,changeReason:{noSessionId:h,activityTimeout:f,sessionPastMaximumLength:u}}),o=r,c=!0):(l||(l=this.Nr(),c=!0),(d=i!==p)&&(Ts.info("adopted cross-tab session id",{sessionId:i,windowId:l}),c=!0));var m=lt(a)&&e&&!u?a:r,_=lt(o)?o:new Date().getTime();this.Wr(l),this.Ur(i,m,_),e||this.qr();var w={noSessionId:h,activityTimeout:f,sessionPastMaximumLength:u,crossTabAdoption:d};return c&&this.Rr.forEach((E=>E(i,l,w))),{sessionId:i,windowId:l,sessionStartTimestamp:_,changeReason:c?w:void 0,lastActivityTimestamp:a}}qr(){this.Fr||(clearTimeout(this.tn),this.tn=setTimeout((()=>{if(!this.Fr)if(this.Xr(new Date().getTime())){var e=this.Dr;this.resetSessionId(),this.Ir.emit("forcedIdleReset",{idleSessionId:e})}else this.qr()}),1.1*this.sessionTimeoutMs))}}var Qu=function(t,e){if(!t)return!1;var s=t.userAgent;if(s&&Wa(s,e))return!0;try{var r=t?.userAgentData;if(r!=null&&r.brands&&r.brands.some((n=>Wa(n?.brand,e))))return!0}catch{}return!!t.webdriver};function ed(){return(ed=X((function*(){var t=ke?.userAgentData;if(t!=null&&t.getHighEntropyValues)try{var e=yield t.getHighEntropyValues(["model"]),s=e?.model;return W(s)&&s.length>0?s:void 0}catch(r){return void k.info("Unable to resolve $device_model from userAgentData.getHighEntropyValues",r)}}))).apply(this,arguments)}var pn=function(t,e){if(!(function(s){try{new RegExp(s)}catch{return!1}return!0})(e))return!1;try{return new RegExp(e).test(t)}catch{return!1}};function mi(t,e,s){return cs({distinct_id:t,userPropertiesToSet:e,userPropertiesToSetOnce:s})}var td={exact:(t,e)=>e.some((s=>t.some((r=>s===r)))),is_not:(t,e)=>e.every((s=>t.every((r=>s!==r)))),regex:(t,e)=>e.some((s=>t.some((r=>pn(s,r))))),not_regex:(t,e)=>e.every((s=>t.every((r=>!pn(s,r))))),icontains:(t,e)=>e.map(Cr).some((s=>t.map(Cr).some((r=>s.includes(r))))),not_icontains:(t,e)=>e.map(Cr).every((s=>t.map(Cr).every((r=>!s.includes(r))))),gt:(t,e)=>e.some((s=>{var r=parseFloat(s);return!isNaN(r)&&t.some((n=>r>parseFloat(n)))})),lt:(t,e)=>e.some((s=>{var r=parseFloat(s);return!isNaN(r)&&t.some((n=>rt.toLowerCase();function sd(t,e){return!t||Object.entries(t).every((s=>{var r=s[1],n=e?.[s[0]];if(x(n)||$e(n))return!1;var i=[String(n)],o=td[r.operator];return!!o&&o(r.values,i)}))}var ho="custom",kl="i.posthog.com",Jp=/^\/static\//;class Yp{constructor(e){this.en={},this.instance=e}get apiHost(){var e=this.instance.config.api_host.trim().replace(/\/$/,"");return e==="https://app.posthog.com"?"https://us.i.posthog.com":e}get flagsApiHost(){var e=this.instance.config.flags_api_host;return e?e.trim().replace(/\/$/,""):this.apiHost}get uiHost(){var e,s=(e=this.instance.config.ui_host)==null?void 0:e.replace(/\/$/,"");return s||(s=this.apiHost.replace("."+kl,".posthog.com")),s==="https://app.posthog.com"?"https://us.posthog.com":s}get region(){return this.en[this.apiHost]||(this.en[this.apiHost]=/https:\/\/(app|us|us-assets)(\.i)?\.posthog\.com/i.test(this.apiHost)?"us":/https:\/\/(eu|eu-assets)(\.i)?\.posthog\.com/i.test(this.apiHost)?"eu":ho),this.en[this.apiHost]}rn(e){if(Jp.test(e)){var s=this.instance.config.asset_host;if(typeof s=="string")return s.trim().replace(/\/$/,"")||void 0}}endpointFor(e,s){if(s===void 0&&(s=""),s&&(s=s[0]==="/"?s:"/"+s),e==="ui")return this.uiHost+s;if(e==="flags")return this.flagsApiHost+s;if(e==="assets"){var r=this.rn(s);if(r)return""+r+s}if(this.region===ho)return this.apiHost+s;var n=kl+s;switch(e){case"assets":return"https://"+this.region+"-assets."+n;case"api":return"https://"+this.region+"."+n}}}function rd(t){var e;return!((e=t.conditions)==null||(e=e.events)==null||(e=e.values)==null||!e.length)}var q=se("[Surveys]"),nd="seenSurvey_",id=t=>{try{var e=(s=>((r,n)=>""+nd+(function(i){return i.current_iteration&&i.current_iteration>0?i.id+"_"+i.current_iteration:i.id})(n))(0,s))(t);if(localStorage.getItem(e))return;localStorage.setItem(e,"true")}catch(s){q.error("Failed to persist survey seen state",s)}},Zp=[di.Popover,di.Widget,di.API],Xp={ignoreConditions:!1,ignoreDelay:!1,displayType:io.Popover},Qp=se("[PostHog ExternalIntegrations]"),ef={intercom:"intercom-integration",crispChat:"crisp-chat-integration"};class tf{constructor(e){this._instance=e}ai(e,s){var r;(r=$.__PosthogExtensions__)==null||r.loadExternalDependency==null||r.loadExternalDependency(this._instance,e,(n=>{if(n)return Qp.error("failed to load script",n);s()}))}startIfEnabledOrStop(){var e=this,s=function(){var i,o,a,l=r[0],u=r[1];!u||(i=$.__PosthogExtensions__)!=null&&(i=i.integrations)!=null&&i[l]||e.ai(ef[l],(()=>{var c;(c=$.__PosthogExtensions__)==null||(c=c.integrations)==null||(c=c[l])==null||c.start(e._instance)})),!u&&(o=$.__PosthogExtensions__)!=null&&(o=o.integrations)!=null&&o[l]&&((a=$.__PosthogExtensions__)==null||(a=a.integrations)==null||(a=a[l])==null||a.stop())};for(var r of Object.entries((n=this._instance.config.integrations)!==null&&n!==void 0?n:{})){var n;s()}}}class sf{constructor(e,s){this.rt=e,this.nn=s,this.sn=new Map,this.an=!1}add(e){var s=this;return X((function*(){if(s.an)throw new Error("Cannot add an extension to a disposed ExtensionRuntime");if(s.sn.has(e.name))throw new Error('Browser extension "'+e.name+'" is already registered');s.sn.set(e.name,e);try{var r=e.setup(s.nn);r&&(yield r)}catch(i){var n=s.sn.get(e.name)===e;n&&s.sn.delete(e.name),s.rt.error('Failed to set up browser extension "'+e.name+'"',i),n&&s.ln(e)}}))()}dispose(){if(!this.an){this.an=!0;var e=Array.from(this.sn.values()).reverse();for(var s of(this.sn.clear(),e))this.ln(s)}}ln(e){try{var s=e.dispose==null?void 0:e.dispose();s&&Se(s.then)&&s.then(void 0,(r=>{this.rt.error('Failed to dispose browser extension "'+e.name+'"',r)}))}catch(r){this.rt.error('Failed to dispose browser extension "'+e.name+'"',r)}}}class rf{constructor(e){this._instance=e}initialize(){}get(e){var s=this._instance.persistence;if(typeof e=="string")return s?.get_property(e);var r={};for(var n of e){var i=s?.get_property(n);x(i)||(r[n]=i)}return r}set(e,s){var r;(r=this._instance.persistence)==null||r.register(typeof e=="string"?{[e]:s}:e)}remove(e){var s;(s=this._instance.persistence)==null||s.unregister(e)}}var Il="extensionsRemoteConfig";class nf{constructor(e){this.an=!1,this.instance=e,this.rt=k,this.un=e.hn,this.kv=new rf(e),this.onEvent=s=>Ir(this.instance.on("eventCaptured",(r=>{try{s({event:r.event,properties:r.properties})}catch(n){this.rt.error("Browser extension event listener failed",n)}}))),this.onRemoteConfig=s=>{if(this.an)return Ir((()=>{}));var r=i=>{try{s(i)}catch(o){this.rt.error("Browser extension remote config listener failed",o)}},n=this.instance.dn.on(Il,r);return this.un&&r(this.un),Ir(n)},this.vn=new sf(k.createLogger("[BrowserExtensions]"),this)}get logger(){return this.rt}get distinctId(){return this.instance.get_distinct_id()}get anonymousId(){var e;return(e=this.instance.get_property(sr))!==null&&e!==void 0?e:this.distinctId}get deviceId(){var e=this.instance.get_property(sr);return typeof e=="string"?e:void 0}get library(){return{name:Y.LIB_NAME,version:Y.LIB_VERSION}}get initialPersonProperties(){var e,s;return(e=(s=this.instance.persistence)==null?void 0:s.get_initial_props())!==null&&e!==void 0?e:{}}get groups(){return this.instance.getGroups()}get session(){try{var e,s,r,n,i=(e=this.instance.sessionManager)==null?void 0:e.checkAndGetSessionAndWindowId(!0);return{sessionId:(s=i?.sessionId)!==null&&s!==void 0?s:"",windowId:(r=i?.windowId)!==null&&r!==void 0?r:"",sessionStartTimestamp:(n=i?.sessionStartTimestamp)!==null&&n!==void 0?n:0}}catch{return{sessionId:"",windowId:"",sessionStartTimestamp:0}}}get projectToken(){return this.instance.config.token}add(e){return this.vn.add(e)}capture(e,s,r){var n=this;return X((function*(){r?n.instance.capture(e,s,{timestamp:r.timestamp,uuid:r.uuid,$set:r.set,$set_once:r.setOnce}):n.instance.capture(e,s)}))()}registerDynamicEventProperties(e){return Ir(this.instance.cn(e))}handleRemoteConfig(e){this.an||(this.un=e,this.instance.dn.emit(Il,e))}sendRequest(e,s){var r=this;return X((function*(){var n;s===void 0&&(s={});var i=r.instance.requestRouter.endpointFor((n=s.target)!==null&&n!==void 0?n:"api",e),o={method:s.method,url:s.query?$n(i,s.query):i,data:s.body,headers:s.headers,timeout:s.timeoutMs,fireCallbackOnDrop:!0,transport:s.transport,compression:s.compression,timestampMode:s.sentAt};return s.transport==="sendBeacon"?(r.instance._send_request(o),{statusCode:202}):new Promise((a=>{o.callback=a,r.instance._send_request(o)}))}))()}dispose(){this.an||(this.an=!0,this.vn.dispose())}}var Ys={},vi=0,fn=()=>{},Cl='Consent opt in/out is not valid with cookieless_mode="always" and will be ignored',Ns="Surveys module not available",Fl="sanitize_properties is deprecated. Use before_send instead",od="Invalid value for property_denylist config: ",of=["token","distinct_id",pu],os="posthog",ad=!Up&&Pe?.indexOf("MSIE")===-1&&Pe?.indexOf("Mozilla")===-1,_i=t=>{var e;return b({api_host:"https://us.i.posthog.com",flags_api_host:null,ui_host:null,asset_host:null,token:"",autocapture:!0,cross_subdomain_cookie:op(C?.location),persistence:"localStorage+cookie",persistence_name:"",cookie_persisted_properties:[],loaded:fn,save_campaign_params:!0,custom_campaign_params:[],custom_blocked_useragents:[],save_referrer:!0,capture_pageleave:"if_capture_pageview",defaults:t??"unset",__preview_deferred_init_extensions:!1,__preview_external_dependency_versioned_paths:!1,__preview_cookie_wins_on_conflict:!1,debug:re&&W(re?.search)&&re.search.indexOf("__posthog_debug=true")!==-1||!1,cookie_expiration:365,upgrade:!1,disable_session_recording:!1,disable_persistence:!1,disable_web_experiments:!0,disable_surveys:!1,disable_surveys_automatic_display:!1,disable_conversations:!1,disable_product_tours:!1,disableDeviceModel:!1,disable_external_dependency_loading:!1,strict_script_versioning:!1,enable_recording_console_log:void 0,secure_cookie:(v==null||(e=v.location)==null?void 0:e.protocol)==="https:",ip:!1,opt_out_capturing_by_default:!1,opt_out_persistence_by_default:!1,opt_out_useragent_filter:!1,opt_out_capturing_persistence_type:"localStorage",consent_persistence_name:null,opt_out_capturing_cookie_prefix:null,opt_in_site_apps:!1,property_denylist:[],respect_dnt:!1,sanitize_properties:null,request_headers:{},request_batching:!0,properties_string_max_length:65535,mask_all_element_attributes:!1,mask_all_text:!1,mask_personal_data_properties:!1,custom_personal_data_properties:[],advanced_disable_flags:!1,advanced_disable_decide:!1,advanced_disable_feature_flags:!1,advanced_disable_feature_flags_on_first_load:!1,advanced_only_evaluate_survey_feature_flags:!1,advanced_feature_flags_dedup_per_session:!1,advanced_enable_surveys:!1,advanced_disable_toolbar_metrics:!1,feature_flag_request_timeout_ms:3e3,surveys_request_timeout_ms:1e4,on_request_error(s){k.error("Bad HTTP status: "+s.statusCode+" "+s.text)},get_device_id:s=>s,capture_performance:void 0,name:"posthog",bootstrap:{},disable_compression:!1,session_idle_timeout_seconds:1800,person_profiles:to,before_send:void 0,get_current_url:void 0,request_queue_config:{flush_interval_ms:uo},error_tracking:{},_onCapture:fn},(s=>({rageclick:s&&s>="2026-05-30"?{content_ignorelist:_p,ignore_text_selection:!0}:!s||"2025-11-30">s||{content_ignorelist:!0},capture_pageview:!s||"2025-05-24">s||"history_change",session_recording:s&&s>="2026-06-25"?{strictMinimumDuration:!0,canvasCapture:{resolutionScale:.6},streamNetworkBody:!0}:s&&s>="2026-05-30"?{strictMinimumDuration:!0,canvasCapture:{resolutionScale:.6}}:s&&s>="2025-11-30"?{strictMinimumDuration:!0}:{},external_scripts_inject_target:s&&s>="2026-01-30"?"head":"body",internal_or_test_user_hostname:s&&s>="2026-01-30"?/^(localhost|127\.0\.0\.1)$/:void 0,persistence_save_debounce_ms:s&&s>="2026-05-30"?250:0,split_storage:!(!s||"2026-05-30">s),detect_google_search_app:!(!s||"2026-05-30">s),disable_capture_url_hashes:!(!s||"2026-06-25">s)}))(t))},af=[["process_person","person_profiles"],["xhr_headers","request_headers"],["cookie_name","persistence_name"],["disable_cookie","disable_persistence"],["__preview_disable_beacon","disable_beacon"],["store_google","save_campaign_params"],["verbose","debug"]],Pl=t=>{var e={};for(var s of af){var r=s[0],n=s[1];x(t[r])||(e[n]=t[r])}var i=ee({},e,t),o=t.__preview_external_dependency_versioned_paths;return x(o)||(x(t.strict_script_versioning)&&(i.strict_script_versioning=!!o),W(o)&&x(t.asset_host)&&(i.asset_host=o)),L(t.property_blacklist)&&(x(t.property_denylist)?i.property_denylist=t.property_blacklist:L(t.property_denylist)?i.property_denylist=[...t.property_blacklist,...t.property_denylist]:k.error(od+t.property_denylist)),i};class lf{constructor(){this.__forceAllowLocalhost=!1}get fn(){return this.__forceAllowLocalhost}set fn(e){k.error("WebPerformanceObserver is deprecated and has no impact on network capture. Use `_forceAllowLocalhostNetworkCapture` on `posthog.sessionRecording`"),this.__forceAllowLocalhost=e}}class Te{pn(e,s){if(e){var r=this.sn.indexOf(e);r!==-1&&this.sn.splice(r,1)}return this.sn.push(s),s.initialize==null||s.initialize(),s}gn(){return this.config.cookieless_mode===ht||this.config.cookieless_mode===Ht&&this.consent.isRejected()}get decideEndpointWasHit(){var e,s;return(e=(s=this.featureFlags)==null?void 0:s.hasLoadedFlags)!==null&&e!==void 0&&e}get flagsEndpointWasHit(){var e,s;return(e=(s=this.featureFlags)==null?void 0:s.hasLoadedFlags)!==null&&e!==void 0&&e}constructor(){var e;this.webPerformance=new lf,this.mn=!1,this.version=Y.LIB_VERSION,this.yn=new Set,this.bn="",this.dn=new Xo,this.sn=[],this._n=[],this._calculate_event_properties=this.calculateEventProperties.bind(this),this.config=_i(),this.SentryIntegration=Ip,this.sentryIntegration=r=>(function(n,i){var o=$u(n,i);return{name:Au,processEvent:a=>o(a)}})(this,r),this.__request_queue=[],this.__loaded=!1,this.analyticsDefaultEndpoint="/e/",this.wn=!1,this.kn=null,this.xn=null,this.Sn=null,this.scrollManager=new Gp(this),this.pageViewManager=new fl(this),this.rateLimiter=new Mp(this),this.requestRouter=new Yp(this),this.consent=new pp(this),this.externalIntegrations=new tf(this);var s=(e=Te.__defaultExtensionClasses)!==null&&e!==void 0?e:{};this.featureFlags=s.featureFlags&&new s.featureFlags(this),this.toolbar=s.toolbar&&new s.toolbar(this),this.surveys=s.surveys&&new s.surveys(this),this.conversations=s.conversations&&new s.conversations(this),this.logs=s.logs&&new s.logs(this),this.metrics=s.metrics&&new s.metrics(this),this.experiments=s.experiments&&new s.experiments(this),this.exceptions=s.exceptions&&new s.exceptions(this),this.people={set:(r,n,i)=>{var o=W(r)?{[r]:n}:r;this.setPersonProperties(o),i?.({})},set_once:(r,n,i)=>{var o=W(r)?{[r]:n}:r;this.setPersonProperties(void 0,o),i?.({})}},this.on("eventCaptured",(r=>k.info('send "'+r?.event+'"',r)))}init(e,s,r){if(r&&r!==os){var n,i=(n=Ys[r])!==null&&n!==void 0?n:new Te;return i._init(e,s,r),Ys[r]=i,Ys[os][r]=i,i}return this._init(e,s,r)}_init(e,s,r){var n,i;s===void 0&&(s={});var o,a=W(e)?e.trim():"";if(!a)return k.critical("PostHog was initialized without a token. This likely indicates a misconfiguration. Please check the first argument passed to posthog.init()"),this;if(this.__loaded)return a!==((o=this.config)==null?void 0:o.token)?console.warn("[PostHog.js]","You have already initialized PostHog with a different project token! Re-initializing is a no-op, so events will keep going to the project this instance was initialized with. To capture into a second project, load PostHog once, then initialize a named instance after the SDK has loaded, e.g. posthog.init('"+a+"', { ... }, 'project2')"):console.warn("[PostHog.js]","You have already initialized PostHog! Re-initializing is a no-op"),this;this.__loaded=!0,this.config=_i(s.defaults),s.debug=this.Cn(s.debug),this.Mn=s,this.Tn=[],s.person_profiles?this.xn=s.person_profiles:s.process_person&&(this.xn=s.process_person);var l=_i(s.defaults),u=Pl(s),c=ee({},l,u,{name:r,token:a});te(l.rageclick)&&te(u.rageclick)&&(c.rageclick=ee({},l.rageclick,u.rageclick)),te(l.session_recording)&&te(u.session_recording)&&(c.session_recording=ee({},l.session_recording,u.session_recording)),this.set_config(c),this.config.on_xhr_error&&k.error("on_xhr_error is deprecated. Use on_request_error instead"),this.compression=s.disable_compression?void 0:xe.GZipJS;var d=this.En();if(this.persistence=new ui(this.config,d),this.sessionPersistence=this.config.persistence==="sessionStorage"||this.config.persistence==="memory"?this.persistence:new ui(b({},this.config,{persistence:"sessionStorage"}),d,!1),this.bn="ph_"+(this.config.persistence_name||this.config.token)+"_session_registered_properties",this.config.persistence!=="memory"&&!d&&ce.N()){var h=ce.H(this.bn);L(h)&&h.forEach((P=>{W(P)&&this.yn.add(P)}))}else ce.q(this.bn);var p=b({},this.persistence.props),f=b({},this.sessionPersistence.props);this.register({$initialization_time:new Date().toISOString()}),this.In=new zp((P=>this.Pn(P)),this.config.request_queue_config),this.Rn=new Vp(this),this.__request_queue=[];var g=this.gn();if(g||(this.sessionManager=new xl(this),this.sessionPropsManager=new Sl(this,this.sessionManager,this.persistence),this.sessionManager.onSessionId(((P,B,S)=>{(S!=null&&S.activityTimeout||S!=null&&S.sessionPastMaximumLength||S!=null&&S.crossTabAdoption)&&this.An()}))),this.Fn(),this.config.__preview_deferred_init_extensions?(k.info("Deferring extension initialization to improve startup performance"),setTimeout((()=>{this.Ln(g)}),0)):(k.info("Initializing extensions synchronously"),this.Ln(g)),Y.DEBUG=Y.DEBUG||this.config.debug,Y.DEBUG&&k.info("Starting in debug mode",{this:this,config:s,thisC:b({},this.config),p,s:f}),!this.config.identity_distinct_id||(n=s.bootstrap)!=null&&n.distinctID||(s.bootstrap=b({},s.bootstrap,{distinctID:this.config.identity_distinct_id,isIdentifiedID:!0})),((i=s.bootstrap)==null?void 0:i.distinctID)!==void 0){var m=s.bootstrap.distinctID,_=this.get_distinct_id(),w=this.persistence.get_property(He);if(s.bootstrap.isIdentifiedID&&_!=null&&_!==m&&w===es)this.identify(m);else if(s.bootstrap.isIdentifiedID&&_!=null&&_!==m&&w===Tt)k.warn("Bootstrap distinctID differs from an already-identified user. The existing identity is preserved. Call reset() before reinitializing if you intend to switch users.");else{var E=this.config.get_device_id(dt()),I=s.bootstrap.isIdentifiedID?E:m;this.persistence.set_property(He,s.bootstrap.isIdentifiedID?Tt:es),this.register({distinct_id:m,$device_id:I})}}if(g)this.register_once({distinct_id:br,$device_id:null},"");else if(!this.get_distinct_id()){var F=this.config.get_device_id(dt());this.register_once({distinct_id:F,$device_id:F},""),this.persistence.set_property(He,es)}return ne(v,"onpagehide"in self?"pagehide":"unload",this._handle_unload.bind(this),{passive:!1}),s.segment?(function(P,B){var S=P.config.segment;if(!S)return B();(function(A,R){var N=A.config.segment;if(!N)return R();var T=J=>{var z=()=>J.anonymousId()||dt();A.config.get_device_id=z,J.id()&&(A.register({distinct_id:J.id(),$device_id:z()}),A.persistence.set_property(He,Tt)),R()},O=N.user();"then"in O&&Se(O.then)?O.then(T):T(O)})(P,(()=>{S.register((A=>{typeof Promise<"u"&&Promise.resolve||li.warn("This browser does not have Promise support, and can not use the segment integration");var R=(N,T)=>{if(!T)return N;N.event.userId||N.event.anonymousId===A.get_distinct_id()||(li.info("No userId set, resetting PostHog"),A.reset()),N.event.userId&&N.event.userId!==A.get_distinct_id()&&(li.info("UserId set, identifying with PostHog"),A.identify(N.event.userId));var O=A.calculateEventProperties(T,N.event.properties);return N.event.properties=Object.assign({},O,N.event.properties),N};return{name:"PostHog JS",type:"enrichment",version:"1.0.0",isLoaded:()=>!0,load:()=>Promise.resolve(),track:N=>R(N,N.event.event),page:N=>R(N,is),identify:N=>R(N,ii),screen:N=>R(N,"$screen")}})(P)).then((()=>{B()}))}))})(this,(()=>this.On())):this.On(),Se(this.config._onCapture)&&this.config._onCapture!==fn&&(k.warn("onCapture is deprecated. Please use `before_send` instead"),this.on("eventCaptured",(P=>this.config._onCapture(P.event,P)))),this.config.ip&&k.warn('The `ip` config option has NO EFFECT AT ALL and has been deprecated. Use a custom transformation or "Discard IP data" project setting instead. See https://posthog.com/tutorials/web-redact-properties#hiding-customer-ip-address for more information.'),this.config.disableDeviceModel||(function(){return ed.apply(this,arguments)})().then((P=>{P&&this.register({[ri]:P})})).catch(fn),this}Fn(){var e,s,r,n,i,o,a=(e=(s=this.config.__extensionClasses)==null?void 0:s.featureFlags)!==null&&e!==void 0?e:(r=Te.__defaultExtensionClasses)==null?void 0:r.featureFlags;a&&(this.featureFlags&&this.featureFlags instanceof a||((n=this.Dn)==null||n.call(this),this.Dn=void 0,this.featureFlags=new a(this)),Se(this.featureFlags.onReloading)&&Se(this.featureFlags.setup)?this.Dn||(this.Dn=this.featureFlags.onReloading((()=>{this.dn.emit("featureFlagsReloading",!0)})),this.$n().add(this.featureFlags)):(i=(o=this.featureFlags).initialize)==null||i.call(o))}Ln(e){var s,r,n,i,o,a,l,u=performance.now(),c=b({},Te.__defaultExtensionClasses,this.config.__extensionClasses),d=[];c.exceptions&&this.sn.push(this.exceptions=(s=this.exceptions)!==null&&s!==void 0?s:new c.exceptions(this)),c.historyAutocapture&&this.sn.push(this.historyAutocapture=new c.historyAutocapture(this)),c.tracingHeaders&&this.sn.push(this.tracingHeaders=new c.tracingHeaders(this)),c.siteApps&&this.sn.push(this.siteApps=new c.siteApps(this)),c.sessionRecording&&!e&&this.sn.push(this.sessionRecording=new c.sessionRecording(this)),this.config.disable_scroll_properties||d.push((()=>{this.scrollManager.startMeasuringScrollPosition()})),c.autocapture&&this.sn.push(this.autocapture=new c.autocapture(this)),c.surveys&&this.sn.push(this.surveys=(r=this.surveys)!==null&&r!==void 0?r:new c.surveys(this)),c.logs&&this.sn.push(this.logs=(n=this.logs)!==null&&n!==void 0?n:new c.logs(this)),c.metrics&&this.sn.push(this.metrics=(i=this.metrics)!==null&&i!==void 0?i:new c.metrics(this)),c.conversations&&this.sn.push(this.conversations=(o=this.conversations)!==null&&o!==void 0?o:new c.conversations(this)),c.productTours&&this.sn.push(this.productTours=new c.productTours(this)),c.heatmaps&&this.sn.push(this.heatmaps=new c.heatmaps(this)),c.webVitalsAutocapture&&this.sn.push(this.webVitalsAutocapture=new c.webVitalsAutocapture(this)),c.exceptionObserver&&this.sn.push(this.exceptionObserver=new c.exceptionObserver(this)),c.deadClicksAutocapture&&this.sn.push(this.deadClicksAutocapture=new c.deadClicksAutocapture(this,kp)),c.toolbar&&this.sn.push(this.toolbar=(a=this.toolbar)!==null&&a!==void 0?a:new c.toolbar(this)),c.experiments&&this.sn.push(this.experiments=(l=this.experiments)!==null&&l!==void 0?l:new c.experiments(this)),this.sn.forEach((h=>{h.initialize&&d.push((()=>{h.initialize==null||h.initialize()}))})),d.push((()=>{if(this.Nn){var h=this.Nn;this.Nn=void 0,this.sn.forEach((p=>p.onRemoteConfig==null?void 0:p.onRemoteConfig(h)))}})),this.qn(d,u)}qn(e,s){for(;e.length>0;){if(this.config.__preview_deferred_init_extensions&&performance.now()-s>=30&&e.length>0)return void setTimeout((()=>{this.qn(e,s)}),0);var r=e.shift();if(r)try{r()}catch(i){k.error("Error initializing extension:",i)}}var n=Math.round(performance.now()-s);this.register_for_session({[fu]:this.config.__preview_deferred_init_extensions?"deferred":"synchronous",[gu]:n}),this.config.__preview_deferred_init_extensions&&k.info("PostHog extensions initialized ("+n+"ms)")}Zi(e){var s;if(!C||!C.body)return k.info("document not ready yet, trying again in 500 milliseconds..."),void setTimeout((()=>{this.Zi(e)}),500);if(this.config.__preview_deferred_init_extensions&&(this.Nn=e),this.hn=e,this.compression=void 0,e.ok){var r,n=e.config;n.supportedCompression&&!this.config.disable_compression&&(this.compression=M(n.supportedCompression,xe.GZipJS)?xe.GZipJS:M(n.supportedCompression,xe.Base64)?xe.Base64:void 0),(r=n.analytics)!=null&&r.endpoint&&(this.analyticsDefaultEndpoint=n.analytics.endpoint)}this.set_config({person_profiles:this.xn?this.xn:to}),(s=this.jn)==null||s.handleRemoteConfig(e),this.sn.forEach((i=>i.onRemoteConfig==null?void 0:i.onRemoteConfig(e)))}On(){try{this.config.loaded(this)}catch(r){k.critical("`loaded` function failed",r)}if(this.Bn(),this.config.internal_or_test_user_hostname&&re!=null&&re.hostname){var e=re.hostname,s=this.config.internal_or_test_user_hostname;(typeof s=="string"?e===s:s.test(e))&&this.setInternalOrTestUser()}this.config.capture_pageview&&setTimeout((()=>{(this.consent.isOptedIn()||this.gn())&&this.Hn()}),1),this.Un=new Uu(this),this.Un.load()}Bn(){var e;this.is_capturing()&&this.config.request_batching&&((e=this.In)==null||e.enable())}_dom_loaded(){this.is_capturing()&&Er(this.__request_queue,(e=>this.Pn(e))),this.__request_queue=[],this.Bn()}_handle_unload(){var e,s,r,n,i;(e=this.surveys)==null||e.handlePageUnload==null||e.handlePageUnload(),(s=this.metrics)==null||s.flush("sendBeacon"),this.config.request_batching?(this.zn()&&this.capture(ni),(r=this.logs)==null||r.flushLogs("sendBeacon"),(n=this.In)==null||n.unload(),(i=this.Rn)==null||i.unload()):this.zn()&&this.capture(ni,null,{transport:"sendBeacon"})}_send_request(e){this.__loaded?ad?this.__request_queue.push(e):this.rateLimiter.isServerRateLimited(e.batchKey)?e.fireCallbackOnDrop&&(e.callback==null||e.callback({statusCode:429})):(e.transport=e.transport||this.config.api_transport,e.headers=b({},this.config.request_headers,e.headers),e.compression=e.compression==="best-available"?this.compression:e.compression,(x(this.config.disable_beacon)?this.config.__preview_disable_beacon:this.config.disable_beacon)&&(e.disableTransport=["sendBeacon"]),e.fetchOptions=e.fetchOptions||this.config.fetch_options,(s=>{var r,n,i,o=b({},s);o.timeout=o.timeout||6e4;var a,l,u,c,d,h=(r=o.transport)!==null&&r!==void 0?r:"fetch";h==="sendBeacon"&&x(o.compression)&&o.data&&(o.compression=xe.Base64),o.method==="POST"&&o.data&&(o.timestampMode==="capture-body"?o.data={api_key:(l=(d=(c=L(a=o.data)?a:[a])[0])==null||(u=d.properties)==null?void 0:u.token)!==null&&l!==void 0?l:d?.token,batch:c,sent_at:new Date().toISOString()}:o.timestampMode==="body"&&(o.data=(function(m,_){return _===void 0&&(_=new Date().toISOString()),L(m)?m.map((w=>b({},w,{sent_at:_}))):b({},m,{sent_at:_})})(o.data))),o.url=El(o.url,o.method,o.compression,o.timestampMode);var p=Br.filter((m=>!o.disableTransport||!m.transport||!o.disableTransport.includes(m.transport))),f=(n=(i=(function(m,_){for(var w=0;m.length>w;w++)if(m[w].transport===h)return m[w]})(p))==null?void 0:i.method)!==null&&n!==void 0?n:p[0].method;if(!f)throw new Error("No available transport method");var g=m=>{try{f(m)}catch(_){Zu(_)?k.warn(_):k.error(_),o.callback==null||o.callback({statusCode:0,error:_})}};h!=="sendBeacon"&&o.data&&o.compression===xe.GZipJS&&lh&&typeof Promise<"u"&&!Dr?Hp(o).then((m=>{g(m)})).catch((m=>{if(Ha(m))return Dr=!0,void g(b({},o,{compression:void 0,url:El(s.url,s.method,void 0,s.timestampMode)}));(_=>{if(!_||typeof _!="object")return!1;var w="name"in _?String(_.name):"";return Ha(_)||w===Cc})(m)&&(Dr=!0),g(o)})):f(o)})(b({},e,{callback:s=>{var r,n;this.rateLimiter.checkForLimiting(s),400>s.statusCode||(r=(n=this.config).on_request_error)==null||r.call(n,s),e.callback==null||e.callback(s)}}))):e.fireCallbackOnDrop&&(e.callback==null||e.callback({statusCode:0}))}Pn(e){this.Rn?this.Rn.retriableRequest(e):this._send_request(e)}_execute_array(e){vi++;try{var s,r=[],n=[],i=[];Er(e,(a=>{if(a)if(L(s=a[0]))i.push(a);else if(Se(a))try{a.call(this)}catch(l){k.error("Error executing queued PostHog call",a,l)}else L(a)&&s==="alias"?r.push(a):L(a)&&s.indexOf("capture")!==-1&&Se(this[s])?i.push(a):n.push(a)}));var o=function(a,l){Er(a,(function(u){try{if(L(u[0])){var c=l;Z(u,(function(d){c=c[d[0]].apply(c,d.slice(1))}))}else l[u[0]].apply(l,u.slice(1))}catch(d){k.error("Error executing queued PostHog call",u,d)}}))};o(r,this),o(n,this),o(i,this)}finally{vi--}}push(e){if(vi>0&&L(e)&&W(e[0])){var s=Te.prototype[e[0]];Se(s)&&s.apply(this,e.slice(1))}else this._execute_array([e])}capture(e,s,r){var n,i,o,a,l;if(this.__loaded&&this.persistence&&this.sessionPersistence&&this.In){if(this.is_capturing())if(!x(e)&&W(e)){var u=!this.config.opt_out_useragent_filter&&this._is_bot();if(!u||this.config.__preview_capture_bot_pageviews){var c=r!=null&&r.skip_client_rate_limiting?void 0:this.rateLimiter.clientRateLimitContext();if(c==null||!c.isRateLimited){s!=null&&s.$current_url&&!W(s?.$current_url)&&(k.error("Invalid `$current_url` property provided to `posthog.capture`. Input must be a string. Ignoring provided value."),s==null||delete s.$current_url),e!=="$exception"||r!=null&&r.Wn||k.warn("Using `posthog.capture('$exception')` is unreliable because it does not attach required metadata. Use `posthog.captureException(error)` instead, which attaches required metadata automatically."),this.sessionPersistence.update_search_keyword(),this.config.save_campaign_params&&this.sessionPersistence.update_campaign_params(),this.config.save_referrer&&this.sessionPersistence.update_referrer_info(),(this.config.save_campaign_params||this.config.save_referrer)&&this.persistence.set_initial_person_info();var d=new Date,h=r?.timestamp||d,p=Ga(r?.uuid,dt),f={uuid:p,event:e,properties:this.calculateEventProperties(e,s||{},h,p)};e===is&&this.config.__preview_capture_bot_pageviews&&u&&(f.event="$bot_pageview",f.properties.$browser_type="bot"),c&&(f.properties.$lib_rate_limit_remaining_tokens=c.remainingTokens);var g=e==="$feature_flag_called"&&f.properties.$feature_flag_has_experiment===!1&&this.get_property(en)===!0;r?.$set&&!g&&(f.$set=r?.$set);var m=r?.$unset;m&&(f.$unset=m);var _,w,E,I=g?void 0:this.Vn(r?.$set_once,e!==Qa,e===ii);if(I&&(f.$set_once=I),r!=null&&r._noTruncate||(i=this.config.properties_string_max_length,o=f,a=T=>W(T)?T.slice(0,i):T,l=new Set,f=(function T(O,J){if(O!==Object(O))return a?a(O):O;if(!l.has(O)){var z;if(l.add(O),L(O))z=[],Er(O,(oe=>{z.push(T(oe))}));else{var H={};Z(O,((oe,pe)=>{l.has(oe)||(H[pe]=T(oe))})),z=H}return z}})(o)),f.timestamp=h,x(r?.timestamp)||(f.properties.$event_time_override_provided=!0,f.properties.$event_time_override_system_time=d),g&&(f.properties=(function(T,O){O===void 0&&(O=[]);var J={},z=H=>{T[H]!==void 0&&(J[H]=T[H])};return ch.forEach(z),O.forEach(z),J})(f.properties,of)),e===ft.DISMISSED||e===ft.SENT){var F=s?.[hi.SURVEY_ID],P=s?.[hi.SURVEY_ITERATION];id({id:F,current_iteration:P}),f.$set=b({},f.$set,{[(_={id:F,current_iteration:P},w=e===ft.SENT?"responded":"dismissed",E="$survey_"+w+"/"+_.id,_.current_iteration&&_.current_iteration>0&&(E="$survey_"+w+"/"+_.id+"/"+_.current_iteration),E)]:!0})}else e===ft.SHOWN&&(f.$set=b({},f.$set,{[hi.SURVEY_LAST_SEEN_DATE]:new Date().toISOString()}));if(e===Np.SHOWN){var B=s?.[ml.TOUR_TYPE];B&&(f.$set=b({},f.$set,{[ml.TOUR_LAST_SEEN_DATE+"/"+B]:new Date().toISOString()}))}var S=b({},f.properties.$set,f.$set);if(mt(S)||this.setPersonPropertiesForFlags(S),!D(this.config.before_send)){var A=this.Pt(f);if(!A)return;(f=A).uuid=Ga(f.uuid,dt)}this.dn.emit("eventCaptured",f);var R=(n=r?._url)!==null&&n!==void 0?n:this.requestRouter.endpointFor("api",this.analyticsDefaultEndpoint),N={method:"POST",url:R,data:f,compression:"best-available",timestampMode:r?._batchKey==="recordings"||/\/s\/(?:\?|$)/.test(R)?"body":"capture-body",batchKey:r?._batchKey,transport:r?.transport};return!this.config.request_batching||r&&(r==null||!r._batchKey)||r!=null&&r.send_instantly?this.Pn(N):this.In.enqueue(N),f}k.critical("This capture call is ignored due to client rate limiting.")}}else k.error("No event name provided to posthog.capture")}else k.uninitializedWarning("posthog.capture")}_addCaptureHook(e){return this.on("eventCaptured",(s=>e(s.event,s)))}$n(){var e;return(e=this.jn)!==null&&e!==void 0?e:this.jn=new nf(this)}cn(e){this._n.push(e);var s=!0;return()=>{if(s){s=!1;var r=this._n.indexOf(e);r!==-1&&this._n.splice(r,1)}}}calculateEventProperties(e,s,r,n,i){if(r=r||new Date,!this.persistence||!this.sessionPersistence)return s;var o=i?void 0:this.persistence.remove_event_timer(e),a=b({},s);if(a.token=this.config.token,a.$config_defaults=this.config.defaults,this.gn()&&(a[pu]=!0),e==="$snapshot"){var l=b({},this.persistence.properties(),this.sessionPersistence.properties());return a.distinct_id=l.distinct_id,(!W(a.distinct_id)&&!he(a.distinct_id)||Mi(a.distinct_id))&&k.error("Invalid distinct_id for replay event. This indicates a bug in your implementation"),a}var u,c=(function(F,P,B,S){var A,R,N,T;if(S===void 0&&(S=!1),!Pe)return{};var O,J=F?[...vs,...P||[]]:[],z=(function(vr){for(var je=0;qa.length>je;je++){var _r=qa[je],Xt=_r[1],Qt=_r[0].exec(vr),Is=Qt&&(Se(Xt)?Xt(Qt,vr):Xt);if(Is)return Is}return["",""]})(Pe),H=z[0],oe=z[1],pe=(O=typeof navigator<"u"?navigator:void 0)!=null&&O.brave?{brave:!0}:{},Ie={};x(B)||(Ie.detectGoogleSearchApp=B);var _e={},Ce=(A=navigator)==null||(A=A.userAgentData)==null?void 0:A.platform,Re=(R=navigator)==null?void 0:R.maxTouchPoints,ae=v==null||(N=v.screen)==null?void 0:N.width,me=v==null||(T=v.screen)==null?void 0:T.height,ge=v?.devicePixelRatio;x(Ce)||(_e.userAgentDataPlatform=Ce),x(Re)||(_e.maxTouchPoints=Re),x(ae)||(_e.screenWidth=ae),x(me)||(_e.screenHeight=me),x(ge)||(_e.devicePixelRatio=ge);var Ye,Rt,de,Ve,St,ks,Be,Fe,mr=ee(Vo({$os:H,$os_version:oe,$browser:Xc(Pe,navigator.vendor,pe,Ie),$device:Va(Pe),$device_type:(Rt=Pe,de=_e,Fe=Va(Rt),Fe===Nc||Fe===Tc||Fe==="Kobo"||Fe==="Kindle Fire"||Fe===Gc?ps:Fe===er||Fe===ds||Fe===tr||Fe===Oi?"Console":Fe===Lc?"Wearable":Fe?Oe:de?.userAgentDataPlatform==="Android"&&((Ve=de?.maxTouchPoints)!==null&&Ve!==void 0?Ve:0)>0?600>Math.min((St=de?.screenWidth)!==null&&St!==void 0?St:0,(ks=de?.screenHeight)!==null&&ks!==void 0?ks:0)/((Be=de?.devicePixelRatio)!==null&&Be!==void 0?Be:1)?Oe:ps:"Desktop"),$timezone:ju(),$timezone_offset:$p()}),{$current_url:nr(S?Ct(re?.href):re?.href,J,ir),$host:re?.host,$pathname:re?.pathname,$raw_user_agent:Pe.length>1e3?Pe.substring(0,997)+"...":Pe,$browser_version:Fh(Pe,navigator.vendor,pe,Ie),$browser_language:gl(),$browser_language_prefix:(Ye=gl(),typeof Ye=="string"?Ye.split("-")[0]:void 0),$screen_height:v?.screen.height,$screen_width:v?.screen.width,$viewport_height:v?.innerHeight,$viewport_width:v?.innerWidth,$lib:Y.LIB_NAME,$lib_version:Y.LIB_VERSION,$insert_id:Math.random().toString(36).substring(2,10)+Math.random().toString(36).substring(2,10),$time:Date.now()/1e3});return Y.SDK_DIST_CHANNEL&&(mr.$sdk_dist_channel=Y.SDK_DIST_CHANNEL),mr})(this.config.mask_personal_data_properties,this.config.custom_personal_data_properties,this.config.detect_google_search_app,this.config.disable_capture_url_hashes);if(this.sessionManager){var d=this.sessionManager.checkAndGetSessionAndWindowId(i,r.getTime()),h=d.windowId;a.$session_id=d.sessionId,a.$window_id=h}this.sessionPropsManager&&ee(a,this.sessionPropsManager.getSessionProps());try{var p;this.sessionRecording&&ee(a,this.sessionRecording.sdkDebugProperties),a.$sdk_debug_retry_queue_size=(p=this.Rn)==null?void 0:p.length}catch(F){a.$sdk_debug_error_capturing_properties=String(F)}if(this.requestRouter.region===ho&&(a.$lib_custom_api_host=this.config.api_host),u=e!==is||i?e!==ni||i?this.pageViewManager.doEvent():this.pageViewManager.doPageLeave(r):this.pageViewManager.doPageView(r,n),a=ee(a,u),e===is&&C&&(a.title=C.title),!x(o)){var f=r.getTime()-o;a.$duration=parseFloat((f/1e3).toFixed(3))}Pe&&this.config.opt_out_useragent_filter&&(a.$browser_type=this._is_bot()?"bot":"browser");var g=this.persistence.properties(),m=this.sessionPersistence.properties();Z(["$referrer","$referring_domain"],(F=>{F in g&&delete m[F]}));var _={};if(this._n.length>0)for(var w of this._n.slice())try{ee(_,w())}catch(F){k.error("Failed to produce browser extension event properties",F)}(a=ee({},c,g,m,b({},_,a))).$is_identified=this._isIdentified(),L(this.config.property_denylist)?Z(this.config.property_denylist,(function(F){delete a[F]})):k.error(od+this.config.property_denylist+" or property_blacklist config: "+this.config.property_blacklist);var E=this.config.sanitize_properties;E&&(k.error(Fl),a=E(a,e));var I=this.Zn();return a.$process_person_profile=I,I&&!i&&this.Gn("_calculate_event_properties"),a}Vn(e,s,r){var n;if(s===void 0&&(s=!0),r===void 0&&(r=!1),!this.persistence||!this.Zn()||this.mn&&!r)return e;var i=this.persistence.get_initial_props(),o=(n=this.sessionPropsManager)==null?void 0:n.getSetOnceProps(),a=ee({},i,o||{},e||{}),l=this.config.sanitize_properties;return l&&(k.error(Fl),a=l(a,"$set_once")),s&&(this.mn=!0),mt(a)?void 0:a}register(e,s){var r;(r=this.persistence)==null||r.register(e,s)}register_once(e,s,r){var n;(n=this.persistence)==null||n.register_once(e,s,r)}register_for_session(e){var s;(s=this.sessionPersistence)==null||s.register(e),Object.keys(e).forEach((r=>this.yn.add(r))),this.Qn()}unregister(e){var s;(s=this.persistence)==null||s.unregister(e)}unregister_for_session(e){var s;(s=this.sessionPersistence)==null||s.unregister(e),this.yn.delete(e),this.Qn()}Kn(e,s){this.register({[e]:s})}An(){this.yn.forEach((e=>{var s;(s=this.sessionPersistence)==null||s.unregister(e)})),this.yn.clear(),this.Qn()}Qn(){var e;if(this.bn)if(this.config.persistence==="memory"||(e=this.sessionPersistence)!=null&&e.xi||!ce.N())ce.q(this.bn);else{var s=[];this.yn.forEach((r=>s.push(r))),s.length>0?ce.F(this.bn,s):ce.q(this.bn)}}getFeatureFlag(e,s){var r;return(r=this.featureFlags)==null?void 0:r.getFeatureFlag(e,s)}getFeatureFlagPayload(e){var s;return(s=this.featureFlags)==null?void 0:s.getFeatureFlagPayload(e)}getFeatureFlagResult(e,s){var r;return(r=this.featureFlags)==null?void 0:r.getFeatureFlagResult(e,s)}getAllFeatureFlags(){var e,s;return(e=(s=this.featureFlags)==null?void 0:s.getAllFeatureFlags())!==null&&e!==void 0?e:[]}isFeatureEnabled(e,s){var r,n;return(r=(n=this.featureFlags)==null?void 0:n.isFeatureEnabled(e,s))!==null&&r!==void 0?r:s?.defaultValue}reloadFeatureFlags(){var e;(e=this.featureFlags)==null||e.reloadFeatureFlags()}updateFlags(e,s,r){var n;(n=this.featureFlags)==null||n.updateFlags(e,s,r)}updateEarlyAccessFeatureEnrollment(e,s,r){var n;(n=this.featureFlags)==null||n.updateEarlyAccessFeatureEnrollment(e,s,r)}getEarlyAccessFeatures(e,s,r){var n;return s===void 0&&(s=!1),(n=this.featureFlags)==null?void 0:n.getEarlyAccessFeatures(e,s,r)}on(e,s){return this.dn.on(e,s)}onFeatureFlags(e){return this.featureFlags?this.featureFlags.onFeatureFlags(e):(e([],{},{errorsLoading:!0}),()=>{})}onSurveysLoaded(e){return this.surveys?this.surveys.onSurveysLoaded(e):(e([],{isLoaded:!1,error:Ns}),()=>{})}onSessionId(e){var s,r;return(s=(r=this.sessionManager)==null?void 0:r.onSessionId(e))!==null&&s!==void 0?s:()=>{}}getSurveys(e,s){s===void 0&&(s=!1),this.surveys?this.surveys.getSurveys(e,s):e([],{isLoaded:!1,error:Ns})}getActiveMatchingSurveys(e,s){s===void 0&&(s=!1),this.surveys?this.surveys.getActiveMatchingSurveys(e,s):e([],{isLoaded:!1,error:Ns})}renderSurvey(e,s){var r;(r=this.surveys)==null||r.renderSurvey(e,s)}displaySurvey(e,s){var r;s===void 0&&(s=Xp),(r=this.surveys)==null||r.displaySurvey(e,s)}cancelPendingSurvey(e){var s;(s=this.surveys)==null||s.cancelPendingSurvey(e)}canRenderSurvey(e){var s,r;return(s=(r=this.surveys)==null?void 0:r.canRenderSurvey(e))!==null&&s!==void 0?s:{visible:!1,disabledReason:Ns}}canRenderSurveyAsync(e,s){var r,n;return s===void 0&&(s=!1),(r=(n=this.surveys)==null?void 0:n.canRenderSurveyAsync(e,s))!==null&&r!==void 0?r:Promise.resolve({visible:!1,disabledReason:Ns})}Jn(e){return!e||Mi(e)?(k.critical("Unique user id has not been set in posthog.identify"),!1):e===br?(k.critical('The string "'+e+'" was set in posthog.identify which indicates an error. This ID is only used as a sentinel value.'),!1):!["distinct_id","distinctid"].includes(e.toLowerCase())&&!["undefined","null"].includes(e.toLowerCase())||(k.critical('The string "'+e+'" was set in posthog.identify which indicates an error. This ID should be unique to the user and not a hardcoded string.'),!1)}identify(e,s,r){if(!this.__loaded||!this.persistence)return k.uninitializedWarning("posthog.identify");if(he(e)&&(e=e.toString(),k.warn("The first argument to posthog.identify was a number, but it should be a string. It has been converted to a string.")),this.Jn(e)&&this.Gn("posthog.identify")){var n=this.get_distinct_id();this.register({$user_id:e}),this.get_property(sr)||this.register_once({$had_persisted_distinct_id:!0,$device_id:n},""),e!==n&&e!==this.get_property(Bs)&&(this.unregister(Bs),this.register({distinct_id:e}));var i,o=(this.persistence.get_property(He)||es)===es,a=e!==n,l=!a&&o;if(a&&o)this.persistence.set_property(He,Tt),this.setPersonPropertiesForFlags({$set:s||{},$set_once:r||{}},!1),this.capture(ii,{distinct_id:e,$anon_distinct_id:n},{$set:s||{},$set_once:r||{}}),this.Sn=mi(e,s,r),(i=this.featureFlags)==null||i.setAnonymousDistinctId(n);else if(l){this.persistence.set_property(He,Tt);var u=s||{},c=r||{};this.setPersonPropertiesForFlags({$set:u,$set_once:c},!1),this.capture("$set",{$set:u,$set_once:c}),this.Sn=mi(e,s,r)}else(s||r)&&this.setPersonProperties(s,r);a?(this.reloadFeatureFlags(),this.featureFlags?this.featureFlags.resetFlagCallReported():this.unregister(Wt)):l&&(s||r)&&this.reloadFeatureFlags()}}setPersonProperties(e,s){if((e||s)&&this.Gn("posthog.setPersonProperties")){var r=mi(this.get_distinct_id(),e,s);this.Sn!==r?(this.setPersonPropertiesForFlags({$set:e||{},$set_once:s||{}},!0),this.capture("$set",{$set:e||{},$set_once:s||{}}),this.Sn=r):k.info("A duplicate setPersonProperties call was made with the same properties. It has been ignored.")}}unsetPersonProperties(e){var s,r=(L(e)?e:[e]).filter((n=>W(n)&&n.length>0));r.length!==0&&this.Gn("posthog.unsetPersonProperties")&&((s=this.featureFlags)==null||s.unsetPersonPropertiesForFlags(r,!0),this.capture("$set",{$unset:r}),this.Sn=null)}group(e,s,r){if(e&&s){var n=this.getGroups(),i=n[e]!==s;if(i&&this.resetGroupPropertiesForFlags(e),this.register({$groups:b({},n,{[e]:s})}),i||r){var o={$group_type:e,$group_key:s};r&&(o.$group_set=r),this.capture(Qa,o)}r&&this.setGroupPropertiesForFlags({[e]:r}),i&&!r&&this.reloadFeatureFlags()}else k.error("posthog.group requires a group type and group key")}resetGroups(){this.register({$groups:{}}),this.resetGroupPropertiesForFlags(),this.reloadFeatureFlags()}setPersonPropertiesForFlags(e,s){var r;s===void 0&&(s=!0),(r=this.featureFlags)==null||r.setPersonPropertiesForFlags(e,s)}resetPersonPropertiesForFlags(e){var s;e===void 0&&(e=!0),(s=this.featureFlags)==null||s.resetPersonPropertiesForFlags(e)}setGroupPropertiesForFlags(e,s){var r;s===void 0&&(s=!0),this.Gn("posthog.setGroupPropertiesForFlags")&&((r=this.featureFlags)==null||r.setGroupPropertiesForFlags(e,s))}resetGroupPropertiesForFlags(e){var s;(s=this.featureFlags)==null||s.resetGroupPropertiesForFlags(e)}reset(e){this.Yn(e)}Yn(e,s){var r,n,i,o,a,l,u,c,d,h;if(s===void 0&&(s=!1),k.info("reset"),!this.__loaded)return k.uninitializedWarning("posthog.reset");var p,f=this.get_property(sr),g=this.get_property(ri),m=this.get_property(qt),_=this.is_capturing();if(this.consent.reset(),s||!_||this.is_capturing()||console.warn("[PostHog.js]","reset() cleared the stored consent, and capturing is now off because of `opt_out_capturing_by_default`. Call opt_in_capturing() again, and prefer calling reset() before opting in rather than after."),(r=this.persistence)==null||r.clear(),(n=this.sessionPersistence)==null||n.clear(),this.yn.clear(),this.Qn(),x(m)||(p=this.persistence)==null||p.register({[qt]:m}),(i=this.surveys)==null||i.reset(),(o=this.Un)==null||o.stop(),(a=this.featureFlags)==null||a.reset(),(l=this.conversations)==null||l.reset(),(u=this.logs)==null||u.reset(),(c=this.metrics)==null||c.reset(),(d=this.persistence)==null||d.set_property(He,es),(h=this.sessionManager)==null||h.resetSessionId(),this.Sn=null,this.config.cookieless_mode===ht)this.register_once({distinct_id:br,$device_id:null},"");else{var w=this.config.get_device_id(dt());this.register_once({distinct_id:w,$device_id:e?w:f},""),e||x(g)||this.register({[ri]:g})}this.register({$last_posthog_reset:new Date().toISOString()},1),delete this.config.identity_distinct_id,delete this.config.identity_hash,this.reloadFeatureFlags()}shutdown(e){var s=this;return X((function*(){var r,n,i,o,a,l,u;if(s.__loaded){(r=s.Un)==null||r.stop(),(n=s.jn)==null||n.dispose(),(i=s.sessionRecording)==null||i.dispose(),(o=s.logs)==null||o.flushLogs("sendBeacon"),(a=s.metrics)==null||a.flush("sendBeacon"),(l=s.In)==null||l.unload(),(u=s.Rn)==null||u.unload();try{var c;(c=s.featureFlags)==null||c.destroy()}catch(d){k.error("Error while destroying feature flags",d)}}else k.uninitializedWarning("posthog.shutdown")}))()}setIdentity(e,s){var r;this.config.identity_distinct_id=e,this.config.identity_hash=s,this.alias(e),(r=this.conversations)==null||r.Xn()}clearIdentity(){var e;delete this.config.identity_distinct_id,delete this.config.identity_hash,(e=this.conversations)==null||e.ts()}get_distinct_id(){return this.get_property("distinct_id")}getGroups(){return this.get_property("$groups")||{}}get_session_id(){var e,s;return(e=(s=this.sessionManager)==null?void 0:s.checkAndGetSessionAndWindowId(!0).sessionId)!==null&&e!==void 0?e:""}get_session_replay_url(e){if(!this.sessionManager)return"";var s=this.sessionManager.checkAndGetSessionAndWindowId(!0),r=s.sessionStartTimestamp,n=this.requestRouter.endpointFor("ui","/project/"+this.config.token+"/replay/"+s.sessionId);if(e!=null&&e.withTimestamp&&r){var i,o=(i=e.timestampLookBack)!==null&&i!==void 0?i:10;if(!r)return n;n+="?t="+Math.max(Math.floor((new Date().getTime()-r)/1e3)-o,0)}return n}alias(e,s){return e===this.get_property(au)?(k.critical("Attempting to create alias for existing People user - aborting."),-2):this.Gn("posthog.alias")?(x(s)&&(s=this.get_distinct_id()),e!==s?(this.Kn(Bs,e),this.capture("$create_alias",{alias:e,distinct_id:s})):(k.warn("alias matches current distinct_id - skipping api call."),this.identify(e),-1)):void 0}set_config(e){var s=b({},this.config);if(te(e)){var r,n,i,o,a,l,u,c,d,h,p,f;ee(this.config,Pl(e));var g=this.En();(r=this.persistence)==null||r.update_config(this.config,s,g),this.sessionPersistence=this.config.persistence==="sessionStorage"||this.config.persistence==="memory"?this.persistence:new ui(b({},this.config,{persistence:"sessionStorage"}),g,!1);var m=this.Cn(this.config.debug);Ke(m)&&(this.config.debug=m),Ke(this.config.debug)&&(this.config.debug?(Y.DEBUG=!0,Q.N()&&Q.F("ph_debug",!0),k.info("set_config",{config:e,oldConfig:s,newConfig:b({},this.config)})):(Y.DEBUG=!1,Q.N()&&Q.q("ph_debug"))),(n=this.featureFlags)==null||n.updateConfig==null||n.updateConfig(this.config,this.Qi()),(i=this.exceptionObserver)==null||i.onConfigChange(),(o=this.exceptions)==null||o.onConfigChange(),(a=this.sessionRecording)==null||a.startIfEnabledOrStop(),(l=this.tracingHeaders)==null||l.startIfEnabledOrStop(),(u=this.autocapture)==null||u.startIfEnabled(),(c=this.heatmaps)==null||c.startIfEnabled(),(d=this.exceptionObserver)==null||d.startIfEnabledOrStop(),(h=this.deadClicksAutocapture)==null||h.startIfEnabledOrStop(),(p=this.surveys)==null||p.loadIfEnabled(),this.es(),(f=this.externalIntegrations)==null||f.startIfEnabledOrStop()}}_overrideSDKInfo(e,s){Y.LIB_NAME=e,Y.LIB_VERSION=s}startSessionRecording(e){var s,r,n,i,o,a=e===!0,l={sampling:a||!(e==null||!e.sampling),linked_flag:a||!(e==null||!e.linked_flag),url_trigger:a||!(e==null||!e.url_trigger),event_trigger:a||!(e==null||!e.event_trigger)};Object.values(l).some(Boolean)&&((s=this.sessionManager)==null||s.checkAndGetSessionAndWindowId(),l.sampling&&((r=this.sessionRecording)==null||r.overrideSampling()),l.linked_flag&&((n=this.sessionRecording)==null||n.overrideLinkedFlag()),l.url_trigger&&((i=this.sessionRecording)==null||i.overrideTrigger("url")),l.event_trigger&&((o=this.sessionRecording)==null||o.overrideTrigger("event"))),this.set_config({disable_session_recording:!1})}stopSessionRecording(){this.set_config({disable_session_recording:!0})}sessionRecordingStarted(){var e;return!((e=this.sessionRecording)==null||!e.started)}captureException(e,s){if(this.exceptions){var r=new Error("PostHog syntheticException"),n=this.exceptions.buildProperties(e,{handled:!0,syntheticException:r});return this.exceptions.sendExceptionEvent(b({},n,s))}}addExceptionStep(e,s){var r;(r=this.exceptions)==null||r.addExceptionStep(e,s)}captureLog(e){var s;(s=this.logs)==null||s.captureLog(e)}get logger(){var e,s;return(e=(s=this.logs)==null?void 0:s.logger)!==null&&e!==void 0?e:Te.rs}startExceptionAutocapture(e){this.set_config({capture_exceptions:e==null||e})}stopExceptionAutocapture(){this.set_config({capture_exceptions:!1})}loadToolbar(e){var s,r;return(s=(r=this.toolbar)==null?void 0:r.loadToolbar(e))!==null&&s!==void 0&&s}get_property(e){var s;return(s=this.persistence)==null?void 0:s.props[e]}getSessionProperty(e){var s;return(s=this.sessionPersistence)==null?void 0:s.props[e]}toString(){var e,s=(e=this.config.name)!==null&&e!==void 0?e:os;return s!==os&&(s=os+"."+s),s}_isIdentified(){var e,s;return((e=this.persistence)==null?void 0:e.get_property(He))===Tt||((s=this.sessionPersistence)==null?void 0:s.get_property(He))===Tt}Zn(){var e,s;return!(this.config.person_profiles==="never"||this.config.person_profiles===to&&!this._isIdentified()&&mt(this.getGroups())&&((e=this.persistence)==null||(e=e.props)==null||!e[Bs])&&((s=this.persistence)==null||(s=s.props)==null||!s[rn]))}zn(){return this.config.capture_pageleave===!0||this.config.capture_pageleave==="if_capture_pageview"&&(this.config.capture_pageview===!0||this.config.capture_pageview==="history_change")}createPersonProfile(){this.Zn()||this.Gn("posthog.createPersonProfile")&&this.setPersonProperties({},{})}setInternalOrTestUser(){this.Gn("posthog.setInternalOrTestUser")&&this.setPersonProperties({$internal_or_test_user:!0})}Gn(e){return this.config.person_profiles==="never"?(k.error(e+' was called, but process_person is set to "never". This call will be ignored.'),!1):(this.Kn(rn,!0),!0)}En(){if(this.config.cookieless_mode==="always")return!0;var e=this.consent.isOptedOut();return this.config.disable_persistence||e&&!(!this.config.opt_out_persistence_by_default&&this.config.cookieless_mode!==Ht)}es(){var e,s,r,n,i=this.En();return((e=this.persistence)==null?void 0:e.xi)!==i&&((r=this.persistence)==null||r.set_disabled(i)),((s=this.sessionPersistence)==null?void 0:s.xi)!==i&&((n=this.sessionPersistence)==null||n.set_disabled(i)),i&&(this.yn.clear(),this.Qn()),i}opt_in_capturing(e){var s;if(this.config.cookieless_mode!==ht){if(this.gn()){var r,n,i,o,a;this.Yn(!0,!0),(r=this.sessionManager)==null||r.destroy(),(n=this.pageViewManager)==null||n.destroy(),this.sessionManager=new xl(this),this.pageViewManager=new fl(this),this.persistence&&(this.sessionPropsManager=new Sl(this,this.sessionManager,this.persistence));var l,u=(i=(o=this.config.__extensionClasses)==null?void 0:o.sessionRecording)!==null&&i!==void 0?i:(a=Te.__defaultExtensionClasses)==null?void 0:a.sessionRecording;u&&(this.sessionRecording=this.pn(this.sessionRecording,new u(this)),this.hn&&((l=this.sessionRecording)==null||l.onRemoteConfig==null||l.onRemoteConfig(this.hn)))}var c,d;this.consent.optInOut(!0),this.es(),this.Bn(),(s=this.sessionRecording)==null||s.startIfEnabledOrStop(),this.config.cookieless_mode==Ht&&((c=this.surveys)==null||c.loadIfEnabled()),(x(e?.captureEventName)||e!=null&&e.captureEventName)&&this.capture((d=e?.captureEventName)!==null&&d!==void 0?d:"$opt_in",e?.captureProperties,{send_instantly:!0}),this.config.capture_pageview&&this.Hn()}else k.warn(Cl)}opt_out_capturing(){var e,s,r;this.config.cookieless_mode!==ht?(this.config.cookieless_mode===Ht&&this.consent.isOptedIn()&&this.Yn(!0,!0),this.consent.optInOut(!1),this.es(),this.config.cookieless_mode===Ht&&(this.register({distinct_id:br,$device_id:null}),(e=this.sessionRecording)==null||e.stopRecording(),this.sessionRecording=void 0,(s=this.sessionManager)==null||s.destroy(),(r=this.pageViewManager)==null||r.destroy(),this.sessionManager=void 0,this.sessionPropsManager=void 0,this.config.capture_pageview&&this.Hn(),this.Bn())):k.warn(Cl)}has_opted_in_capturing(){return this.consent.isOptedIn()}has_opted_out_capturing(){return this.consent.isOptedOut()}get_explicit_consent_status(){var e=this.consent.consent;return e===1?"granted":e===0?"denied":"pending"}is_capturing(){return this.config.cookieless_mode===ht||(this.config.cookieless_mode===Ht?this.consent.isRejected()||this.consent.isOptedIn():!this.has_opted_out_capturing())}clear_opt_in_out_capturing(){this.consent.reset(),this.es()}_is_bot(){return ke?Qu(ke,this.config.custom_blocked_useragents):void 0}Hn(){C&&(C.visibilityState==="visible"?this.wn||(this.wn=!0,this.capture(is,{title:C.title},{send_instantly:!0}),this.kn&&(C.removeEventListener(nn,this.kn),this.kn=null)):this.kn||(this.kn=this.Hn.bind(this),ne(C,nn,this.kn)))}debug(e){e===!1?(v?.console.log("You've disabled debug mode."),this.set_config({debug:!1})):(v?.console.log("You're now in debug mode. All calls to PostHog will be logged in your console.\nYou can disable this with `posthog.debug(false)`."),this.set_config({debug:!0}))}Qi(){var e=this.Mn||{};return"advanced_disable_flags"in e?!!e.advanced_disable_flags:this.config.advanced_disable_flags!==!1?!!this.config.advanced_disable_flags:this.config.advanced_disable_decide===!0?(k.warn("Config field 'advanced_disable_decide' is deprecated. Please use 'advanced_disable_flags' instead. The old field will be removed in a future major version."),!0):(function(s,r,n,i,o){var a=r in s&&!D(s[r]),l=n in s&&!D(s[n]);return a?s[r]:!!l&&(o&&o.warn("Config field '"+n+"' is deprecated. Please use '"+r+"' instead. The old field will be removed in a future major version."),s[n])})(e,"advanced_disable_flags","advanced_disable_decide",0,k)}Pt(e){var s;if(D(this.config.before_send))return e;var r=Object.keys((s=e.properties)!==null&&s!==void 0?s:{}).filter(mh),n=L(this.config.before_send)?this.config.before_send:[this.config.before_send],i=e;for(var o of n){if(i=o(i),D(i)){var a="Event '"+e.event+"' was rejected in beforeSend function";return gh(e.event)?k.warn(a+". This can cause unexpected behavior."):k.info(a),null}i.properties&&!mt(i.properties)||k.warn("Event '"+e.event+"' has no properties after beforeSend function, this is likely an error.")}for(var l of r)if(i.properties&&D(i.properties[l]))return k.warn("Event '"+e.event+"' had its '"+l+"' property removed in a beforeSend function. This property is required for ingestion, so the event will be dropped."),null;return i}getPageViewId(){var e;return(e=this.pageViewManager.ui)==null?void 0:e.pageViewId}captureTraceFeedback(e,s){this.capture("$ai_feedback",{$ai_trace_id:String(e),$ai_feedback_text:s})}captureTraceMetric(e,s,r){this.capture("$ai_metric",{$ai_trace_id:String(e),$ai_metric_name:s,$ai_metric_value:String(r)})}Cn(e){var s=Ke(e)&&!e,r=Q.N()&&Q.P("ph_debug")==="true";return!s&&(!!r||e)}}Te.__defaultExtensionClasses={},Te.rs=(()=>{var t=()=>{};return{trace:t,debug:t,info:t,warn:t,error:t,fatal:t}})(),(function(t,e){for(var s=0;e.length>s;s++)t.prototype[e[s]]=np(t.prototype[e[s]])})(Te,["identify"]);class Al{constructor(e){this.disabled=e===!1;var s=te(e)?e:{};this.thresholdPx=s.threshold_px||30,this.timeoutMs=s.timeout_ms||1e3,this.clickCount=s.click_count||3,this.clicks=[]}isRageClick(e,s,r){if(this.disabled)return!1;var n=this.clicks[this.clicks.length-1];if(n&&Math.abs(e-n.x)+Math.abs(s-n.y)r-n.timestamp){if(this.clicks.push({x:e,y:s,timestamp:r}),this.clicks.length===this.clickCount)return!0}else this.clicks=[{x:e,y:s,timestamp:r}];return!1}}var yi="$copy_autocapture",wi=se("[AutoCapture]");function bi(t,e){return e.length>t?e.slice(0,t)+"...":e}function cf(t){if(t.previousElementSibling)return t.previousElementSibling;var e=t;do e=e.previousSibling;while(e&&!Ft(e));return e}function uf(t,e){var s,r,n=e.e,i=e.maskAllElementAttributes,o=e.maskAllText,a=e.elementAttributeIgnoreList,l=e.elementsChainAsString,u=e.disableCaptureUrlHashes;if(!Ft(t))return{props:{}};for(var c=[t],d=new Set([t]),h=t;h.parentNode&&!Me(h,"body")&&Su>c.length;)if(Eu(h.parentNode)){var p=h.parentNode.host;if(d.has(p))break;d.add(p),c.push(p),h=p}else{if(!Ft(h.parentNode)||d.has(h.parentNode))break;d.add(h.parentNode),c.push(h.parentNode),h=h.parentNode}var f,g,m=[],_={},w=!1,E=!1;if(Z(c,(S=>{var A=no(S);if(Me(S,"a")){var R=S.getAttribute("href");w=!!(A&&R&&Ks(R))&&(u?Ct(R):R)}M(ln(S),"ph-no-capture")&&(E=!0),m.push((function(T,O,J,z,H){H===void 0&&(H=!1);var oe=T.tagName.toLowerCase(),pe={tag_name:oe};Ko.indexOf(oe)>-1&&!J&&(pe.$el_text=oe.toLowerCase()==="a"||oe.toLowerCase()==="button"?bi(1024,dl(T)):bi(1024,rr(T)));var Ie=ln(T);Ie.length>0&&(pe.classes=Ie.filter((function(ae){return ae!==""}))),Z(T.attributes,(function(ae){var me;if((!Fu(T)||["name","id","class","aria-label"].indexOf(ae.name)!==-1)&&(z==null||!z.includes(ae.name))&&!O&&Ks(ae.value)&&(!W(me=ae.name)||me.substring(0,10)!=="_ngcontent"&&me.substring(0,7)!=="_nghost")){var ge=ae.value;ae.name==="class"&&(ge=Go(ge).join(" ")),pe["attr__"+ae.name]=bi(1024,ae.name==="href"&&H?Ct(ge):ge)}}));for(var _e=1,Ce=1,Re=T;Re=cf(Re);)_e++,Re.tagName===T.tagName&&Ce++;return pe.nth_child=_e,pe.nth_of_type=Ce,pe})(S,i,o,a,u));var N=(function(T){if(!no(T))return{};var O={};return Z(T.attributes,(function(J){if(J.name&&J.name.indexOf("data-ph-capture-attribute")===0){var z=J.name.replace("data-ph-capture-attribute-",""),H=J.value;z&&H&&Ks(H)&&(O[z]=H)}})),O})(S);ee(_,N)})),E)return{props:{},explicitNoCapture:E};if(o||(m[0].$el_text=Me(t,"a")||Me(t,"button")?dl(t):rr(t)),w){var I,F;m[0].attr__href=w;var P=(I=cn(w))==null?void 0:I.host,B=v==null||(F=v.location)==null?void 0:F.host;P&&B&&P!==B&&(f=w)}return{props:ee({$event_type:n.type,$ce_version:1},l?{}:{$elements:m},{$elements_chain:(g=m,(function(S){return S.map((A=>{var R,N,T="";if(A.tag_name&&(T+=A.tag_name),A.attr_class)for(var O of(A.attr_class.sort(),A.attr_class))T+="."+O.replace(/"/g,"");var J=b({},A.text?{text:A.text}:{},{"nth-child":(R=A.nth_child)!==null&&R!==void 0?R:0,"nth-of-type":(N=A.nth_of_type)!==null&&N!==void 0?N:0},A.href?{href:A.href}:{},A.attr_id?{attr_id:A.attr_id}:{},A.attributes),z={};return Or(J).sort(((H,oe)=>H[0].localeCompare(oe[0]))).forEach((H=>{var oe=H[1];return z[hl(H[0].toString())]=hl(oe.toString())})),(T+=":")+Or(z).map((H=>H[0]+'="'+H[1]+'"')).join("")})).join(";")})((function(S){return S.map((A=>{var R,N,T={text:(R=A.$el_text)==null?void 0:R.slice(0,400),tag_name:A.tag_name,href:(N=A.attr__href)==null?void 0:N.slice(0,2048),attr_class:Sp(A),attr_id:A.attr__id,nth_child:A.nth_child,nth_of_type:A.nth_of_type,attributes:{}};return Or(A).filter((O=>O[0].indexOf("attr__")===0)).forEach((O=>T.attributes[O[0]]=O[1])),T}))})(g)))},(s=m[0])!=null&&s.$el_text?{$el_text:(r=m[0])==null?void 0:r.$el_text}:{},f&&n.type==="click"?{$external_click_url:f}:{},_)}}var Ms=se("[ExceptionAutocapture]"),$l=()=>{},df=se("[TracingHeaders]"),Lt=se("[Web Vitals]"),Rl=9e5,Tl="disabled",Nl="lazy_loading",Ls="awaiting_config",Fr="missing_config";se("[SessionRecording]"),se("[SessionRecording]");var po="[SessionRecording]",at=se(po),hf=se("[Heatmaps]");function Ei(t){return te(t)&&"clientX"in t&&"clientY"in t&&he(t.clientX)&&he(t.clientY)}var Pr=se("[Product Tours]"),Si=t=>{var e;return!t.config.disable_product_tours&&!((e=t.persistence)==null||!e.get_property(Wo))},pf=["$set_once","$set"],Ze=se("[SiteApps]"),Ml="Error while initializing PostHog app with config id ";function rs(t,e,s){if(D(t))return!1;switch(s){case"exact":return t===e;case"contains":var r=e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/_/g,".").replace(/%/g,".*");return new RegExp(r,"i").test(t);case"regex":try{return new RegExp(e).test(t)}catch{return!1}default:return!1}}class ff{constructor(e){this.ns=new Xo,this.ss=(s,r)=>this.os(s,r)&&this.ls(s,r)&&this.us(s,r)&&this.hs(s,r),this.os=(s,r)=>r==null||!r.event||s?.event===r?.event,this._instance=e,this.ds=new Set,this.vs=new Set}init(){var e,s;x((e=this._instance)==null?void 0:e._addCaptureHook)||(s=this._instance)==null||s._addCaptureHook(((r,n)=>{this.on(r,n)}))}register(e){var s,r;if(!x((s=this._instance)==null?void 0:s._addCaptureHook)&&(e.forEach((o=>{var a,l;(a=this.vs)==null||a.add(o),(l=o.steps)==null||l.forEach((u=>{var c;(c=this.ds)==null||c.add(u?.event||"")}))})),(r=this._instance)!=null&&r.autocapture)){var n,i=new Set;e.forEach((o=>{var a;(a=o.steps)==null||a.forEach((l=>{l!=null&&l.selector&&i.add(l?.selector)}))})),(n=this._instance)==null||n.autocapture.setElementSelectors(i)}}on(e,s){var r;s!=null&&e.length!=0&&(this.ds.has(e)||this.ds.has(s.event))&&this.vs&&((r=this.vs)==null?void 0:r.size)>0&&this.vs.forEach((n=>{this.cs(s,n)&&this.ns.emit("actionCaptured",n.name)}))}fs(e){this.onAction("actionCaptured",(s=>e(s)))}cs(e,s){if(s?.steps==null)return!1;for(var r of s.steps)if(this.ss(e,r))return!0;return!1}onAction(e,s){return this.ns.on(e,s)}ls(e,s){if(s!=null&&s.url){var r,n=e==null||(r=e.properties)==null?void 0:r.$current_url;if(!n||typeof n!="string"||!rs(n,s.url,s.url_matching||"contains"))return!1}return!0}us(e,s){return!!this.ps(e,s)&&!!this.gs(e,s)&&!!this.ys(e,s)}ps(e,s){var r;if(s==null||!s.href)return!0;var n=this.bs(e);if(n.length>0)return n.some((a=>rs(a.href,s.href,s.href_matching||"exact")));var i,o=(e==null||(r=e.properties)==null?void 0:r.$elements_chain)||"";return!!o&&rs((i=o.match(/(?::|")href="(.*?)"/))?i[1]:"",s.href,s.href_matching||"exact")}gs(e,s){var r;if(s==null||!s.text)return!0;var n=this.bs(e);if(n.length>0)return n.some((u=>rs(u.text,s.text,s.text_matching||"exact")||rs(u.$el_text,s.text,s.text_matching||"exact")));var i,o,a,l=(e==null||(r=e.properties)==null?void 0:r.$elements_chain)||"";return!!l&&(i=(function(u){for(var c,d=[],h=/(?::|")text="(.*?)"/g;!D(c=h.exec(u));)d.includes(c[1])||d.push(c[1]);return d})(l),o=s.text,a=s.text_matching||"exact",i.some((u=>rs(u,o,a))))}ys(e,s){var r,n;if(s==null||!s.selector)return!0;var i=e==null||(r=e.properties)==null?void 0:r.$element_selectors;if(i!=null&&i.includes(s.selector))return!0;var o=(e==null||(n=e.properties)==null?void 0:n.$elements_chain)||"";if(s.selector_regex&&o)try{return new RegExp(s.selector_regex).test(o)}catch{return!1}return!1}bs(e){var s;return(e==null||(s=e.properties)==null?void 0:s.$elements)==null?[]:e?.properties.$elements}hs(e,s){return s==null||!s.properties||s.properties.length===0||sd(s.properties.reduce(((r,n)=>{var i=L(n.value)?n.value.map(String):n.value!=null?[String(n.value)]:[];return r[n.key]={values:i,operator:n.operator||"exact"},r}),{}),e?.properties)}}class gf{constructor(e){var s;this._s=[],this._instance=e,this.ws=new Map,this.ks=new Map,this.xs=new Map,(s=this._instance)==null||s.onSessionId==null||s.onSessionId((r=>this.Ss(r)))}Cs(e){return!1}Ms(){return null}Ts(e){}Es(){}Is(e,s){return!!e&&sd(e.propertyFilters,s?.properties)}Ps(e,s){var r=new Map;return e.forEach((n=>{var i;(i=n.conditions)==null||(i=i[s])==null||(i=i.values)==null||i.forEach((o=>{if(o!=null&&o.name){var a=r.get(o.name)||[];a.push(n.id),r.set(o.name,a)}}))})),r}Rs(e,s,r){var n=(r===As.Activation?this.ws:this.ks).get(e),i=[];return this.As((o=>{i=o.filter((a=>n?.includes(a.id)))})),i.filter((o=>{var a,l=(a=o.conditions)==null||(a=a[r])==null||(a=a.values)==null?void 0:a.find((u=>u.name===e));return this.Is(l,s)}))}register(e){var s;x((s=this._instance)==null?void 0:s._addCaptureHook)||(this.Fs(e),this.Ls(e))}Ls(e){var s=e.filter((r=>{var n,i;return((n=r.conditions)==null?void 0:n.actions)&&((i=r.conditions)==null||(i=i.actions)==null||(i=i.values)==null?void 0:i.length)>0}));s.length!==0&&(this.Os==null&&(this.Os=new ff(this._instance),this.Os.init(),this.Os.fs((r=>{this.onAction(r)}))),s.forEach((r=>{var n,i,o,a,l;r.conditions&&(n=r.conditions)!=null&&n.actions&&(i=r.conditions)!=null&&(i=i.actions)!=null&&i.values&&((o=r.conditions)==null||(o=o.actions)==null||(o=o.values)==null?void 0:o.length)>0&&((a=this.Os)==null||a.register(r.conditions.actions.values),(l=r.conditions)==null||(l=l.actions)==null||(l=l.values)==null||l.forEach((u=>{if(u&&u.name){var c=this.xs.get(u.name);c&&c.push(r.id),this.xs.set(u.name,c||[r.id])}})))})))}Fs(e){var s,r=e.filter((i=>{var o,a;return((o=i.conditions)==null?void 0:o.events)&&((a=i.conditions)==null||(a=a.events)==null||(a=a.values)==null?void 0:a.length)>0})),n=e.filter((i=>{var o,a;return((o=i.conditions)==null?void 0:o.cancelEvents)&&((a=i.conditions)==null||(a=a.cancelEvents)==null||(a=a.values)==null?void 0:a.length)>0}));r.length===0&&n.length===0||((s=this._instance)==null||s._addCaptureHook(((i,o)=>{this.onEvent(i,o)})),this.ws=this.Ps(e,As.Activation),this.ks=this.Ps(e,As.Cancellation))}onEvent(e,s){var r,n,i=this.Ds(),o=(s==null||(r=s.properties)==null?void 0:r.$survey_id)||(s==null||(n=s.properties)==null?void 0:n.$product_tour_id);if(o&&this.getActivatedIds().includes(o)){var a=this.$s(e,o);if(a==="consume")return i.info("event consumed activated item, removing it",{event:e,itemId:o}),void this.Ns([o]);if(a==="persist")return i.info("shown item promoted to persisted activation",{event:e,itemId:o}),this.qs(o),void this.js([o])}if(this.ks.has(e)){var l=this.Rs(e,s,As.Cancellation);l.length>0&&(i.info("cancel event matched, cancelling items",{event:e,itemsToCancel:l.map((c=>c.id))}),this.Ns(l.map((c=>c.id))),l.forEach((c=>this.Bs(c.id))))}if(this.ws.has(e)){i.info("event name matched",{event:e,eventPayload:s,items:this.ws.get(e)});var u=this.Rs(e,s,As.Activation);this.Hs(u.map((c=>c.id)))}}onAction(e){this.xs.has(e)&&this.Hs(this.xs.get(e)||[])}Hs(e){var s;if(e.length!==0){var r=!((s=this._instance)==null||s.get_session_id==null||!s.get_session_id()),n=[];for(var i of e)r&&this.Cs(i)?this.qs(i)&&this.Us(i):n.push(i);n.length>0&&(this._s=[...new Set([...this._s,...n])]),this.Ds().info("updating activated items",{activatedItems:this.getActivatedIds()})}}qs(e){this._s=this._s.filter((r=>r!==e));var s=this.zs();return!s.includes(e)&&(this.Ws([...s,e]),this.Vs(),!0)}Ns(e){var s=new Set(e);this._s=this._s.filter((i=>!s.has(i)));var r=this.Zs(),n=r.filter((i=>!s.has(i)));n.length!==r.length&&(this.Ws(n),n.length===0&&this.Gs()),this.js(e)}Qs(){var e,s=this.Ms();if(!s)return{};var r=(e=this._instance)==null||(e=e.persistence)==null?void 0:e.props[s];return r&&typeof r=="object"?r:{}}Us(e){if(this.Ms()){var s=this.Qs();this.Ts(b({},s,{[e]:Date.now()}))}}js(e){if(this.Ms()){var s=this.Qs(),r={},n=!1;for(var i of Object.entries(s)){var o=i[0],a=i[1];e.includes(o)?n=!0:r[o]=a}n&&(mt(r)?this.Es():this.Ts(r))}}Ks(){this.Ms()&&this.Es()}getActivationTimestamp(e){if(this.zs().includes(e)){var s=this.Qs()[e];return he(s)?s:void 0}}Zs(){var e,s=this.Js();return((e=this._instance)==null||(e=e.persistence)==null?void 0:e.props[s])||[]}zs(){var e,s,r=this.Zs();if(r.length===0)return[];var n=(e=this._instance)==null||(e=e.persistence)==null?void 0:e.props[this.Ys()],i=(s=this._instance)==null||s.get_session_id==null?void 0:s.get_session_id();return i&&n===i?r:[]}Vs(){var e,s=(e=this._instance)==null||e.get_session_id==null?void 0:e.get_session_id();s&&this.Xs(s)}Gs(){this.ta()}Ss(e){var s,r=(s=this._instance)==null||(s=s.persistence)==null?void 0:s.props[this.Ys()];if(r&&r!==e){var n=this.Zs(),i=this.Qs();n.length>0&&(this.Ws([]),n.filter((o=>he(i[o]))).forEach((o=>this.Bs(o)))),this.Gs(),this.Ks()}}getActivatedIds(){return[...new Set([...this.zs(),...this._s])].filter((e=>!this.ea(e)))}reset(){this._s=[],this.Zs().length>0&&this.Ws([]),this.Gs(),this.Ks()}getEventToItemsMap(){return this.ws}ia(){return this.Os}}class mf extends gf{constructor(e){super(e)}Js(){return Yi}Ys(){return Nr}Ms(){return Mr}Ts(e){var s;(s=this._instance)==null||(s=s.persistence)==null||s.register({[Mr]:e})}Es(){var e;(e=this._instance)==null||(e=e.persistence)==null||e.unregister(Mr)}Cs(e){var s,r;this.As((i=>{r=i.find((o=>o.id===e))}));var n=(s=r)==null||(s=s.appearance)==null?void 0:s.surveyPopupDelaySeconds;return he(n)&&n>0}ra(){return ft.SHOWN}As(e){var s;(s=this._instance)==null||s.getSurveys(e)}Bs(e){var s;(s=this._instance)==null||s.cancelPendingSurvey(e)}Ds(){return q}Ws(e){var s;(s=this._instance)==null||(s=s.persistence)==null||s.register({[Yi]:e})}Xs(e){var s;(s=this._instance)==null||(s=s.persistence)==null||s.register({[Nr]:e})}ta(){var e;(e=this._instance)==null||(e=e.persistence)==null||e.unregister(Nr)}ea(){return!1}$s(e,s){var r;this.As((i=>{r=i.find((o=>o.id===s))}));var n=!r||(function(i){var o;return rd(i)&&!((o=i.conditions)==null||(o=o.events)==null||!o.repeatedActivation)||i.schedule==="always"})(r);return n?e===ft.SHOWN?"consume":"ignore":e===ft.SHOWN?"persist":e===ft.DISMISSED||e===ft.SENT?"consume":"ignore"}getSurveys(){return this.getActivatedIds()}getEventToSurveys(){return this.getEventToItemsMap()}}var Ar="SDK is not enabled or survey functionality is not yet loaded",Ll="Disabled. Not loading surveys.",vf=v!=null&&v.location?un(v.location.hash,"__posthog")||un(location.hash,"state"):null,Ol="_postHogToolbarParams",Dl=se("[Toolbar]"),Bl=se("[FeatureFlags]");class _f{constructor(e,s){s===void 0&&(s=!1),this.na=!1,this.update(e,s)}update(e,s){this.sa=((r,n)=>{var i,o,a,l;return{bootstrap:{featureFlags:(i=r.bootstrap)==null?void 0:i.featureFlags,featureFlagPayloads:(o=r.bootstrap)==null?void 0:o.featureFlagPayloads},remoteRequestsDisabled:n,featureFlagsDisabled:!!r.advanced_disable_feature_flags,onlyEvaluateSurveyFeatureFlags:!!r.advanced_only_evaluate_survey_feature_flags,deduplicateCallsPerSession:!!r.advanced_feature_flags_dedup_per_session,cacheTtlMs:r.feature_flag_cache_ttl_ms,requestTimeoutMs:r.feature_flag_request_timeout_ms,compression:r.disable_compression?"none":"base64",evaluationContexts:(a=(l=r.evaluation_contexts)!==null&&l!==void 0?l:r.evaluation_environments)!==null&&a!==void 0?a:[],flagKeys:L(r.flag_keys)?r.flag_keys:void 0}})(e,s),!e.evaluation_environments||e.evaluation_contexts||this.na||(Bl.warn("evaluation_environments is deprecated. Use evaluation_contexts instead. evaluation_environments will be removed in a future version."),this.na=!0),x(e.flag_keys)||L(e.flag_keys)||Bl.error("Invalid flag_keys found:",e.flag_keys,"Expected array of non-empty strings")}get(){return this.sa}}var jl=se("[FeatureFlags]"),Ot=se("[FeatureFlags]",{debugEnabled:!0}),xi=`" failed. Feature flags didn't load in time.`,Ul="connection_error",Hl=t=>{for(var e={},s=0;t.length>s;s++)e[t[s]]=!0;return e},Wl=t=>{var e={};for(var s of Or(t||{})){var r=s[1];r&&(e[s[0]]=r)}return e},Xe=se("[Error tracking]"),zl="Refusing to render web experiment since the viewer is a likely bot",yf={icontains:(t,e)=>e.toLowerCase().indexOf(t.toLowerCase())>-1,not_icontains:(t,e)=>e.toLowerCase().indexOf(t.toLowerCase())===-1,regex:(t,e)=>pn(e,t),not_regex:(t,e)=>!pn(e,t),exact:(t,e)=>e===t,is_not:(t,e)=>e!==t};class ye{get Ne(){return this._instance.config}constructor(e){var s=this;this.getWebExperimentsAndEvaluateDisplayLogic=function(r){r===void 0&&(r=!1),s.getWebExperiments((n=>{ye.aa("retrieved web experiments from the server"),s.oa=new Map,n.forEach((i=>{if(i.feature_flag_key){var o;s.oa&&(ye.aa("setting flag key ",i.feature_flag_key," to web experiment ",i),(o=s.oa)==null||o.set(i.feature_flag_key,i));var a=s._instance.getFeatureFlag(i.feature_flag_key);W(a)&&i.variants[a]&&s.la(i.name,a,i.variants[a].transforms)}else if(i.variants)for(var l in i.variants){var u=i.variants[l];ye.ua(u,s._instance)&&s.la(i.name,l,u.transforms)}}))}),r)},this._instance=e,this._instance.onFeatureFlags((r=>{this.onFeatureFlags(r)}))}initialize(){}onFeatureFlags(e){if(this._is_bot())ye.aa(zl);else if(!this.Ne.disable_web_experiments){if(D(this.oa))return this.oa=new Map,this.loadIfEnabled(),void this.previewWebExperiment();ye.aa("applying feature flags",e),e.forEach((s=>{var r;if(this.oa&&(r=this.oa)!=null&&r.has(s)){var n,i=this._instance.getFeatureFlag(s),o=(n=this.oa)==null?void 0:n.get(s);i&&o!=null&&o.variants[i]&&this.la(o.name,i,o.variants[i].transforms)}}))}}previewWebExperiment(){var e=ye.getWindowLocation();if(e!=null&&e.search){var s=ms(e?.search,"__experiment_id"),r=ms(e?.search,"__experiment_variant");s&&r&&(ye.aa("previewing web experiments "+s+" && "+r),this.getWebExperiments((n=>{this.ha(parseInt(s),r,n)}),!1,!0))}}loadIfEnabled(){this.Ne.disable_web_experiments||this.getWebExperimentsAndEvaluateDisplayLogic()}getWebExperiments(e,s,r){if(this.Ne.disable_web_experiments&&!r)return e([]);var n=this._instance.get_property("$web_experiments");if(n&&!s)return e(n);this._instance._send_request({url:this._instance.requestRouter.endpointFor("api","/api/web_experiments/?token="+this.Ne.token),method:"GET",timestampMode:"query",callback:i=>e(i.statusCode===200&&i.json&&i.json.experiments||[])})}ha(e,s,r){var n=r.filter((i=>i.id===e));n&&n.length>0&&(ye.aa("Previewing web experiment ["+n[0].name+"] with variant ["+s+"]"),this.la(n[0].name,s,n[0].variants[s].transforms))}static ua(e,s){return!D(e.conditions)&&ye.da(e,s)&&ye.va(e)}static da(e,s){var r;if(D(e.conditions)||D((r=e.conditions)==null?void 0:r.url))return!0;var n=ye.getWindowLocation();if(n){var i,o,a,l=yu(s,n.href);return(i=e.conditions)==null||!i.url||yf[(o=(a=e.conditions)==null?void 0:a.urlMatchType)!==null&&o!==void 0?o:"icontains"](e.conditions.url,l)}return!1}static getWindowLocation(){return v?.location}static va(e){var s;if(D(e.conditions)||D((s=e.conditions)==null?void 0:s.utm))return!0;var r=Nu();if(r.utm_source){var n,i,o,a,l,u,c,d,h=(n=e.conditions)==null||(n=n.utm)==null||!n.utm_campaign||((i=e.conditions)==null||(i=i.utm)==null?void 0:i.utm_campaign)==r.utm_campaign,p=(o=e.conditions)==null||(o=o.utm)==null||!o.utm_source||((a=e.conditions)==null||(a=a.utm)==null?void 0:a.utm_source)==r.utm_source,f=(l=e.conditions)==null||(l=l.utm)==null||!l.utm_medium||((u=e.conditions)==null||(u=u.utm)==null?void 0:u.utm_medium)==r.utm_medium,g=(c=e.conditions)==null||(c=c.utm)==null||!c.utm_term||((d=e.conditions)==null||(d=d.utm)==null?void 0:d.utm_term)==r.utm_term;return h&&f&&g&&p}return!1}static aa(e){for(var s=arguments.length,r=new Array(s>1?s-1:0),n=1;s>n;n++)r[n-1]=arguments[n];k.info("[WebExperiments] "+e,r)}la(e,s,r){this._is_bot()?ye.aa(zl):s!=="control"?r.forEach((n=>{if(n.selector){var i;ye.aa("applying transform of variant "+s+" for experiment "+e+" ",n);var o=(i=document)==null?void 0:i.querySelectorAll(n.selector);o?.forEach((a=>{var l=a;n.html&&(l.innerHTML=n.html),n.css&&l.setAttribute("style",n.css)}))}})):ye.aa("Control variants leave the page unmodified.")}_is_bot(){return ke&&this._instance?Qu(ke,this.Ne.custom_blocked_useragents):void 0}}var Ue=se("[Conversations]"),Dt="Conversations not available yet.",ql="console",ld="__posthogHandledLogsRequestError",ki=(t,e)=>{var s=t instanceof Error?t:new Error(e);return s[ld]=!0,s},Vl=t=>!!t&&typeof t=="object"&&t[ld]===!0,Rn={featureFlags:class{constructor(t){this.name="featureFlags",this.ca=!1,this.featureFlagEventHandlers=[],this.rt=jl,this.fa={},this.pa={},this.ga=[],this.ma=!1,this.ya=!1,this.ba=0,this._a=!1,this.wa=!1,this.ka=!1,this.xa=!1,this.Sa=0,this.Ca=()=>{var e=this.Ma();this.Sa=0,e&&this.reloadFeatureFlags()},"get"in t?this.Ta=t:(this.Ea=new _f(t.config,t.Qi()),this.Ta=this.Ea)}updateConfig(t,e){var s;(s=this.Ea)==null||s.update(t,e)}setup(t){return this.Ia=t,this.rt=t.logger.createLogger("[FeatureFlags]"),s=()=>{this.Ia===t&&(this.Ia=void 0,this.nn=t,this.Pa(t))},(e=t.kv.initialize())!=null&&e.then?e.then(s):s();var e,s}Pa(t){if(this.nn===t)return v&&ne(v,"online",this.Ca),this.Ra=t.registerDynamicEventProperties((()=>this.Aa()?this.fa:this.pa)),this.Fa(),this.initialize()}destroy(){v?.removeEventListener("online",this.Ca)}dispose(){var t;this.ba++,this.wa=!1,this.Ia=void 0,this.nn&&(this.La(),(t=this.Ra)==null||t.dispose(),this.Ra=void 0,this.ga=[],v?.removeEventListener("online",this.Ca),this.nn=void 0)}get Ne(){return this.Ta.get()}Oa(t){var e;return(e=this.nn)==null?void 0:e.kv.get(t)}F(t){this.Da((()=>{var e;return(e=this.nn)==null?void 0:e.kv.set(t)}))}q(t){this.Da((()=>{var e;return(e=this.nn)==null?void 0:e.kv.remove(t)}))}Da(t){try{t()}catch(e){this.rt.error("Failed to update feature flag persistence",e)}}Fa(){var t={};for(var e of[Us,Hs,Tr,et]){var s=this.Oa(e);x(s)||(t[e]=s)}this.fa=t;var r=b({},t),n=this.Oa(Bt);if(n)for(var i of Object.entries(n))r["$feature/"+i[0]]=i[1];this.pa=r}Aa(){var t=this.Ne.cacheTtlMs;if(!t||0>=t)return!1;var e=this.Oa(Gs);return typeof e!="number"||Date.now()-e>t}$a(){return!!this.Aa()&&(this.xa||this.ya||(this.xa=!0,this.rt.warn("Feature flag cache is stale, triggering refresh..."),this.reloadFeatureFlags()),!0)}Na(){var t=this.Ne.evaluationContexts;return t!=null&&t.length?t.filter((e=>{var s=e&&typeof e=="string"&&e.trim().length>0;return s||this.rt.error("Invalid evaluation context found:",e,"Expected non-empty string"),s})):[]}qa(){var t=this.Ne.flagKeys;if(!x(t))return t.filter((e=>{var s=e&&typeof e=="string"&&e.trim().length>0;return s||this.rt.error("Invalid flag key found:",e,"Expected non-empty string"),s}))}initialize(){var t,e,s=this.Ne,r=(t=(e=s.bootstrap)==null?void 0:e.featureFlags)!==null&&t!==void 0?t:{};if(Object.keys(r).length){var n,i,o=(n=(i=s.bootstrap)==null?void 0:i.featureFlagPayloads)!==null&&n!==void 0?n:{},a=Object.keys(r).filter((u=>!!r[u])).reduce(((u,c)=>(u[c]=r[c]||!1,u)),{}),l=Object.keys(o).filter((u=>a[u])).reduce(((u,c)=>(o[c]&&(u[c]=o[c]),u)),{});return this.ja({featureFlags:a,featureFlagPayloads:l})}}updateFlags(t,e,s){var r,n,i=s!=null&&s.merge&&(r=this.Oa(Bt))!==null&&r!==void 0?r:{},o=s!=null&&s.merge&&(n=this.Oa(Hs))!==null&&n!==void 0?n:{},a=b({},i,t),l=b({},o,e),u={};for(var c of Object.entries(a)){var d=c[0],h=c[1];u[d]={key:d,enabled:Da(h),variant:Ba(h),reason:void 0,metadata:x(l?.[d])?void 0:{id:0,version:void 0,description:void 0,payload:l[d]}}}this.ja({flags:u})}get hasLoadedFlags(){return this.ma}getFlags(){return Object.keys(this.getFlagVariants())}getFlagsWithDetails(){var t=this.Oa(Ki),e=this.Oa(et),s=this.Oa(jt);if(!s&&!e)return t||{};var r=ee({},t||{}),n=[...new Set([...Object.keys(s||{}),...Object.keys(e||{})])];for(var i of n){var o,a,l=r[i],u=e?.[i],c=x(u)?(o=l?.enabled)!==null&&o!==void 0&&o:!!u,d=x(u)?l?.variant:typeof u=="string"?u:void 0,h=s?.[i],p=b({},l,{enabled:c,variant:c?d??l?.variant:void 0});c!==l?.enabled&&(p.original_enabled=l?.enabled),d!==l?.variant&&(p.original_variant=l?.variant),h&&(p.metadata=b({},l?.metadata,{payload:h,original_payload:l==null||(a=l.metadata)==null?void 0:a.payload})),r[i]=p}return this.ca||(this.rt.warn(" Overriding feature flag details!",{flagDetails:t,overriddenPayloads:s,finalDetails:r}),this.ca=!0),r}getAllFeatureFlags(){var t=this.getFlagVariants(),e=this.getFlagPayloads();return Object.keys(t).map((s=>{var r=t[s];return{key:s,enabled:Da(r),variant:Ba(r),payload:Oa(e[s])}}))}getFlagVariants(){var t=this.Oa(Bt),e=this.Oa(et);if(!e)return t||{};for(var s=ee({},t||{}),r=Object.keys(e),n=0;r.length>n;n++)s[r[n]]=e[r[n]];return this.ca||(this.rt.warn(" Overriding feature flags!",{enabledFlags:t,overriddenFlags:e,finalFlags:s}),this.ca=!0),s}getFlagPayloads(){var t=this.Oa(Hs),e=this.Oa(jt);if(!e)return t||{};for(var s=ee({},t||{}),r=Object.keys(e),n=0;r.length>n;n++)s[r[n]]=e[r[n]];return this.ca||(this.rt.warn(" Overriding feature flag payloads!",{flagPayloads:t,overriddenPayloads:e,finalPayloads:s}),this.ca=!0),s}reloadFeatureFlags(){this._a||this.Ne.featureFlagsDisabled||this.Ma()||this.Ba||(this.ga.slice().forEach((t=>{try{t()}catch(e){this.rt.error("Error while running feature flags reloading callback",e)}})),this.Ba=setTimeout((()=>{this.Ha()}),5))}La(){clearTimeout(this.Ba),this.Ba=void 0}onReloading(t){return this.ga.push(t),()=>{this.ga=this.ga.filter((e=>e!==t))}}ensureFlagsLoaded(){this.ma||this.ya||this.Ba||this.reloadFeatureFlags()}setAnonymousDistinctId(t){this.$anon_distinct_id=t}setReloadingPaused(t){this._a=t}resetFlagCallReported(){this.q(Wt)}Ha(t){this.La();var e=this.nn;if(e&&!this.Ne.remoteRequestsDisabled&&!this.Ma())if(this.ya)this.wa=!0;else{var s={token:e.projectToken,distinct_id:e.distinctId,groups:e.groups,$anon_distinct_id:this.$anon_distinct_id,person_properties:b({},e.initialPersonProperties,this.Oa(ct)||{},{$lib:e.library.name,$lib_version:e.library.version}),group_properties:this.Oa(Ut),timezone:ju()};x(e.deviceId)||(s.$device_id=e.deviceId),(t!=null&&t.disableFlags||this.Ne.featureFlagsDisabled)&&(s.disable_flags=!0);var r=this.Na();r.length&&(s.evaluation_contexts=r);var n=this.qa();x(n)||(s.flag_keys=n);var i=this.Ne.onlyEvaluateSurveyFeatureFlags,o="/flags/?v=2"+(i?"&only_evaluate_survey_feature_flags=true":""),a=this.ba;this.ya=!0;var l=()=>{this.wa&&(this.wa=!1,this.Ha())},u=c=>{this.ya=!1,a===this.ba&&(this.F({[Lr]:[Ul]}),this.rt.error("Feature flag request failed",c)),l()};try{e.sendRequest(o,{target:"flags",method:"POST",body:s,compression:this.Ne.compression==="base64"?xe.Base64:void 0,sentAt:"body",timeoutMs:this.Ne.requestTimeoutMs}).then((c=>{var d,h,p=(d=c.json)!==null&&d!==void 0?d:{},f=c.statusCode!==200;if(this.ya=!1,a===this.ba){if(this.Ua(c.statusCode),f||this.wa||(this.$anon_distinct_id=void 0),!s.disable_flags||this.wa){this.ka=!f;var g=[];c.error?g.push(c.error instanceof Error&&c.error.name==="AbortError"?"timeout":c.error instanceof Error?Ul:"unknown_error"):c.statusCode!==200&&g.push("api_error_"+c.statusCode),p.errorsWhileComputingFlags&&g.push("errors_while_computing_flags");var m=!((h=p.quotaLimited)==null||!h.includes("feature_flags"));m&&g.push("quota_limited"),this.F({[Lr]:g}),m?this.rt.warn("You have hit your feature flags quota limit, and will not be able to load feature flags until the quota is reset. Please visit https://posthog.com/docs/billing/limits-alerts to learn more."):s.disable_flags||this.ja(p,f,{partialResponse:i}),l()}}else l()})).catch(u)}catch(c){u(c)}}}Ma(){return Ru(this.Sa,3)}Ua(t){this.Sa=Tu(t,this.Sa,3,(()=>this.rt.warn("Feature flag requests are failing before receiving an HTTP response; this can happen due to network issues, CORS, browser blocking, or ad blockers. Stopped refreshing feature flags; will try again when connectivity changes.")))}getFeatureFlag(t,e){var s;if(e===void 0&&(e={}),!e.fresh||this.ka)if(this.ma||this.getFlags()&&this.getFlags().length>0){if(!this.$a()){var r=this.getFeatureFlagResult(t,e);return(s=r?.variant)!==null&&s!==void 0?s:r?.enabled}}else this.rt.warn('getFeatureFlag for key "'+t+xi)}getFeatureFlagDetails(t){return this.getFlagsWithDetails()[t]}getFeatureFlagPayload(t){var e=this.getFeatureFlagResult(t,{send_event:!1});return e?.payload}getFeatureFlagResult(t,e){if(e===void 0&&(e={}),!e.fresh||this.ka)if(this.ma||this.getFlags()&&this.getFlags().length>0){if(!this.$a()){var s,r=this.getFlagVariants(),n=t in r,i=r[t],o=this.getFlagPayloads()[t],a=String(i),l=this.Oa(Tr)||void 0,u=this.Oa(Gs)||void 0,c=this.Oa(Wt)||{};if(this.Ne.deduplicateCallsPerSession){var d,h=(d=this.nn)==null?void 0:d.session.sessionId,p=this.Oa(zs);h&&h!==p&&(c={},s=h)}if(e.send_event||!("send_event"in e))if(t in c&&c[t].includes(a))s&&this.F({[Wt]:c,[zs]:s});else{var f,g,m,_,w,E,I,F,P,B;L(c[t])?c[t].push(a):c[t]=[a],this.F(b({[Wt]:c},s?{[zs]:s}:{}));var S=this.getFeatureFlagDetails(t),A=[...(f=this.Oa(Lr))!==null&&f!==void 0?f:[]];x(i)&&A.push("flag_missing");var R={$feature_flag:t,$feature_flag_response:i,$feature_flag_payload:o||null,$feature_flag_request_id:l,$feature_flag_evaluated_at:u,$feature_flag_bootstrapped_response:((g=this.Ne.bootstrap)==null||(g=g.featureFlags)==null?void 0:g[t])||null,$feature_flag_bootstrapped_payload:((m=this.Ne.bootstrap)==null||(m=m.featureFlagPayloads)==null?void 0:m[t])||null,$used_bootstrap_value:!this.ka};x(S==null||(_=S.metadata)==null?void 0:_.has_experiment)||(R.$feature_flag_has_experiment=S.metadata.has_experiment),x(S==null||(w=S.metadata)==null?void 0:w.version)||(R.$feature_flag_version=S.metadata.version);var N,T=(E=S==null||(I=S.reason)==null?void 0:I.description)!==null&&E!==void 0?E:S==null||(F=S.reason)==null?void 0:F.code;T&&(R.$feature_flag_reason=T),S!=null&&(P=S.metadata)!=null&&P.id&&(R.$feature_flag_id=S.metadata.id),x(S?.original_variant)&&x(S?.original_enabled)||(R.$feature_flag_original_response=x(S.original_variant)?S.original_enabled:S.original_variant),S!=null&&(B=S.metadata)!=null&&B.original_payload&&(R.$feature_flag_original_payload=S==null||(N=S.metadata)==null?void 0:N.original_payload),A.length&&(R.$feature_flag_error=A.join(",")),this.za(R)}else s&&this.F({[Wt]:c,[zs]:s});if(n)return{key:t,enabled:!!i,variant:typeof i=="string"?i:void 0,payload:Oa(o)}}}else this.rt.warn('getFeatureFlagResult for key "'+t+xi)}za(t){try{var e;(e=this.nn)==null||e.capture("$feature_flag_called",t).catch((s=>{this.rt.error("Failed to capture feature flag call",s)}))}catch(s){this.rt.error("Failed to capture feature flag call",s)}}getRemoteConfigPayload(t,e){this.Wa(t,e)}Wa(t,e){var s=this;return X((function*(){var r=s.nn;if(r){var n={distinct_id:r.distinctId,token:r.projectToken,person_properties:{$lib:r.library.name,$lib_version:r.library.version}},i=s.Na();i.length&&(n.evaluation_contexts=i);var o,a=s.qa();x(a)||(n.flag_keys=a);try{var l,u=(l=(yield r.sendRequest("/flags/?v=2",{target:"flags",method:"POST",body:n,compression:s.Ne.compression==="base64"?xe.Base64:void 0,sentAt:"body",timeoutMs:s.Ne.requestTimeoutMs})).json)==null?void 0:l.featureFlagPayloads;o=u?.[t]||void 0}catch(c){return void s.rt.error("Remote config feature flag request failed",c)}try{e(o)}catch(c){s.rt.error("Remote config feature flag callback failed",c)}}}))()}isFeatureEnabled(t,e){if(e===void 0&&(e={}),e.fresh&&!this.ka)return e.defaultValue;if(!(this.ma||this.getFlags()&&this.getFlags().length>0))return this.rt.warn('isFeatureEnabled for key "'+t+xi),e.defaultValue;var s=this.getFeatureFlag(t,e);return x(s)?e.defaultValue:!!s}addFeatureFlagsHandler(t){this.featureFlagEventHandlers.push(t)}removeFeatureFlagsHandler(t){this.featureFlagEventHandlers=this.featureFlagEventHandlers.filter((e=>e!==t))}receivedFeatureFlags(t,e,s){this.ja(t,e,s)}ja(t,e,s){if(this.nn){this.ma=!0;var r=(function(n,i,o,a,l,u){i===void 0&&(i={}),o===void 0&&(o={}),a===void 0&&(a={}),u===void 0&&(u=jl);var c=((P,B)=>{var S=P.flags;return S?b({},P,{featureFlags:Object.fromEntries(Object.keys(S).map((A=>{var R;return[A,(R=S[A].variant)!==null&&R!==void 0?R:S[A].enabled]}))),featureFlagPayloads:Object.fromEntries(Object.keys(S).filter((A=>S[A].enabled)).filter((A=>{var R;return(R=S[A].metadata)==null?void 0:R.payload})).map((A=>{var R;return[A,(R=S[A].metadata)==null?void 0:R.payload]})))}):(P.featureFlags&&B.warn("Using an older version of the feature flags endpoint. Please upgrade your PostHog server to the latest version"),P)})(n,u),d=c.flags,h=c.featureFlags,p=c.featureFlagPayloads;if(h){var f=n.requestId,g=n.evaluatedAt;if(L(h)){u.warn("v1 of the feature flags endpoint is deprecated. Please use the latest version.");var m={};if(h)for(var _=0;h.length>_;_++)m[h[_]]=!0;return{[Us]:h,[Bt]:m,[en]:!1}}var w=h,E=p,I=d;if(l!=null&&l.partialResponse)w=b({},i,w),E=b({},o,E),I=b({},a,I);else if(n.errorsWhileComputingFlags)if(d){var F=new Set(Object.keys(d).filter((P=>{var B;return!((B=d[P])!=null&&B.failed)})));w=b({},i,Object.fromEntries(Object.entries(w).filter((P=>F.has(P[0]))))),E=b({},o,Object.fromEntries(Object.entries(E||{}).filter((P=>F.has(P[0]))))),I=b({},a,Object.fromEntries(Object.entries(I||{}).filter((P=>F.has(P[0])))))}else w=b({},i,w),E=b({},o,E),I=b({},a,I);return b({[Us]:Object.keys(Wl(w)),[Bt]:w||{},[Hs]:E||{},[Ki]:I||{},[en]:n.minimalFlagCalledEvents===!0},f?{[Tr]:f}:{},g?{[Gs]:g}:{})}})(t,this.getFlagVariants(),this.getFlagPayloads(),this.getFlagsWithDetails(),s,this.rt);r&&this.F(r),e||(this.xa=!1),this.Va(e)}}override(t,e){e===void 0&&(e=!1),this.rt.warn("override is deprecated. Please use overrideFeatureFlags instead."),this.overrideFeatureFlags({flags:t,suppressWarning:e})}overrideFeatureFlags(t){this.Za(t)}Za(t){if(this.nn){if(t===!1)return this.q([et,jt]),this.Va(),void Ot.info("All overrides cleared");if(L(t))return this.F({[et]:Hl(t)}),this.Va(),void Ot.info("Flag overrides set",{flags:t});if(t&&typeof t=="object"&&("flags"in t||"payloads"in t)){var e,s=t;this.ca=!!((e=s.suppressWarning)!==null&&e!==void 0&&e);var r={},n=s.flags,i=s.payloads;return n&&(r[et]=L(n)?Hl(n):n),i&&(r[jt]=i),Object.keys(r).length&&this.F(r),n===!1&&i===!1?this.q([et,jt]):n===!1?this.q(et):i===!1&&this.q(jt),this.Va(),n===!1?Ot.info("Flag overrides cleared"):n&&Ot.info("Flag overrides set",{flags:n}),void(i===!1?Ot.info("Payload overrides cleared"):i&&Ot.info("Payload overrides set",{payloads:i}))}if(t&&typeof t=="object")return this.F({[et]:t}),this.Va(),void Ot.info("Flag overrides set",{flags:t});this.rt.warn("Invalid overrideOptions provided to overrideFeatureFlags",{overrideOptions:t})}else this.rt.warn("posthog.featureFlags.overrideFeatureFlags called before feature flags were ready")}onFeatureFlags(t){if(this.addFeatureFlagsHandler(t),this.ma){var e=this.Ga(),s=e.flags,r=e.flagVariants;try{t(s,r)}catch(n){this.rt.error("Error while running feature flags callback",n)}}return()=>this.removeFeatureFlagsHandler(t)}updateEarlyAccessFeatureEnrollment(t,e,s){var r=(this.Oa(Rr)||[]).find((l=>l.flagKey===t)),n={["$feature_enrollment/"+t]:e},i={$feature_flag:t,$feature_enrollment:e,$set:n};r&&(i.$early_access_feature_name=r.name),s&&(i.$feature_enrollment_stage=s);var o=b({},this.getFlagVariants(),{[t]:e});this.F({[Us]:Object.keys(Wl(o)),[Bt]:o,[ct]:b({},this.Oa(ct)||{},n)}),this.Va();try{var a;(a=this.nn)==null||a.capture("$feature_enrollment_update",i).catch((l=>{this.rt.error("Failed to capture early access feature enrollment",l)}))}catch(l){this.rt.error("Failed to capture early access feature enrollment",l)}}getEarlyAccessFeatures(t,e,s){e===void 0&&(e=!1);var r=this.Oa(Rr);!r||e?this.Qa(t,s):t(r)}Qa(t,e){var s=this;return X((function*(){var r=s.nn;if(r){var n,i=e?"&"+e.map((a=>"stage="+a)).join("&"):"";try{var o=yield r.sendRequest("/api/early_access_features/?token="+r.projectToken+i,{target:"api",method:"GET",sentAt:"query"});if(!o.json)return;s.F({[Rr]:n=o.json.earlyAccessFeatures})}catch(a){return void s.rt.error("Early access feature request failed",a)}try{t(n)}catch(a){s.rt.error("Early access feature callback failed",a)}}}))()}Ga(){var t=this.getFlags(),e=this.getFlagVariants();return{flags:t.filter((s=>e[s])),flagVariants:Object.keys(e).filter((s=>e[s])).reduce(((s,r)=>(s[r]=e[r],s)),{})}}Va(t){this.Fa();var e=this.Ga(),s=e.flags,r=e.flagVariants;this.featureFlagEventHandlers.forEach((n=>{try{n(s,r,{errorsLoading:t})}catch(i){this.rt.error("Error while running feature flags callback",i)}}))}setPersonPropertiesForFlags(t,e){e===void 0&&(e=!0),this.Ka(t,e)}Ka(t,e){e===void 0&&(e=!0);var s=this.Oa(ct)||{},r=t?.$set||(t!=null&&t.$set_once?{}:t),n=t?.$set_once,i={};if(n)for(var o in n)({}).hasOwnProperty.call(n,o)&&(o in s||(i[o]=n[o]));this.F({[ct]:b({},s,i,r)}),e&&this.reloadFeatureFlags()}unsetPersonPropertiesForFlags(t,e){e===void 0&&(e=!0);var s=b({},this.Oa(ct)||{});t.forEach((r=>{delete s[r]})),this.F({[ct]:s}),e&&this.reloadFeatureFlags()}resetPersonPropertiesForFlags(t){t===void 0&&(t=!0),this.q(ct),t&&this.reloadFeatureFlags()}setGroupPropertiesForFlags(t,e){e===void 0&&(e=!0);var s=this.Oa(Ut)||{},r=b({},s);for(var n of Object.keys(t))r[n]=b({},s[n],t[n]);this.F({[Ut]:r}),e&&this.reloadFeatureFlags()}resetGroupPropertiesForFlags(t){if(t){var e=this.Oa(Ut)||{};this.F({[Ut]:b({},e,{[t]:{}})})}else this.q(Ut)}reset(){this.ba++,this.wa=!1,this.Fa(),this.ma=!1,this._a=!1,this.ka=!1,this.$anon_distinct_id=void 0,this.La(),this.ca=!1,this.Sa=0}}},wf={sessionRecording:class{get Ne(){return this._instance.config}get Mr(){return this._instance.persistence}get started(){var t;return!((t=this.Ja)==null||!t.isStarted)}get status(){var t,e;return this.Ya===Ls||this.Ya===Fr?this.Ya:(t=(e=this.Ja)==null?void 0:e.status)!==null&&t!==void 0?t:this.Ya}constructor(t){if(this._forceAllowLocalhostNetworkCapture=!1,this.Ya=Tl,this.Xa=void 0,this.eo=!1,this.io=(()=>{var e;if(C==null||!C.visibilityState||C.visibilityState==="visible")return!0;var s=v==null||(e=v.performance)==null||e.getEntriesByType==null?void 0:e.getEntriesByType("visibility-state");return!(s!=null&&s.length)||s.some((r=>r.name==="visible"))})(),this.Ie=()=>{var e;C?.visibilityState==="visible"&&(this.io=!0,(e=this.Ja)==null||e.setDocumentWasEverVisible==null||e.setDocumentWasEverVisible(!0))},this._instance=t,!this._instance.sessionManager)throw at.error("started without valid sessionManager"),new Error(po+" started without valid sessionManager. This is a bug.");if(this.Ne.cookieless_mode===ht)throw new Error(po+' cannot be used with cookieless_mode="always"');C!=null&&C.addEventListener&&ne(C,"visibilitychange",this.Ie)}initialize(){this.startIfEnabledOrStop()}dispose(){this.eo=!0,C==null||C.removeEventListener==null||C.removeEventListener("visibilitychange",this.Ie),this.stopRecording()}get ro(){var t,e=!((t=this._instance.get_property(qt))==null||!t.enabled),s=!this.Ne.disable_session_recording,r=this.Ne.disable_session_recording||this._instance.consent.isOptedOut();return v&&e&&s&&!r}startIfEnabledOrStop(t){var e;if(!(this.eo||this.ro&&(e=this.Ja)!=null&&e.isStarted)){var s=!x(Object.assign)&&!x(Array.from);this.ro&&s?(this.no(t),at.info("starting")):(this.Ya=Tl,this.stopRecording())}}no(t){var e,s,r;this.ro&&(this.Ya!==Ls&&this.Ya!==Fr&&(this.Ya=Nl),$!=null&&(e=$.__PosthogExtensions__)!=null&&(e=e.rrweb)!=null&&e.record&&(s=$.__PosthogExtensions__)!=null&&s.initSessionRecording?this.so(t):(r=$.__PosthogExtensions__)==null||r.loadExternalDependency==null||r.loadExternalDependency(this._instance,this.ao,(n=>{if(n)return at.error("could not load recorder",n);this.so(t)})))}stopRecording(){var t,e;(t=this.Xa)==null||t.call(this),this.Xa=void 0,(e=this.Ja)==null||e.stop()}oo(){var t,e;(t=this.Xa)==null||t.call(this),this.Xa=void 0,(e=this.Ja)==null||e.discard()}lo(){var t,e;(t=this.Mr)==null||t.unregister(zo),(e=this.Mr)==null||e.unregister(lu)}uo(t,e){if(D(t))return null;var s,r=he(t)?t:parseFloat(t);return typeof(s=r)!="number"||!Number.isFinite(s)||0>s||s>1?(at.warn(e+" must be between 0 and 1. Ignoring invalid value:",t),null):r}ho(t){if(this.Mr){var e,s,r=this.Mr,n=()=>{var i,o=t.sessionRecording===!1?void 0:t.sessionRecording,a=this.uo((i=this.Ne.session_recording)==null?void 0:i.sampleRate,"session_recording.sampleRate"),l=this.uo(o?.sampleRate,"remote config sampleRate"),u=a??l;D(u)&&this.lo();var c=o?.minimumDurationMilliseconds;r.register({[qt]:b({cache_timestamp:Date.now(),enabled:!!o},o,{networkPayloadCapture:b({capturePerformance:t.capturePerformance},o?.networkPayloadCapture),canvasRecording:{enabled:o?.recordCanvas,fps:o?.canvasFps,quality:o?.canvasQuality},sampleRate:u,minimumDurationMilliseconds:x(c)?null:c,endpoint:o?.endpoint,triggerMatchType:o?.triggerMatchType,masking:o?.masking,urlTriggers:o?.urlTriggers,version:o?.version,triggerGroups:o?.triggerGroups})})};n(),(e=this.Xa)==null||e.call(this),this.Xa=(s=this._instance.sessionManager)==null?void 0:s.onSessionId(n)}}onRemoteConfig(t){var e=t.ok?t.config:void 0;return e&&"sessionRecording"in e?e.sessionRecording===!1?(this.ho(e),void this.oo()):(this.ho(e),void this.startIfEnabledOrStop()):(this.Ya===Ls&&(this.Ya=Fr,at.warn("config refresh failed, recording will not start until page reload")),void this.startIfEnabledOrStop())}log(t,e){var s;e===void 0&&(e="log"),(s=this.Ja)!=null&&s.log?this.Ja.log(t,e):at.warn("log called before recorder was ready")}get ao(){var t,e,s=(t=this._instance)==null||(t=t.persistence)==null?void 0:t.get_property(qt);return(s==null||(e=s.scriptConfig)==null?void 0:e.script)||"lazy-recorder"}do(){var t,e=this._instance.get_property(qt);if(!e)return!1;try{t=typeof e=="object"?e:JSON.parse(e)}catch(s){return at.warn("persisted remote config for session recording is invalid and will be ignored",s),!1}return!D(t.cache_timestamp)&&36e5>=Date.now()-t.cache_timestamp}so(t){var e,s,r;if(!this.eo){if((e=$.__PosthogExtensions__)==null||!e.initSessionRecording)return at.warn("Called on script loaded before session recording is available. This can be caused by adblockers."),void this._instance.register_for_session({[mu]:!0});var n;if(this.Ja||(this.Ja=(n=$.__PosthogExtensions__)==null?void 0:n.initSessionRecording(this._instance,this.io),this.Ja._forceAllowLocalhostNetworkCapture=this._forceAllowLocalhostNetworkCapture),!this.do())return this.Ya===Fr||this.Ya===Ls?void 0:(this.Ya=Ls,at.info("persisted remote config is stale, requesting fresh config before starting"),void new Uu(this._instance).load());this.Ya=Nl,(s=(r=this.Ja).setDocumentWasEverVisible)==null||s.call(r,this.io),this.Ja.start(t)}}onRRwebEmit(t){var e;(e=this.Ja)==null||e.onRRwebEmit==null||e.onRRwebEmit(t)}overrideLinkedFlag(){var t,e;this.Ja||(e=this.Mr)==null||e.register({[uu]:!0}),(t=this.Ja)==null||t.overrideLinkedFlag()}overrideSampling(){var t,e;this.Ja||(e=this.Mr)==null||e.register({[cu]:!0}),(t=this.Ja)==null||t.overrideSampling()}overrideTrigger(t){var e,s;this.Ja||(s=this.Mr)==null||s.register({[t==="url"?du:hu]:!0}),(e=this.Ja)==null||e.overrideTrigger(t)}get sdkDebugProperties(){var t;return((t=this.Ja)==null?void 0:t.sdkDebugProperties)||{$recording_status:this.status}}tryAddCustomEvent(t,e){var s;return!((s=this.Ja)==null||!s.tryAddCustomEvent(t,e))}}},bf={autocapture:class{constructor(t){this.vo=!1,this.co=null,this.fo=!1,this.po=!1,this.instance=t,this.rageclicks=new Al(t.config.rageclick),this.mo=null}initialize(){this.startIfEnabled()}get Ne(){var t,e,s=te(this.instance.config.autocapture)?this.instance.config.autocapture:{};return s.url_allowlist=(t=s.url_allowlist)==null?void 0:t.map((r=>new RegExp(r))),s.url_ignorelist=(e=s.url_ignorelist)==null?void 0:e.map((r=>new RegExp(r))),s}yo(){if(this.isBrowserSupported()){if(v&&C){var t=s=>{s=s||v?.event;try{this.bo(s)}catch(r){wi.error("Failed to capture event",r)}};if(ne(C,"submit",t,{capture:!0}),ne(C,"change",t,{capture:!0}),ne(C,"click",t,{capture:!0}),this.Ne.capture_copied_text){var e=s=>{s=s||v?.event;try{this.bo(s,yi)}catch(r){wi.error("Failed to capture copy/cut event",r)}};ne(C,"copy",e,{capture:!0}),ne(C,"cut",e,{capture:!0})}}}else wi.info("Disabling Automatic Event Collection because this browser is not supported")}startIfEnabled(){this.isEnabled&&!this.vo&&(this.yo(),this.vo=!0)}onRemoteConfig(t){if(this.fo=!0,t.ok){var e=t.config;e.elementsChainAsString&&(this.po=e.elementsChainAsString);var s=e.autocapture_opt_out;Ke(s)&&(this.instance.persistence&&this.instance.persistence.register({[Ui]:s}),this.co=s),this.startIfEnabled()}else this.startIfEnabled()}setElementSelectors(t){this.mo=t}getElementSelectors(t){var e,s=[];return(e=this.mo)==null||e.forEach((r=>{var n=C?.querySelectorAll(r);n?.forEach((i=>{t===i&&s.push(r)}))})),s}get isEnabled(){var t,e,s=(t=this.instance.persistence)==null?void 0:t.props[Ui],r=this.co,n=this.instance.Qi()&&!this.fo;if($e(r)&&!Ke(s)&&!n)return!1;var i=(e=this.co)!==null&&e!==void 0?e:!!s;return!!this.instance.config.autocapture&&!i}bo(t,e){if(e===void 0&&(e="$autocapture"),this.isEnabled){var s,r=ai(t);bu(r)&&(r=r.parentNode||null),e==="$autocapture"&&t.type==="click"&&t instanceof MouseEvent&&this.instance.config.rageclick&&(s=this.rageclicks)!=null&&s.isRageClick(t.clientX,t.clientY,t.timeStamp||new Date().getTime())&&ol(r,this.instance.config.rageclick)&&this.bo(t,"$rageclick");var n=e===yi;if(r&&(function(d,h,p,f,g,m){var _;if(!v||Jo(d)||p!=null&&p.url_allowlist&&!rl(p.url_allowlist,m)||p!=null&&p.url_ignorelist&&rl(p.url_ignorelist,m))return!1;if(p!=null&&p.dom_event_allowlist){var w=p.dom_event_allowlist;if(w&&!w.some((S=>h.type===S)))return!1}var E=Cu(d,f),I=E.parentIsUsefulElement,F=E.targetElementList;if(!(function(S,A){var R=A?.element_allowlist;if(x(R))return!0;var N,T=function(J){if(R.some((z=>J.tagName.toLowerCase()===z)))return{v:!0}};for(var O of S)if(N=T(O))return N.v;return!1})(F,p)||!ro(F,p?.css_selector_allowlist)||ro(F,(_=p?.css_selector_ignorelist)!==null&&_!==void 0?_:vp))return!1;try{var P=v.getComputedStyle(d);if(P&&P.getPropertyValue("cursor")==="pointer"&&h.type==="click")return!0}catch{}var B=d.tagName.toLowerCase();switch(B){case"html":return!1;case"form":return(g||["submit"]).indexOf(h.type)>=0;case"input":case"select":case"textarea":return(g||["change","click"]).indexOf(h.type)>=0;default:return I?(g||["click"]).indexOf(h.type)>=0:(g||["click"]).indexOf(h.type)>=0&&(Ko.indexOf(B)>-1||d.getAttribute("contenteditable")==="true")}})(r,t,this.Ne,n,n?["copy","cut"]:void 0,this.instance)){var i=uf(r,{e:t,maskAllElementAttributes:this.instance.config.mask_all_element_attributes,maskAllText:this.instance.config.mask_all_text,elementAttributeIgnoreList:this.Ne.element_attribute_ignorelist,elementsChainAsString:this.po,disableCaptureUrlHashes:this.instance.config.disable_capture_url_hashes}),o=i.props;if(i.explicitNoCapture)return!1;var a=this.getElementSelectors(r);if(a&&a.length>0&&(o.$element_selectors=a),e===yi){var l,u=xu(v==null||(l=v.getSelection())==null?void 0:l.toString()),c=t.type||"clipboard";if(!u)return!1;o.$selected_content=u,o.$copy_type=c}return this.instance.capture(e,o),!0}}}isBrowserSupported(){return Se(C?.querySelectorAll)}},historyAutocapture:class{constructor(t){var e;this._instance=t,this._o=(v==null||(e=v.location)==null?void 0:e.pathname)||""}initialize(){this.startIfEnabled()}get isEnabled(){return this._instance.config.capture_pageview==="history_change"}startIfEnabled(){this.isEnabled&&(k.info("History API monitoring enabled, starting..."),this.monitorHistoryChanges())}stop(){this.wo&&this.wo(),this.wo=void 0,k.info("History API monitoring stopped")}monitorHistoryChanges(){v&&v.history&&(this.ko("pushState"),this.ko("replaceState"),this.xo())}ko(t){var e;if(v&&((e=v.history[t])==null||!e.__posthog_wrapped__)){var s=this;(function(r,n,i){try{if(!(n in r))return $l;var o={next:r[n]},a=i((function(){for(var l=arguments.length,u=new Array(l),c=0;l>c;c++)u[c]=arguments[c];return o.next.apply(this,u)}));return Se(a)&&(a.prototype=a.prototype||{},Object.defineProperties(a,{__posthog_wrapped__:{enumerable:!1,value:!0},__posthog_layer__:{enumerable:!1,value:o}})),r[n]=a,()=>{if(r[n]!==a)for(var l=r[n];Se(l)&&l.__posthog_layer__;){var u=l.__posthog_layer__;if(u.next===a)return void(u.next=o.next);l=u.next}else r[n]=o.next}}catch{return $l}})(v.history,t,(r=>function(n,i,o){r.call(this,n,i,o),s.So(t)}))}}So(t){try{var e,s=v==null||(e=v.location)==null?void 0:e.pathname;if(!s)return;s!==this._o&&this.isEnabled&&this._instance.capture(is,{navigation_type:t}),this._o=s}catch(r){k.error("Error capturing "+t+" pageview",r)}}xo(){if(!this.wo){var t=()=>{this.So("popstate")};ne(v,"popstate",t),this.wo=()=>{v&&v.removeEventListener("popstate",t)}}}},heatmaps:class{get Ne(){return this.instance.config}constructor(t){var e;this.Co=!1,this.vo=!1,this.Mo=null,this.instance=t,this.Co=!((e=this.instance.persistence)==null||!e.props[Hi]),this.rageclicks=new Al(t.config.rageclick)}initialize(){this.startIfEnabled()}get flushIntervalMilliseconds(){var t=5e3;return te(this.Ne.capture_heatmaps)&&this.Ne.capture_heatmaps.flush_interval_milliseconds&&(t=this.Ne.capture_heatmaps.flush_interval_milliseconds),t}get isEnabled(){return D(this.Ne.capture_heatmaps)?D(this.Ne.enable_heatmaps)?this.Co:this.Ne.enable_heatmaps:this.Ne.capture_heatmaps!==!1}startIfEnabled(){if(this.isEnabled){if(this.vo)return;hf.info("starting..."),this.To(),this.Ie()}else{var t;clearInterval((t=this.Mo)!==null&&t!==void 0?t:void 0),this.Eo(),this.getAndClearBuffer()}}onRemoteConfig(t){if(t.ok){var e=t.config;if("heatmaps"in e){var s=!!e.heatmaps;this.instance.persistence&&this.instance.persistence.register({[Hi]:s}),this.Co=s,this.startIfEnabled()}}}getAndClearBuffer(){var t=this.R;return this.R=void 0,t}Io(t){Ei(t.originalEvent)&&this.ke(t.originalEvent,"deadclick")}Ie(){this.Mo&&clearInterval(this.Mo),this.Mo=C?.visibilityState==="visible"?setInterval(this.cr.bind(this),this.flushIntervalMilliseconds):null}To(){v&&C&&(this.Po=this.cr.bind(this),ne(v,on,this.Po),this.Ro=t=>this.ke(t||v?.event),ne(C,"click",this.Ro,{capture:!0}),this.Ao=t=>this.Fo(t||v?.event),ne(C,"mousemove",this.Ao,{capture:!0}),this.Lo=new pl(this.instance,xp,this.Io.bind(this)),this.Lo.startIfEnabledOrStop(),this.Oo=this.Ie.bind(this),ne(C,nn,this.Oo),this.vo=!0)}Eo(){var t;v&&C&&(this.Po&&v.removeEventListener(on,this.Po),this.Ro&&C.removeEventListener("click",this.Ro,{capture:!0}),this.Ao&&C.removeEventListener("mousemove",this.Ao,{capture:!0}),this.Oo&&C.removeEventListener(nn,this.Oo),clearTimeout(this.Do),(t=this.Lo)==null||t.stop(),this.vo=!1)}$o(t,e){var s=this.instance.scrollManager.scrollY(),r=this.instance.scrollManager.scrollX(),n=this.instance.scrollManager.scrollElement(),i=(function(o,a,l){for(var u=o;u&&Ft(u)&&!Me(u,"body");){if(u===l)return!1;var c=void 0;try{var d,h,p;c=(d=(h=(p=u.ownerDocument)==null?void 0:p.defaultView)!==null&&h!==void 0?h:v)==null?void 0:d.getComputedStyle(u).position}catch{return!1}if(M(a,c))return!0;u=ku(u)}return!1})(ai(t),["fixed","sticky"],n);return{x:t.clientX+(i?0:r),y:t.clientY+(i?0:s),target_fixed:i,type:e}}ke(t,e){var s;if(e===void 0&&(e="click"),!sl(t.target)&&Ei(t)){var r=this.$o(t,e);(s=this.rageclicks)!=null&&s.isRageClick(t.clientX,t.clientY,new Date().getTime())&&ol(ai(t),this.instance.config.rageclick)&&this.Vt(b({},r,{type:"rageclick"})),this.Vt(r)}}Fo(t){!sl(t.target)&&Ei(t)&&(clearTimeout(this.Do),this.Do=setTimeout((()=>{this.Vt(this.$o(t,"mousemove"))}),500))}Vt(t){if(v){var e=this.Ne.disable_capture_url_hashes?Ct(v.location.href):v.location.href,s=this.Ne.custom_personal_data_properties,r=this.Ne.mask_personal_data_properties?[...vs,...s||[]]:[],n=nr(e,r,ir);this.R=this.R||{},this.R[n]||(this.R[n]=[]),this.R[n].push(t)}}cr(){this.R&&!mt(this.R)&&this.instance.capture("$$heatmap",{$heatmap_data:this.getAndClearBuffer()})}},deadClicksAutocapture:pl,webVitalsAutocapture:class{constructor(t){var e;this.Co=!1,this.vo=!1,this.R={navigationKey:void 0,url:void 0,metrics:[],firstMetricTimestamp:void 0},this.No=()=>{clearTimeout(this.qo),this.qo=void 0,this.R.metrics.length!==0&&(this._instance.capture("$web_vitals",b({$current_url:this.R.url},this.R.metrics.reduce(((s,r)=>b({},s,{["$web_vitals_"+r.name+"_event"]:b({},r),["$web_vitals_"+r.name+"_value"]:r.value})),{}))),this.R={navigationKey:void 0,url:void 0,metrics:[],firstMetricTimestamp:void 0})},this.jo=s=>{var r;if(this.R=this.R||{navigationKey:void 0,url:void 0,metrics:[],firstMetricTimestamp:void 0},D(s?.name)||D(s?.value))Lt.error("Invalid metric received",s);else{var n=typeof s.navigationURL=="string"?s.navigationURL:void 0,i=this.Bo(n);if(!x(i)){var o=he(s.navigationId)||typeof s.navigationId=="string"?"navigation:"+s.navigationId:"url:"+i;if(!this.Ho||this.Ho>s.value){this.R.navigationKey!==o&&(this.No(),this.qo=setTimeout(this.No,this.flushToCaptureTimeoutMs)),x(this.R.navigationKey)&&(this.R.navigationKey=o,this.R.url=i),this.R.firstMetricTimestamp=x(this.R.firstMetricTimestamp)?Date.now():this.R.firstMetricTimestamp,s.attribution&&s.attribution.interactionTargetElement&&(s.attribution.interactionTargetElement=void 0);var a=(r=this._instance.sessionManager)==null?void 0:r.checkAndGetSessionAndWindowId(!0),l=b({},s,n?{navigationURL:i}:{},{$current_url:i,timestamp:Date.now()});x(a)||(l.$session_id=a.sessionId,l.$window_id=a.windowId),this.R.metrics.push(l),this.R.metrics.length===this.allowedMetrics.length&&this.No()}else Lt.error("Ignoring metric with value >= "+this.Ho,s)}}},this.Uo=()=>{if(!this.vo){var s,r,n,i,o=$.__PosthogExtensions__,a=o?.postHogWebVitalsCallbacksByFlavor,l=a?.[this.zo]||(this.zo==="web-vitals"&&x(a)?o?.postHogWebVitalsCallbacks:void 0);if(x(l)||(s=l.onLCP,r=l.onCLS,n=l.onFCP,i=l.onINP),s&&r&&n&&i){var u={reportSoftNavs:this.useSoftNavs};this.allowedMetrics.indexOf("LCP")>-1&&s(this.jo.bind(this),u),this.allowedMetrics.indexOf("CLS")>-1&&r(this.jo.bind(this),u),this.allowedMetrics.indexOf("FCP")>-1&&n(this.jo.bind(this),u),this.allowedMetrics.indexOf("INP")>-1&&i(this.jo.bind(this),u),this.vo=!0}else Lt.error("web vitals callbacks not loaded - not starting")}},this._instance=t,this.Co=!((e=this._instance.persistence)==null||!e.props[Vi]),this.startIfEnabled()}get Wo(){return this._instance.config.capture_performance}get allowedMetrics(){var t,e,s=te(this.Wo)?(t=this.Wo)==null?void 0:t.web_vitals_allowed_metrics:void 0;return D(s)?((e=this._instance.persistence)==null?void 0:e.props[Gi])||["CLS","FCP","INP","LCP"]:s}get flushToCaptureTimeoutMs(){return(te(this.Wo)?this.Wo.web_vitals_delayed_flush_ms:void 0)||5e3}get useAttribution(){var t=te(this.Wo)?this.Wo.web_vitals_attribution:void 0;return t!=null&&t}get useSoftNavs(){var t=te(this.Wo)?this.Wo.__preview_web_vitals_soft_navs:void 0;return t!=null&&t}get Ho(){var t=te(this.Wo)&&he(this.Wo.__web_vitals_max_value)?this.Wo.__web_vitals_max_value:Rl;return t>0&&6e4>=t?Rl:t}get isEnabled(){var t=re?.protocol;if(t!=="http:"&&t!=="https:")return Lt.info("Web Vitals are disabled on non-http/https protocols"),!1;var e=te(this.Wo)?this.Wo.web_vitals:Ke(this.Wo)?this.Wo:void 0;return Ke(e)?e:this.Co}startIfEnabled(){this.isEnabled&&!this.vo&&(Lt.info("enabled, starting..."),this.ai(this.Uo))}onRemoteConfig(t){if(t.ok){var e=t.config;if("capturePerformance"in e){var s=te(e.capturePerformance)&&!!e.capturePerformance.web_vitals,r=te(e.capturePerformance)?e.capturePerformance.web_vitals_allowed_metrics:void 0;this._instance.persistence&&(this._instance.persistence.register({[Vi]:s}),this._instance.persistence.register({[Gi]:r})),this.Co=s,this.startIfEnabled()}}}get zo(){return this.useSoftNavs?this.useAttribution?"web-vitals-with-attribution-soft-navs":"web-vitals-soft-navs":this.useAttribution?"web-vitals-with-attribution":"web-vitals"}ai(t){var e=$.__PosthogExtensions__,s=this.zo,r=e?.postHogWebVitalsCallbacksByFlavor;r!=null&&r[s]||s==="web-vitals"&&x(r)&&e!=null&&e.postHogWebVitalsCallbacks?t():e==null||e.loadExternalDependency==null||e.loadExternalDependency(this._instance,s,(n=>{n?Lt.error("failed to load script",n):t()}))}Bo(t){var e=t||v?.location.href;if(e){var s=this._instance.config.disable_capture_url_hashes?Ct(e):e,r=this._instance.config.custom_personal_data_properties,n=this._instance.config.mask_personal_data_properties?[...vs,...r||[]]:[];return nr(s,n,ir)}Lt.error("Could not determine current URL")}}},Ef={exceptionObserver:class{constructor(t){var e;this.Uo=()=>{var s;if(v&&this.isEnabled&&(s=$.__PosthogExtensions__)!=null&&s.errorWrappingFunctions){var r=$.__PosthogExtensions__.errorWrappingFunctions.wrapOnError,n=$.__PosthogExtensions__.errorWrappingFunctions.wrapUnhandledRejection,i=$.__PosthogExtensions__.errorWrappingFunctions.wrapConsoleError;try{!this.Vo&&this.Ne.capture_unhandled_errors&&(this.Vo=r(this.captureException.bind(this))),!this.Zo&&this.Ne.capture_unhandled_rejections&&(this.Zo=n(this.captureException.bind(this))),!this.Go&&this.Ne.capture_console_errors&&(this.Go=i(this.captureException.bind(this)))}catch(o){Ms.error("failed to start",o),this.Qo()}}},this._instance=t,this.Ko=!((e=this._instance.persistence)==null||!e.props[Wi]),this.Jo=new yh(b({},(function(s){var r,n,i,o;return s===void 0&&(s={}),{refillRate:(r=(n=s.exceptionRateLimiterRefillRate)!==null&&n!==void 0?n:s.__exceptionRateLimiterRefillRate)!==null&&r!==void 0?r:1,bucketSize:(i=(o=s.exceptionRateLimiterBucketSize)!==null&&o!==void 0?o:s.__exceptionRateLimiterBucketSize)!==null&&i!==void 0?i:10}})(this._instance.config.error_tracking),{refillInterval:1e4,rt:Ms})),this.Ne=this.Yo(),this.startIfEnabledOrStop()}Yo(){var t=this._instance.config.capture_exceptions,e={capture_unhandled_errors:!1,capture_unhandled_rejections:!1,capture_console_errors:!1};return te(t)?e=b({},e,t):(x(t)?this.Ko:t)&&(e=b({},e,{capture_unhandled_errors:!0,capture_unhandled_rejections:!0})),e}get isEnabled(){return this.Ne.capture_console_errors||this.Ne.capture_unhandled_errors||this.Ne.capture_unhandled_rejections}startIfEnabledOrStop(){this.isEnabled?(Ms.info("enabled"),this.Qo(),this.ai(this.Uo)):this.Qo()}ai(t){var e,s;(e=$.__PosthogExtensions__)!=null&&e.errorWrappingFunctions?t():(s=$.__PosthogExtensions__)==null||s.loadExternalDependency==null||s.loadExternalDependency(this._instance,"exception-autocapture",(r=>{if(r)return Ms.error("failed to load script",r);t()}))}Qo(){var t,e,s;(t=this.Vo)==null||t.call(this),this.Vo=void 0,(e=this.Zo)==null||e.call(this),this.Zo=void 0,(s=this.Go)==null||s.call(this),this.Go=void 0}onRemoteConfig(t){if(t.ok){var e=t.config;"autocaptureExceptions"in e&&(this.Ko=!!e.autocaptureExceptions||!1,this._instance.persistence&&this._instance.persistence.register({[Wi]:this.Ko}),this.Ne=this.Yo(),this.startIfEnabledOrStop())}}onConfigChange(){this.Ne=this.Yo()}captureException(t){var e,s,r,n=(e=t==null||(s=t.$exception_list)==null||(s=s[0])==null?void 0:s.type)!==null&&e!==void 0?e:"Exception";this.Jo.consumeRateLimit(n)?Ms.info("Skipping exception capture because of client rate limiting.",{exception:n}):(r=this._instance.exceptions)==null||r.sendExceptionEvent(t)}},exceptions:class{constructor(t){var e,s;this.Xo=[],this.tl=new Lh([new zh,new Qh,new Vh,new qh,new Zh,new Yh,new Kh,new Xh],(function(r){for(var n=arguments.length,i=new Array(n>1?n-1:0),o=1;n>o;o++)i[o-1]=arguments[o];return function(a,l){l===void 0&&(l=0);for(var u=[],c=a.split(` -`),d=l;c.length>d;d++){var h=c[d];if(1024>=h.length){var p=Xa.test(h)?h.replace(Xa,"$1"):h;if(!p.match(/\S*Error: /)){for(var f of i){var g=f(p,r);if(g){u.push(g);break}}if(u.length>=50)break}}}return(function(m){if(!m.length)return[];var _=Array.from(m);return _.reverse(),_.slice(0,50).map((w=>{return b({},w,{filename:w.filename||(E=_,E[E.length-1]||{}).filename,function:w.function||gs});var E}))})(u)}})("web:javascript",jh,Wh)),this._instance=t,this.Xo=(e=(s=this._instance.persistence)==null?void 0:s.get_property(zi))!==null&&e!==void 0?e:[],this.el=Qr(this.il()),this.rl=new tp(this.el)}onConfigChange(){this.el=Qr(this.il()),this.rl.setConfig(this.el)}onRemoteConfig(t){var e,s,r;if(t.ok){var n=t.config;if("errorTracking"in n){var i=(e=(s=n.errorTracking)==null?void 0:s.suppressionRules)!==null&&e!==void 0?e:[],o=(r=n.errorTracking)==null?void 0:r.captureExtensionExceptions;this.Xo=i,this._instance.persistence&&this._instance.persistence.register({[zi]:this.Xo,[qi]:o})}}}get nl(){var t,e=!!this._instance.get_property(qi),s=this._instance.config.error_tracking.captureExtensionExceptions;return(t=s??e)!==null&&t!==void 0&&t}buildProperties(t,e){return this.tl.buildFromUnknown(t,{syntheticException:e?.syntheticException,mechanism:{handled:e?.handled}})}addExceptionStep(t,e){if(this.el.enabled)try{if(!W(t)||t.trim().length===0)return void Xe.warn("Ignoring exception step because message must be a non-empty string");var s=(function(i){if(!i)return{sanitizedProperties:{},droppedKeys:[]};var o=[];return{sanitizedProperties:Object.keys(i).reduce(((a,l)=>ep.has(l)?(o.push(l),a):(a[l]=i[l],a)),{}),droppedKeys:o}})(this.sl(e)),r=s.sanitizedProperties,n=s.droppedKeys;n.length>0&&Xe.warn("Ignoring reserved exception step fields",{droppedKeys:n}),this.rl.add(b({[Zr]:t,[Xr]:new Date().toISOString()},r))}catch(i){Xe.error("Failed to add exception step. Ignoring breadcrumb.",i)}}sendExceptionEvent(t){try{var e=t.$exception_list;if(this.al(e)){if(this.ol(e))return this.ll("Exception dropped: matched a suppression rule"),void Xe.info("Skipping exception capture because a suppression rule matched");if(!this.nl&&this.ul(e))return this.ll("Exception dropped: thrown by a browser extension"),void Xe.info("Skipping exception capture because it was thrown by an extension");if(!this._instance.config.error_tracking.__capturePostHogExceptions&&this.hl(e))return this.ll("Exception dropped: thrown by the PostHog SDK"),void Xe.info("Skipping exception capture because it was thrown by the PostHog SDK")}var s=this.el.enabled&&D(t.$exception_steps)?this.dl(t):t,r=typeof(i=globalThis._posthogReleaseId)=="string"&&i.length>0?i:void 0;r&&(s.$release_id=r);try{var n=this._instance.capture("$exception",s,{_noTruncate:!0,_batchKey:"exceptionEvent",Wn:!0});return n&&this.rl.clear(),n}catch(o){return Xe.error("Failed to capture exception event. Dropping this exception.",o),void this.rl.clear()}}catch(o){return void Xe.error("Failed to process exception event. Ignoring this exception.",o)}var i}dl(t){try{var e=this.rl.getAttachable();return e.length===0?t:b({},t,{$exception_steps:e})}catch(s){return Xe.error("Failed to read buffered exception steps. Capturing exception without steps.",s),t}}ll(t){this.el.enabled&&this.rl.add({[Zr]:t,[Xr]:new Date().toISOString()})}sl(t){return te(t)?b({},t):{}}il(){var t,e;return(t=(e=this._instance.config.error_tracking)==null?void 0:e.exception_steps)!==null&&t!==void 0?t:{}}ol(t){if(t.length===0)return!1;try{var e=t.reduce(((s,r)=>{var n=r.type,i=r.value;return W(n)&&n.length>0&&s.$exception_types.push(n),W(i)&&i.length>0&&s.$exception_values.push(i),s}),{$exception_types:[],$exception_values:[]});return this.Xo.some((s=>{var r=s.values.map((n=>{var i=td[n.operator],o=e[n.key];if(!i||!o)return!1;var a=L(n.value)?n.value:[n.value];return a.length>0&&i(a,o)}));return s.type==="OR"?r.some(Boolean):r.every(Boolean)}))}catch(s){return Xe.warn("Failed to evaluate suppression rules. Capturing the exception.",s),!1}}ul(t){return t.flatMap((e=>{var s,r;return(s=(r=e.stacktrace)==null?void 0:r.frames)!==null&&s!==void 0?s:[]})).some((e=>e.filename&&e.filename.startsWith("chrome-extension://")))}hl(t){if(t.length>0){var e,s,r,n,i=(e=(s=t[0].stacktrace)==null?void 0:s.frames)!==null&&e!==void 0?e:[],o=i[i.length-1];return(r=o==null||(n=o.filename)==null?void 0:n.includes("posthog.com/static"))!==null&&r!==void 0&&r}return!1}al(t){return!D(t)&&L(t)}}},Sf=b({productTours:class{get Mr(){return this._instance.persistence}constructor(t){this.vl=null,this.cl=null,this._instance=t}initialize(){this.loadIfEnabled()}onRemoteConfig(t){if(t.ok){var e=t.config;if("productTours"in e){var s,r;if(this.Mr&&this.Mr.register({[Wo]:!!e.productTours}),!Si(this._instance))return!this.vl&&D((s=this.Mr)==null?void 0:s.props[Ws])||Pr.info("product tours disabled; stopping and clearing cached tours"),(r=this.vl)==null||r.stop(),this.vl=null,void this.clearCache();this.loadIfEnabled()}}}loadIfEnabled(){!this.vl&&Si(this._instance)&&this.ai((()=>this.fl()))}ai(t){var e,s;(e=$.__PosthogExtensions__)!=null&&e.generateProductTours?t():(s=$.__PosthogExtensions__)==null||s.loadExternalDependency==null||s.loadExternalDependency(this._instance,"product-tours",(r=>{r?Pr.error("Could not load product tours script",r):t()}))}fl(){var t;!this.vl&&(t=$.__PosthogExtensions__)!=null&&t.generateProductTours&&(this.vl=$.__PosthogExtensions__.generateProductTours(this._instance,!0))}getProductTours(t,e){if(e===void 0&&(e=!1),!L(this.cl)||e){var s=this.Mr;if(s){var r=s.props[Ws];if(L(r)&&!e)return this.cl=r,void t(r,{isLoaded:!0})}this._instance._send_request({url:this._instance.requestRouter.endpointFor("api","/api/product_tours/?token="+this._instance.config.token),method:"GET",timestampMode:"query",callback:n=>{if(Si(this._instance)){var i=n.statusCode;if(i!==200||!n.json){var o="Product Tours API could not be loaded, status: "+i;return i===0?n.error||Pr.warn(o):Pr.error(o),void t([],{isLoaded:!1,error:o})}var a=L(n.json.product_tours)?n.json.product_tours:[];this.cl=a,s&&s.register({[Ws]:a}),t(a,{isLoaded:!0})}else t([],{isLoaded:!0})}})}else t(this.cl,{isLoaded:!0})}getActiveProductTours(t){D(this.vl)?t([],{isLoaded:!1,error:"Product tours not loaded"}):this.vl.getActiveProductTours(t)}showProductTour(t){var e;(e=this.vl)==null||e.showTourById(t)}previewTour(t){this.vl?this.vl.previewTour(t):this.ai((()=>{var e;this.fl(),(e=this.vl)==null||e.previewTour(t)}))}dismissProductTour(){var t;(t=this.vl)==null||t.dismissTour("user_clicked_skip")}nextStep(){var t;(t=this.vl)==null||t.nextStep()}previousStep(){var t;(t=this.vl)==null||t.previousStep()}clearCache(){var t;this.cl=null,(t=this.Mr)==null||t.unregister(Ws)}resetTour(t){var e;(e=this.vl)==null||e.resetTour(t)}resetAllTours(){var t;(t=this.vl)==null||t.resetAllTours()}cancelPendingTour(t){var e;(e=this.vl)==null||e.cancelPendingTour(t)}}},Rn),xf={siteApps:class{constructor(t){this.pl=0,this._instance=t,this.gl=[],this.apps={}}get isEnabled(){return!!this._instance.config.opt_in_site_apps}ml(t,e){if(e){var s=this.globalsForEvent(e);this.gl.push(s),this.gl.length>1e3&&(this.gl=this.gl.slice(10))}}get siteAppLoaders(){var t;return(t=$._POSTHOG_REMOTE_CONFIG)==null||(t=t[this._instance.config.token])==null?void 0:t.siteApps}initialize(){if(this.isEnabled){var t=this._instance._addCaptureHook(this.ml.bind(this));this.yl=()=>{t(),this.gl=[],this.yl=void 0}}}globalsForEvent(t){var e,s,r,n,i,o,a;if(!t)throw new Error("Event payload is required");var l={},u=this._instance.get_property("$groups")||[],c=this._instance.get_property("$stored_group_properties")||{};for(var d of Object.entries(c)){var h=d[0];l[h]={id:u[h],type:h,properties:d[1]}}var p=t.$set_once,f=t.$set;return{event:b({},Ic(t,pf),{properties:b({},t.properties,f?{$set:b({},(e=(s=t.properties)==null?void 0:s.$set)!==null&&e!==void 0?e:{},f)}:{},p?{$set_once:b({},(r=(n=t.properties)==null?void 0:n.$set_once)!==null&&r!==void 0?r:{},p)}:{}),elements_chain:(i=(o=t.properties)==null?void 0:o.$elements_chain)!==null&&i!==void 0?i:"",distinct_id:(a=t.properties)==null?void 0:a.distinct_id}),person:{properties:this._instance.get_property("$stored_person_properties")},groups:l}}bl(t){var e,s=(e=t.tagName)==null?void 0:e.toLowerCase();return s==="style"&&this._instance.config.prepare_external_dependency_stylesheet?this._instance.config.prepare_external_dependency_stylesheet(t)||(Ze.error("prepare_external_dependency_stylesheet returned null"),null):s==="script"&&this._instance.config.prepare_external_dependency_script?this._instance.config.prepare_external_dependency_script(t)||(Ze.error("prepare_external_dependency_script returned null"),null):t}_l(){var t,e,s,r,n,i,o,a;if(!this._instance.config.prepare_external_dependency_stylesheet&&!this._instance.config.prepare_external_dependency_script)return()=>{};var l=C?.defaultView,u=l==null||(t=l.Node)==null?void 0:t.prototype;if(!l||!u)return()=>{};if(this.pl++,this.wl)return this.kl();var c=[],d=this,h=new WeakSet,p=(m,_,w)=>{if(m!=null&&m[_]){var E=m[_];m[_]=w(E),c.push((()=>{m[_]=E}))}},f=m=>{if(h.has(m))return m;var _=d.bl(m);return _&&h.add(_),_},g=m=>m.map((_=>typeof _=="string"?_:f(_))).filter((_=>!$e(_)));return p(u,"appendChild",(m=>function(_){var w=f(_);return w?m.call(this,w):_})),p(u,"insertBefore",(m=>function(_,w){var E=f(_);return E?m.call(this,E,w):_})),p(u,"replaceChild",(m=>function(_,w){var E=f(_);return E?m.call(this,E,w):w})),[(e=l.Element)==null?void 0:e.prototype,(s=l.Document)==null?void 0:s.prototype,(r=l.DocumentFragment)==null?void 0:r.prototype].forEach((m=>{p(m,"append",(_=>function(){for(var w=arguments.length,E=new Array(w),I=0;w>I;I++)E[I]=arguments[I];return _.apply(this,g(E))})),p(m,"prepend",(_=>function(){for(var w=arguments.length,E=new Array(w),I=0;w>I;I++)E[I]=arguments[I];return _.apply(this,g(E))}))})),[(n=l.Element)==null?void 0:n.prototype,(i=l.CharacterData)==null?void 0:i.prototype,(o=l.DocumentType)==null?void 0:o.prototype].forEach((m=>{p(m,"before",(_=>function(){for(var w=arguments.length,E=new Array(w),I=0;w>I;I++)E[I]=arguments[I];return _.apply(this,g(E))})),p(m,"after",(_=>function(){for(var w=arguments.length,E=new Array(w),I=0;w>I;I++)E[I]=arguments[I];return _.apply(this,g(E))})),p(m,"replaceWith",(_=>function(){for(var w=arguments.length,E=new Array(w),I=0;w>I;I++)E[I]=arguments[I];var F=g(E);return E.length&&!F.length?void 0:_.apply(this,F)}))})),p((a=l.Element)==null?void 0:a.prototype,"insertAdjacentElement",(m=>function(_,w){var E=f(w);return E?m.call(this,_,E):null})),this.wl=()=>{c.forEach((m=>m())),this.wl=void 0},this.kl()}kl(){var t=!1;return()=>{var e;t||(t=!0,this.pl--,this.pl===0&&((e=this.wl)==null||e.call(this)))}}xl(t,e){e===void 0&&(e=!0);var s=this._l();try{var r=t(s);return e&&s(),r}catch(n){throw s(),n}}setupSiteApp(t){var e=this.apps[t.id],s=()=>{var o;!e.errored&&this.gl.length&&(Ze.info("Processing "+this.gl.length+" events for site app with id "+t.id),this.gl.forEach((a=>this.xl((()=>e.processEvent==null?void 0:e.processEvent(a))))),e.processedBuffer=!0),Object.values(this.apps).every((a=>a.processedBuffer||a.errored))&&((o=this.yl)==null||o.call(this))},r=!1,n=o=>{e.errored=!o,e.loaded=!0,Ze.info("Site app with id "+t.id+" "+(o?"loaded":"errored")),r&&s()};try{var i=this.xl((o=>t.init({posthog:this._instance,callback(a){o(),n(a)}})),!1).processEvent;i&&(e.processEvent=i),r=!0}catch(o){Ze.error(Ml+t.id,o),n(!1)}if(r&&e.loaded)try{s()}catch(o){Ze.error("Error while processing buffered events PostHog app with config id "+t.id,o),e.errored=!0}}Sl(){var t=this.siteAppLoaders||[];for(var e of t)this.apps[e.id]={id:e.id,loaded:!1,errored:!1,processedBuffer:!1};for(var s of t)this.setupSiteApp(s)}Cl(t){var e=this;if(Object.keys(this.apps).length!==0){var s=this.globalsForEvent(t),r=function(i){try{e.xl((()=>i.processEvent==null?void 0:i.processEvent(s)))}catch(o){Ze.error("Error while processing event "+t.event+" for site app "+i.id,o)}};for(var n of Object.values(this.apps))r(n)}}onRemoteConfig(t){var e,s,r,n=this;if((e=this.siteAppLoaders)!=null&&e.length)return this.isEnabled?(this.Sl(),void this._instance.on("eventCaptured",(l=>this.Cl(l)))):void Ze.error('PostHog site apps are disabled. Enable the "opt_in_site_apps" config to proceed.');if((s=this.yl)==null||s.call(this),t.ok){var i=t.config;if((r=i.siteApps)!=null&&r.length)if(this.isEnabled){var o=function(){var l,u=a.id,c=a.url;$["__$$ph_site_app_"+u]=n._instance,(l=$.__PosthogExtensions__)==null||l.loadSiteApp==null||l.loadSiteApp(n._instance,c,(d=>{if(d)return Ze.error(Ml+u,d)}))};for(var a of i.siteApps)o()}else Ze.error('PostHog site apps are disabled. Enable the "opt_in_site_apps" config to proceed.')}}}},kf={tracingHeaders:class{constructor(t){this.Ml=void 0,this.Tl=void 0,this.El=void 0,this.Uo=()=>{var e,s,r=this.Il();r?(x(this.Ml)&&(this.Ml=(e=$.__PosthogExtensions__)==null||(e=e.tracingHeadersPatchFns)==null?void 0:e._patchXHR(r,(()=>this._instance.get_distinct_id()),this._instance.sessionManager)),x(this.Tl)&&(this.Tl=(s=$.__PosthogExtensions__)==null||(s=s.tracingHeadersPatchFns)==null?void 0:s._patchFetch(r,(()=>this._instance.get_distinct_id()),this._instance.sessionManager))):this.Qo()},this._instance=t}initialize(){this.startIfEnabledOrStop()}ai(t){var e,s;(e=$.__PosthogExtensions__)!=null&&e.tracingHeadersPatchFns?t():(s=$.__PosthogExtensions__)==null||s.loadExternalDependency==null||s.loadExternalDependency(this._instance,"tracing-headers",(r=>{if(r)return df.error("failed to load script",r);t()}))}Pl(){var t,e;return(t=(e=this._instance.config.tracing_headers)!==null&&e!==void 0?e:this._instance.config.addTracingHeaders)!==null&&t!==void 0?t:this._instance.config.__add_tracing_headers}Il(){var t=this.Pl();return L(t)?(L(this.El)?this.El.splice(0,this.El.length,...t):this.El=[...t],t.length>0?this.El:void 0):(L(this.El)&&this.El.splice(0),this.El=t||void 0,this.El)}Qo(){var t,e;(t=this.Ml)==null||t.call(this),(e=this.Tl)==null||e.call(this),this.Ml=void 0,this.Tl=void 0}startIfEnabledOrStop(){this.Il()?this.ai(this.Uo):this.Qo()}}},If=b({surveys:class{get Ne(){return this._instance.config}constructor(t){this.Rl=void 0,this._surveyManager=null,this.Al=!1,this.Fl=[],this.Ll=null,this.Ol=null,this._instance=t,this._surveyEventReceiver=null}initialize(){this.loadIfEnabled()}onRemoteConfig(t){if(!this.Ne.disable_surveys){if(!t.ok)return q.warn("Remote config unavailable. Not loading surveys.");var e=t.config.surveys;if(D(e))return q.warn("Flags not loaded yet. Not loading surveys.");var s=L(e);this.Rl=s?e.length>0:e,q.info("flags response received, isSurveysEnabled: "+this.Rl),this.loadIfEnabled()}}reset(){try{var t;(t=this._surveyEventReceiver)==null||t.reset(),localStorage.removeItem("lastSeenSurveyDate");for(var e=[],s=0;slocalStorage.removeItem(n)))}catch{}}loadIfEnabled(){if(!this._surveyManager)if(this.Al)q.info("Already initializing surveys, skipping...");else if(this.Ne.disable_surveys)q.info(Ll);else if(this.Ne.cookieless_mode&&this._instance.consent.isOptedOut())q.info("Not loading surveys in cookieless mode without consent.");else{var t=$?.__PosthogExtensions__;if(t){if(!x(this.Rl)||this.Ne.advanced_enable_surveys){var e=this.Rl||this.Ne.advanced_enable_surveys;this.Al=!0;try{var s=t.generateSurveys;if(s)return void this.Dl(s,e);var r=t.loadExternalDependency;if(!r)return void this.$l(qo);r(this._instance,"surveys",(n=>{n||!t.generateSurveys?this.$l("Could not load surveys script",n):this.Dl(t.generateSurveys,e)}))}catch(n){throw this.$l("Error initializing surveys",n),n}finally{this.Al=!1}}}else q.error("PostHog Extensions not found.")}}Dl(t,e){this._surveyManager=t(this._instance,e),this._surveyEventReceiver=new mf(this._instance),q.info("Surveys loaded successfully"),this.Nl({isLoaded:!0})}$l(t,e){q.error(t,e),this.Nl({isLoaded:!1,error:t})}onSurveysLoaded(t){return this.Fl.push(t),this._surveyManager&&this.Nl({isLoaded:!0}),()=>{this.Fl=this.Fl.filter((e=>e!==t))}}getSurveys(t,e){if(e===void 0&&(e=!1),this.Ne.disable_surveys)return q.info(Ll),t([]);var s,r=this._instance.get_property(Ji);if(r&&!e)return t(r,{isLoaded:!0}),void(this.ql()&&this.getSurveys((()=>{}),!0));typeof Promise<"u"&&this.Ll?this.Ll.then((n=>t(n.surveys,n.context))):(typeof Promise<"u"&&(this.Ll=new Promise((n=>{s=n}))),this._instance._send_request({url:this._instance.requestRouter.endpointFor("api","/api/surveys/?token="+this.Ne.token),method:"GET",timestampMode:"query",timeout:this.Ne.surveys_request_timeout_ms,callback:n=>{var i;this.Ll=null;var o=n.statusCode;if(o!==200||!n.json){var a="Surveys API could not be loaded, status: "+o;o!==0?q.error(a):n.error||q.warn(a),this.Ol=Date.now();var l={isLoaded:!1,error:a};return t([],l),void(s==null||s({surveys:[],context:l}))}this.Ol=null;var u,c=n.json.surveys||[],d=c.filter((p=>(function(f){return!(!f.start_date||f.end_date)})(p)&&(rd(p)||(function(f){var g;return!((g=f.conditions)==null||(g=g.actions)==null||(g=g.values)==null||!g.length)})(p))));d.length>0&&((u=this._surveyEventReceiver)==null||u.register(d)),(i=this._instance.persistence)==null||i.register({[Ji]:c,[tn]:Date.now()});var h={isLoaded:!0};t(c,h),s?.({surveys:c,context:h})}}))}ql(){return this.jl()&&!this.Ll&&!this.Bl()}jl(){var t=this._instance.get_property(tn);return he(t)&&Date.now()-t>3e5}Bl(){return he(this.Ol)&&3e5>Date.now()-this.Ol}markSurveyAsSeen(t,e){var s,r={id:t,current_iteration:(s=e?.iteration)!==null&&s!==void 0?s:null};id(r);try{localStorage.setItem("lastSeenSurveyDate",new Date().toISOString())}catch{}}Nl(t){for(var e of this.Fl)try{if(!t.isLoaded)return e([],t);this.getSurveys(e)}catch(s){q.error("Error in survey callback",s)}}getActiveMatchingSurveys(t,e){if(e===void 0&&(e=!1),!D(this._surveyManager))return this._surveyManager.getActiveMatchingSurveys(t,e);q.warn("init was not called")}Hl(t){var e=null;return this.getSurveys((s=>{var r;e=(r=s.find((n=>n.id===t)))!==null&&r!==void 0?r:null})),e}Ul(t){if(D(this._surveyManager))return{eligible:!1,reason:Ar};var e=typeof t=="string"?this.Hl(t):t;return e?this._surveyManager.checkSurveyEligibility(e):{eligible:!1,reason:"Survey not found"}}zl(t){if(D(this._surveyManager))return{eligible:!1,reason:Ar};var e=typeof t=="string"?this.Hl(t):t;return e?this._surveyManager.checkSurveyRenderability(e):{eligible:!1,reason:"Survey not found"}}canRenderSurvey(t){if(D(this._surveyManager))return q.warn("init was not called"),{visible:!1,disabledReason:Ar};var e=this.zl(t);return{visible:e.eligible,disabledReason:e.reason}}canRenderSurveyAsync(t,e){return D(this._surveyManager)?(q.warn("init was not called"),Promise.resolve({visible:!1,disabledReason:Ar})):new Promise((s=>{this.getSurveys((r=>{var n,i=(n=r.find((a=>a.id===t)))!==null&&n!==void 0?n:null;if(i){var o=this.zl(i);s({visible:o.eligible,disabledReason:o.reason})}else s({visible:!1,disabledReason:"Survey not found"})}),e)}))}renderSurvey(t,e,s){var r;if(D(this._surveyManager))q.warn("init was not called");else{var n=typeof t=="string"?this.Hl(t):t;if(n!=null&&n.id)if(Zp.includes(n.type)){var i=C?.querySelector(e);if(i)return(r=n.appearance)!=null&&r.surveyPopupDelaySeconds?(q.info("Rendering survey "+n.id+" with delay of "+n.appearance.surveyPopupDelaySeconds+" seconds"),void setTimeout((()=>{var o,a;q.info("Rendering survey "+n.id+" with delay of "+((o=n.appearance)==null?void 0:o.surveyPopupDelaySeconds)+" seconds"),(a=this._surveyManager)==null||a.renderSurvey(n,i,s),q.info("Survey "+n.id+" rendered")}),1e3*n.appearance.surveyPopupDelaySeconds)):void this._surveyManager.renderSurvey(n,i,s);q.warn("Survey element not found")}else q.warn("Surveys of type "+n.type+" cannot be rendered in the app");else q.warn("Survey not found")}}displaySurvey(t,e){var s;if(D(this._surveyManager))q.warn("init was not called");else{var r=this.Hl(t);if(r){var n=r;if((s=r.appearance)!=null&&s.surveyPopupDelaySeconds&&e.ignoreDelay&&(n=b({},r,{appearance:b({},r.appearance,{surveyPopupDelaySeconds:0})})),e.displayType!==io.Popover&&e.initialResponses&&q.warn("initialResponses is only supported for popover surveys. prefill will not be applied."),e.ignoreConditions===!1){var i=this.Ul(r);if(!i.eligible)return void q.warn("Survey is not eligible to be displayed: ",i.reason)}e.displayType!==io.Inline?this._surveyManager.handlePopoverSurvey(n,e):this.renderSurvey(n,e.selector,e.properties)}else q.warn("Survey not found")}}cancelPendingSurvey(t){D(this._surveyManager)?q.warn("init was not called"):this._surveyManager.cancelSurvey(t)}handlePageUnload(){var t;(t=this._surveyManager)==null||t.handlePageUnload==null||t.handlePageUnload()}}},Rn),Cf={toolbar:class{constructor(t){this.instance=t}Wl(t){$.ph_toolbar_state=t}Vl(){var t;return(t=$.ph_toolbar_state)!==null&&t!==void 0?t:0}initialize(){return this.maybeLoadToolbar()}maybeLoadToolbar(t,e,s){if(t===void 0&&(t=void 0),e===void 0&&(e=void 0),s===void 0&&(s=void 0),so(this.instance.config)||!v||!C)return!1;t=t??v.location,s=s??v.history;try{if(!e){try{v.localStorage.setItem("test","test"),v.localStorage.removeItem("test")}catch{return!1}e=v?.localStorage}var r,n=vf||un(t.hash,"__posthog")||un(t.hash,"state"),i=n?el((()=>JSON.parse(atob(decodeURIComponent(n)))))||el((()=>JSON.parse(decodeURIComponent(n)))):null;return i&&i.action==="ph_authorize"?((r=i).source="url",r&&Object.keys(r).length>0&&(i.desiredHash?t.hash=i.desiredHash:s?s.replaceState(s.state,"",t.pathname+t.search):t.hash="")):((r=JSON.parse(e.getItem(Ol)||"{}")).source="localstorage",delete r.userIntent),!(!r.token||this.instance.config.token!==r.token||(this.loadToolbar(r),0))}catch{return!1}}Zl(t){var e=$.ph_load_toolbar||$.ph_load_editor;!D(e)&&Se(e)?e(t,this.instance):Dl.warn("No toolbar load function found")}loadToolbar(t){var e=!(C==null||!C.getElementById(wu));if(!v||e)return!1;var s=this.instance.requestRouter.region==="custom"&&this.instance.config.advanced_disable_toolbar_metrics,r=b({token:this.instance.config.token},t,{apiURL:this.instance.requestRouter.endpointFor("ui")},s?{instrument:!1}:{});if(v.localStorage.setItem(Ol,JSON.stringify(b({},r,{source:void 0}))),this.Vl()===2)this.Zl(r);else if(this.Vl()===0){var n;this.Wl(1),(n=$.__PosthogExtensions__)==null||n.loadExternalDependency==null||n.loadExternalDependency(this.instance,"toolbar",(i=>{if(i)return Dl.error("[Toolbar] Failed to load",i),void this.Wl(0);this.Wl(2),this.Zl(r)})),ne(v,"turbolinks:load",(()=>{this.Wl(0),this.loadToolbar(r)}))}return!0}Gl(t){return this.loadToolbar(t)}maybeLoadEditor(t,e,s){return t===void 0&&(t=void 0),e===void 0&&(e=void 0),s===void 0&&(s=void 0),this.maybeLoadToolbar(t,e,s)}}},Ff=b({experiments:ye},Rn),Pf={conversations:class{constructor(t){this.Ql=void 0,this._conversationsManager=null,this.Kl=!1,this.Jl=null,this.Yl=!1,this._instance=t}initialize(){this.loadIfEnabled()}onRemoteConfig(t){if(!this._instance.config.disable_conversations&&(this.Xl=t.ok,t.ok)){var e=t.config.conversations;D(e)||(Ke(e)?this.Ql=e:(this.Ql=e.enabled,this.Jl=e),this.loadIfEnabled())}}reset(){var t;(t=this._conversationsManager)==null||t.reset(),this._conversationsManager=null,this.Ql=void 0,this.Jl=null,this.Xl=void 0,this.Yl=!1}loadIfEnabled(){if(!(this._conversationsManager||this.Kl||this._instance.config.disable_conversations||so(this._instance.config)||this._instance.config.cookieless_mode&&this._instance.consent.isOptedOut())){var t=$?.__PosthogExtensions__;if(t&&!x(this.Ql)&&this.Ql)if(this.Jl&&this.Jl.token){this.Kl=!0;try{var e=t.initConversations;if(e)return this.tu(e),void(this.Kl=!1);var s=t.loadExternalDependency;if(!s)return void this.eu(qo);s(this._instance,"conversations",(r=>{r||!t.initConversations?this.eu("Could not load conversations script",r):this.tu(t.initConversations),this.Kl=!1}))}catch(r){this.eu("Error initializing conversations",r),this.Kl=!1}}else Ue.error("Conversations enabled but missing token in remote config.")}}tu(t){if(this.Jl)try{this._conversationsManager=t(this.Jl,this._instance),this.Yl=!1,Ue.info("Conversations loaded successfully")}catch(e){this.eu("Error completing conversations initialization",e)}else Ue.error("Cannot complete initialization: remote config is null")}eu(t,e){Ue.error(t,e),this._conversationsManager=null,this.Kl=!1,this.Yl=!0}show(){this._conversationsManager?this._conversationsManager.show():Ue.warn("Conversations not loaded yet.")}hide(){this._conversationsManager&&this._conversationsManager.hide()}isAvailable(){return this.Ql===!0&&!$e(this._conversationsManager)}getUnavailableReason(){return this.isAvailable()?null:this._instance.config.disable_conversations?"disabled_by_config":so(this._instance.config)?"disabled_for_toolbar":this._instance.config.cookieless_mode&&this._instance.consent.isOptedOut()?"consent_opted_out":this.Xl===!1?"remote_config_failed":x(this.Ql)?this.Xl?"disabled_in_project":"remote_config_pending":this.Ql?D(this.Jl)||!this.Jl.token?"missing_token":$!=null&&$.__PosthogExtensions__?this.Kl?"initializing":this.Yl?"load_failed":"not_loaded":"extensions_unavailable":"disabled_in_project"}isVisible(){var t,e;return(t=(e=this._conversationsManager)==null?void 0:e.isVisible())!==null&&t!==void 0&&t}sendMessage(t,e,s){var r=this;return X((function*(){return r._conversationsManager?r._conversationsManager.sendMessage(t,e,s):(Ue.warn(Dt),null)}))()}getMessages(t,e){var s=this;return X((function*(){return s._conversationsManager?s._conversationsManager.getMessages(t,e):(Ue.warn(Dt),null)}))()}markAsRead(t){var e=this;return X((function*(){return e._conversationsManager?e._conversationsManager.markAsRead(t):(Ue.warn(Dt),null)}))()}getTickets(t){var e=this;return X((function*(){return e._conversationsManager?e._conversationsManager.getTickets(t):(Ue.warn(Dt),null)}))()}requestRestoreLink(t){var e=this;return X((function*(){return e._conversationsManager?e._conversationsManager.requestRestoreLink(t):(Ue.warn(Dt),null)}))()}restoreFromToken(t){var e=this;return X((function*(){return e._conversationsManager?e._conversationsManager.restoreFromToken(t):(Ue.warn(Dt),null)}))()}restoreFromUrlToken(){var t=this;return X((function*(){return t._conversationsManager?t._conversationsManager.restoreFromUrlToken():(Ue.warn(Dt),null)}))()}getCurrentTicketId(){var t,e;return(t=(e=this._conversationsManager)==null?void 0:e.getCurrentTicketId())!==null&&t!==void 0?t:null}getWidgetSessionId(){var t,e;return(t=(e=this._conversationsManager)==null?void 0:e.getWidgetSessionId())!==null&&t!==void 0?t:null}Xn(){var t;(t=this._conversationsManager)==null||t.setIdentity()}ts(){var t;(t=this._conversationsManager)==null||t.clearIdentity()}}},Af={logs:class{constructor(t){var e,s=this;this.iu=!1,this.ru=!1,this.rt=se("[logs]"),this.nu=b({},this.rt,{error(){for(var r=arguments.length,n=new Array(r),i=0;r>i;i++)n[i]=arguments[i];n.some(Vl)||s.rt.error(...n)}}),this.tr=[],this.su=[],this.Sa=0,this.au=()=>{var r,n;this.Sa=0,(r=this.ou)==null||r.onReconnect(),(n=this.lu)==null||n.onReconnect()},this._instance=t,this._instance&&(e=this._instance.config.logs)!=null&&e.captureConsoleLogs&&(this.iu=!0),v&&ne(v,"online",this.au)}uu(t,e,s,r){var n,i=(function(o,a){var l,u,c,d,h,p,f,g=(l=o?.flushIntervalMs)!==null&&l!==void 0?l:3e3,m=(u=o?.maxBufferSize)!==null&&u!==void 0?u:100,_=a!=null&&a.consoleCapture?void 0:(c=o?.maxLogsPerInterval)!==null&&c!==void 0?c:1e3,w=x(_)?Math.max(m,2048):Math.max(m,_),E=o?.resourceAttributes;return{serviceName:(d=(h=E?.["service.name"])!==null&&h!==void 0?h:o?.serviceName)!==null&&d!==void 0?d:a?.serviceNameDefault,serviceVersion:(p=E?.["service.version"])!==null&&p!==void 0?p:o?.serviceVersion,environment:(f=E?.["deployment.environment"])!==null&&f!==void 0?f:o?.environment,resourceAttributes:E,beforeSend:o?.beforeSend,flushIntervalMs:g,maxBufferSize:m,maxQueueSize:w,maxBatchRecordsPerPost:100,rateCapWindowMs:g,maxLogsPerInterval:_,backgroundFlushBudgetMs:0,terminationFlushBudgetMs:0}})((n=this._instance)==null||(n=n.config)==null?void 0:n.logs,s);return[new Th(this.hu(t,e),i,this.nu,(()=>this.du()),(o=>o()),void 0,r),i]}vu(){var t,e=(t=this._instance)==null||(t=t.config)==null?void 0:t.logs;if(!this.ou||this.cu!==e){var s;(s=this.ou)==null||s.reset(),this.cu=e;var r=this.uu((()=>this.tr),(n=>{this.tr=n}));this.ou=r[0],this.fu=r[1]}return this.ou}pu(){var t,e=(t=this._instance)==null||(t=t.config)==null?void 0:t.logs;if(!this.lu||this.gu!==e){var s;(s=this.lu)==null||s.reset(),this.gu=e;var r=this.uu((()=>this.su),(n=>{this.su=n}),{serviceNameDefault:"posthog-browser-logs",consoleCapture:!0},ql);this.lu=r[0],this.mu=r[1]}return this.lu}initialize(){this.loadIfEnabled()}onRemoteConfig(t){var e;if(t.ok){var s=(e=t.config.logs)==null?void 0:e.captureConsoleLogs;!D(s)&&s&&(this.iu=!0,this.loadIfEnabled())}}reset(){var t,e;this.tr=[],(t=this.ou)==null||t.reset(),this.su=[],(e=this.lu)==null||e.reset(),this.Sa=0}captureLog(t){this.vu().captureLog(t)}he(t){this.pu().captureLog(t)}get logger(){return this.yu||(this.yu={trace:(t,e)=>this.captureLog({body:t,level:"trace",attributes:e}),debug:(t,e)=>this.captureLog({body:t,level:"debug",attributes:e}),info:(t,e)=>this.captureLog({body:t,level:"info",attributes:e}),warn:(t,e)=>this.captureLog({body:t,level:"warn",attributes:e}),error:(t,e)=>this.captureLog({body:t,level:"error",attributes:e}),fatal:(t,e)=>this.captureLog({body:t,level:"fatal",attributes:e})}),this.yu}flushLogs(t){t?this.bu(t):(this.ou&&this.ou.flush().catch((e=>this._u(e))),this.lu&&this.lu.flush().catch((e=>this._u(e))))}_u(t){Vl(t)||this.rt.error("PostHog logs flush failed:",t)}loadIfEnabled(){if(this.iu&&!this.ru){var t=$?.__PosthogExtensions__;if(t){var e=t.loadExternalDependency;e?e(this._instance,"logs",(s=>{var r;s||(r=t.logs)==null||!r.initializeLogs?this.rt.error("Could not load logs script",s):(t.logs.initializeLogs(this._instance),this.ru=!0)})):this.rt.error(qo)}else this.rt.error("PostHog Extensions not found.")}}hu(t,e){var s=this._instance;return{get isDisabled(){return!1},get optedOut(){return!s.is_capturing()},getPersistedProperty:r=>r===ut.LogsQueue?t():void 0,setPersistedProperty(r,n){var i;r===ut.LogsQueue&&e((i=n)!==null&&i!==void 0?i:[])},Ot:r=>this.Ot(r),getLibraryId:()=>Y.LIB_NAME,getLibraryVersion:()=>Y.LIB_VERSION}}Ot(t){return new Promise((e=>{if(Ru(this.Sa,3))e({kind:"fatal",error:ki(void 0,"logs endpoint is unreachable, dropping batch")});else{var s=!1,r=i=>{s||(s=!0,clearTimeout(n),e(i))},n=setTimeout((()=>{this.rt.warn("Logs request timed out before receiving a response"),r({kind:"retry-later",error:ki(void 0,"logs request timed out")})}),9e4);this._instance._send_request({method:"POST",url:this.wu(),data:t,compression:"best-available",batchKey:"logs",fireCallbackOnDrop:!0,callback:i=>{var o=i.statusCode;if(this.ku(o),o>=200&&300>o)r({kind:"ok"});else if(o===413)r({kind:"too-large"});else if(o!==0&&o!==429&&500>o)r({kind:"fatal",error:new Error("logs request failed with status "+o)});else{var a;o===0?(i.error||this.rt.warn("Logs request failed before receiving an HTTP response"),r({kind:"retry-later",error:ki(i.error,"logs request failed before receiving an HTTP response")})):r({kind:"retry-later",error:(a=i.error)!==null&&a!==void 0?a:new Error("logs request failed with status "+o)})}}})}}))}ku(t){(t!==0||this._instance.__loaded)&&(this.Sa=Tu(t,this.Sa,3,(()=>this.rt.warn("Log requests are failing before receiving an HTTP response; this can happen due to network issues, CORS, browser blocking, or ad blockers. Stopped sending logs; will try again when connectivity changes."))))}bu(t){this.tr.length>0&&this.xu(t,this.tr,this.fu,Y.LIB_NAME,(e=>{this.tr=e})),this.su.length>0&&this.xu(t,this.su,this.mu,ql,(e=>{this.su=e}))}xu(t,e,s,r,n){if(e.length!==0){var i=e.map((a=>a.record));n([]);var o=ru(i,su(s,Y.LIB_NAME,Y.LIB_VERSION),r,Y.LIB_VERSION);this._instance._send_request({method:"POST",url:this.wu(),data:o,compression:"best-available",batchKey:"logs",transport:t})}}wu(){return this._instance.requestRouter.endpointFor("api","/i/v1/logs")+"?token="+encodeURIComponent(this._instance.config.token)}du(){var t,e={};if(e.distinctId=this._instance.get_distinct_id(),this._instance.sessionManager){var s=this._instance.sessionManager.checkAndGetSessionAndWindowId(!0),r=s.windowId,n=s.sessionStartTimestamp,i=s.lastActivityTimestamp;e.sessionId=s.sessionId,e.windowId=r,D(n)||(e.sessionStartTimestamp=n),D(i)||(e.lastActivityTimestamp=i)}if($!=null&&(t=$.location)!=null&&t.href&&(e.currentUrl=this._instance.config.disable_capture_url_hashes?Ct($.location.href):$.location.href),this._instance.featureFlags){var o=this._instance.featureFlags.getFlags();o&&o.length>0&&(e.activeFeatureFlags=o)}return e}}},$f={metrics:class{constructor(t){this.rt=se("[metrics]"),this._instance=t}initialize(){}vu(){var t,e,s=(t=this._instance)==null||(t=t.config)==null?void 0:t.metrics;return this.ou&&this.cu===s||((e=this.ou)==null||e.reset(),this.cu=s,this.ou=new Nh(this.hu(),(function(r){var n,i,o,a,l,u=r?.resourceAttributes;return{serviceName:(n=u?.["service.name"])!==null&&n!==void 0?n:r?.serviceName,serviceVersion:(i=u?.["service.version"])!==null&&i!==void 0?i:r?.serviceVersion,environment:(o=u?.["deployment.environment"])!==null&&o!==void 0?o:r?.environment,resourceAttributes:u,beforeSend:r?.beforeSend,flushIntervalMs:(a=r?.flushIntervalMs)!==null&&a!==void 0?a:1e4,maxSeriesPerFlush:(l=r?.maxSeriesPerFlush)!==null&&l!==void 0?l:1e3}})(s),this.rt)),this.ou}count(t,e,s){e===void 0&&(e=1),this.vu().count(t,e,s)}gauge(t,e,s){this.vu().gauge(t,e,s)}histogram(t,e,s){this.vu().histogram(t,e,s)}flush(t){if(!this.ou)return Promise.resolve();if(t){var e=this.ou.drainWindow();return e&&this.Jt(e,t),Promise.resolve()}return this.ou.flush().catch((s=>this.rt.error("PostHog metrics flush failed:",s)))}reset(){var t;(t=this.ou)==null||t.reset()}hu(){var t=this._instance,e=this;return{get isDisabled(){return!1},get optedOut(){return!t.is_capturing()},Jt:s=>e.Jt(s),getLibraryId:()=>Y.LIB_NAME,getLibraryVersion:()=>Y.LIB_VERSION}}Jt(t,e){return new Promise((s=>{var r=!1,n=o=>{r||(r=!0,clearTimeout(i),s(o))},i=setTimeout((()=>n({kind:"retry-later",error:new Error("metrics request timed out")})),9e4);this._instance._send_request(b({method:"POST",url:this.Su(),data:t,compression:"best-available",batchKey:"metrics"},e&&{transport:e},{fireCallbackOnDrop:!0,callback(o){var a=o.statusCode;if(a>=200&&300>a)n({kind:"ok"});else if(a===413)n({kind:"too-large"});else if(a!==0&&a!==429&&500>a)n({kind:"fatal",error:new Error("metrics request failed with status "+a)});else{var l;n({kind:"retry-later",error:(l=o.error)!==null&&l!==void 0?l:new Error("metrics request failed with status "+a)})}}}))}))}Su(){return this._instance.requestRouter.endpointFor("api","/i/v1/metrics")+"?token="+encodeURIComponent(this._instance.config.token)}}},Rf=b({},Rn,wf,bf,Ef,Sf,xf,If,kf,Cf,Ff,Pf,Af,$f);Te.__defaultExtensionClasses=b({},Rf);(function(){Y.SDK_DIST_CHANNEL="npm";var t=Ys[os]=new Te;return(function(){function e(){e.done||(e.done=!0,ad=!1,Z(Ys,(function(s){s._dom_loaded()})))}C!=null&&C.addEventListener?C.readyState==="complete"?e():ne(C,"DOMContentLoaded",e,{capture:!1}):v&&k.error("Browser doesn't support `document.addEventListener` so PostHog couldn't be initialized")})(),t})();const cd="CodeFile",ud="GeneratedCode",Tf={CustomAction:"A",CustomWidget:"W",CustomFunction:"F",CustomClass:"C",CodeFile:"C"};function kt(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}function fo(t){return String(t||"").trim().replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function Nf(t={},e=0){const s=fo(t.artifactType||t.type||cd),r=fo(t.artifactName||t.name||t.fileName||`${ud}-${e+1}`);return`${s||"artifact"}-${r||e+1}`}function dd(t={},e=0){const s=kt(t),r=s.artifactType||s.type||cd,n=s.artifactName||s.name||ud;let i=s.fileName||n;return i.endsWith(".dart")||(i+=".dart"),{id:fo(s.id)||Nf({...s,artifactType:r,artifactName:n,fileName:i},e),artifactType:r,artifactName:n,fileName:i,deployPath:s.deployPath||"",description:s.description||"",code:s.code||s.content||"",dependencies:hd(s.dependencies),imports:Array.isArray(s.imports)?s.imports:[],publicApi:Array.isArray(s.publicApi)?s.publicApi:[],relationships:pd(s.relationships),deployStatus:s.deployStatus||"pending",review:s.review||null,metadata:kt(s.metadata),codeType:s.codeType||Tf[r]||"O"}}function hd(t){return t?Array.isArray(t)?t.map(e=>{if(typeof e=="string")return{name:e,version:null,inferred:!1};const s=kt(e),r=s.name||s.package;return r?{name:r,version:s.version||null,versionRequired:!!(s.versionRequired||s.required),inferred:!!s.inferred,...s.reason?{reason:s.reason}:{}}:null}).filter(Boolean):Object.entries(kt(t)).map(([e,s])=>({name:e,version:s||null,inferred:!1})):[]}function pd(t){return t?(Array.isArray(t)?t:[t]).map(e=>{const s=kt(e);return!s.from&&!s.to?null:{from:s.from||null,to:s.to||null,type:s.type||"uses",description:s.description||""}}).filter(Boolean):[]}function go(t){if(typeof t!="string")return null;const e=t.trim();if(!e)return null;try{return JSON.parse(e)}catch{const s=e.match(/```(?:json)?\s*([\s\S]*?)```/i);if(!s)return null;try{return JSON.parse(s[1].trim())}catch{return null}}}function or(t,e={}){const s=[],r=typeof t=="string"?go(t):t,i=kt(r||{});!r&&typeof t=="string"&&s.push("Structured bundle parse failed; using legacy single-artifact fallback.");const o=Array.isArray(i.artifacts)?i.artifacts:[{artifactType:i.artifactType||e.artifactType,artifactName:i.artifactName||e.artifactName,fileName:i.fileName||e.fileName,description:i.description,code:i.code||e.code||(typeof t=="string"?t:""),dependencies:i.dependencies||e.dependencies,relationships:i.relationships||e.relationships}];o.forEach((d,h)=>{!d?.artifactType&&!d?.type&&s.push(`Artifact ${h+1} has no artifactType; it will deploy as a standalone code file under lib/custom_code/ root.`)});const a=o.map((d,h)=>dd(d,h)),l=new Map(o.map((d,h)=>[kt(d).id,a[h]?.id]).filter(([d,h])=>d&&h)),u=d=>l.get(d)||d,c=pd(i.relationships||e.relationships).map(d=>({...d,from:d.from?u(d.from):d.from,to:d.to?u(d.to):d.to}));return{schemaVersion:i.schemaVersion||e.schemaVersion||null,id:i.id||e.id||"bundle-current",title:i.title||i.name||e.title||"Generated artifact bundle",description:i.description||e.description||"",artifacts:a,dependencies:hd(i.dependencies||e.dependencies),relationships:c,deployOrder:Array.isArray(i.deployOrder)?i.deployOrder.map(u):a.map(d=>d.id),warnings:[...s,...Array.isArray(i.warnings)?i.warnings:[]],metadata:kt(i.metadata)}}function gn(t){return or(t).artifacts[0]||dd()}function yt(t){if(typeof t!="string")return t??"";const e=t.trim();if(!e)return"";try{return JSON.parse(e)}catch{return t}}function ys(t){return JSON.stringify(t,null,2)}function Mf(t){return ys({task:"architect",userRequest:String(t??"")})}function Lf(t){const e=yt(t);return e&&typeof e=="object"&&typeof e.task=="string"?ys(e):ys({task:"generate_bundle",bundleSpec:e})}function Of(t){return ys({task:"review_bundle",generatedBundle:yt(t),outputRequirements:{bundleReview:["status","score","summary","manualActions","findings"],scoreRange:[0,100],eachArtifact:["id","review.status","review.findings"],manualActions:{definition:"Setup the developer must perform by hand in the FlutterFlow editor that FlutterFlow will NOT do for them.",exclude:["creating the Custom Action, Widget or Code File itself - deploying the code creates it","declaring parameters or return values FlutterFlow derives from the function signature","anything that resolves as a side effect of using the action or widget in the editor","generic advice such as testing, reviewing or rebuilding the app"],preferEmpty:"Return an empty array when nothing qualifies - an empty list is the expected result for most bundles."}}})}function Qo(t,e=null){const s={stage:t};return e!=null&&(s.bundle=yt(e)),s}function Df({bundleSpec:t,artifactBundle:e,bundleReview:s,artifactId:r,userFeedback:n}){return ys({task:"regenerate_artifact",artifactId:r,bundleSpec:yt(t),artifactBundle:yt(e),bundleReview:yt(s),userFeedback:String(n)})}function fd({bundleSpec:t,artifactBundle:e,bundleReview:s,userFeedback:r}){return ys({task:"regenerate_bundle",bundleSpec:yt(t),artifactBundle:yt(e),bundleReview:yt(s),userFeedback:String(r??"")})}const Gl={csam:"child-safety content",dangerous:"dangerous content",harassment:"harassment",hate_speech:"hate speech",maliciousUrls:"a potentially malicious URL",malicious_uris:"a potentially malicious URL",pi_and_jailbreak:"prompt-injection or jailbreak instructions",promptInjection:"prompt-injection or jailbreak instructions",rai:"restricted content",sdp:"sensitive personal data",sexually_explicit:"sexually explicit content",virus_scan:"potentially malicious file content"},Bf=["sanitizationResult","modelArmor","modelArmorResult","data","result","error"];function Le(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function jf(t){return Le(t)?typeof t.filterMatchState=="string"||typeof t.invocationResult=="string"||Array.isArray(t.matchedFilters)||Le(t.filterSummary)||Le(t.filterResults):!1}function gd(t,e=0){if(!Le(t)||e>3)return null;if(jf(t))return t;for(const s of Bf){const r=t[s];if(Le(r)){const n=gd(r,e+1);if(n)return n}}return null}function mn(t){return Array.isArray(t)?t.some(mn):Le(t)?t.matched===!0||t.matchState==="MATCH_FOUND"?!0:Object.values(t).some(mn):!1}function mo(t){return Array.isArray(t)?t.some(mo):Le(t)?typeof t.executionState=="string"&&t.executionState!=="EXECUTION_SUCCESS"?!0:Object.values(t).some(mo):!1}function md(t){return{csamFilterFilterResult:"csam",maliciousUriFilterResult:"malicious_uris",piAndJailbreakFilterResult:"pi_and_jailbreak",raiFilterResult:"rai",sdpFilterResult:"sdp",virusScanFilterResult:"virus_scan"}[t]||t}function Uf(t,e){if(Le(t))for(const[s,r]of Object.entries(t)){if(!Le(r))continue;const n=Le(r.categories)?r.categories:{},i=Object.entries(n).filter(([,o])=>Le(o)&&o.matched===!0).map(([o])=>o);i.length>0?i.forEach(o=>e.add(o)):r.matched===!0&&e.add(md(s))}}function Hf(t,e){if(!t)return;const s=Array.isArray(t)?t.flatMap(r=>Le(r)?Object.entries(r):[]):Object.entries(t);for(const[r,n]of s){if(!mn(n))continue;const i=md(r),o=n?.raiFilterResult?.raiFilterTypeResults||(i==="rai"?n?.raiFilterTypeResults:null),a=Le(o)?Object.entries(o).filter(([,l])=>mn(l)).map(([l])=>l):[];a.length>0?a.forEach(l=>e.add(l)):e.add(i)}}function Wf(t){return Gl[t]?Gl[t]:String(t).replace(/([a-z])([A-Z])/g,"$1 $2").replace(/_/g," ").toLowerCase()}function Kl(t){return t.length<=1?t[0]||"content that did not pass":t.length===2?`${t[0]} and ${t[1]}`:`${t.slice(0,-1).join(", ")}, and ${t.at(-1)}`}function zf(t){const e=gd(t);if(!e)return null;const s=new Set(Array.isArray(e.matchedFilters)?e.matchedFilters:[]);Uf(e.filterSummary,s),Hf(e.filterResults,s);const r=e.blocked===!0||e.filterMatchState==="MATCH_FOUND"||s.size>0,n=e.invocationResult||null,i=mo(e.filterSummary||e.filterResults);return!r&&!i&&!["PARTIAL","FAILURE"].includes(n)?null:{kind:r?"blocked":"unavailable",invocationResult:n,matchedFilters:[...s]}}function qf(t,e){const s=zf(t);if(!s)return null;const r=[...new Set(s.matchedFilters.map(Wf))],n=s.kind==="blocked",i=new Error(n?`Safety screening blocked this pipeline step for ${Kl(r)}.`:"Safety screening could not be completed. Please try again.");return i.name="ModelArmorError",i.code=n?"MODEL_ARMOR_BLOCKED":"MODEL_ARMOR_UNAVAILABLE",i.isModelArmor=!0,i.pipelineStep=e,i.userTitle=n?"Request blocked for safety":"Safety check unavailable",i.userMessage=n?`The safety check detected ${Kl(r)}. Edit your request to remove or rephrase the flagged content, then run the pipeline again.`:"The safety service did not finish all of its checks. Please wait a moment and run the pipeline again.",i.retryExplanation=n?"Trying another model would not change this safety decision.":"A fallback model was not attempted because safety screening must complete first.",i.matchedFilters=s.matchedFilters,i}function Vf(t){return String(t||"").replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/[^\n]*/g,"")}function Jl(t){const e=/^(import|export|part|library|class|enum|extension|typedef|mixin|abstract|const|final|var|late)\b/,s=[];for(const r of Vf(t).split(` -`)){if(!/^[A-Za-z_$]/.test(r)||e.test(r))continue;const n=r.match(/^[\w$<>,?\s[\]]+?\s([a-zA-Z_$][\w$]*)\s*\(/);n&&s.push(n[1])}return s}function ea(t,e){const s=t.replace(/\.dart$/,"");if(e==="W")return s.replace(/(^|_)(\w)/g,(r,n,i)=>i.toUpperCase());if(e==="A"){const r=s.replace(/(^|_)(\w)/g,(n,i,o)=>o.toUpperCase());return r.charAt(0).toLowerCase()+r.slice(1)}return e==="F"?"CustomFunctions":e==="C"?t.endsWith(".dart")?t:`${t}.dart`:s}async function Yl(t){const e=new TextEncoder().encode(String(t||"")),s=await globalThis.crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(s),r=>r.toString(16).padStart(2,"0")).join("")}async function Gf(t,e=new Map){const s={},r=new Set;for(const[o,a]of t.entries()){if(a.type==="D"||a.type==="O")continue;const l=ea(o,a.type),u={old_identifier_name:l,new_identifier_name:l,type:a.type,is_deleted:!1,current_checksum:await Yl(a.content)},c=e.get(a.path);if(c!==void 0&&(u.original_checksum=await Yl(c)),s[o]=u,a.type==="F"){const d=Jl(a.content);(d.length>0?d:[a.functionName].filter(Boolean)).forEach(p=>r.add(p))}}const n=new Set(Jl(e.get("lib/flutter_flow/custom_functions.dart")||"")),i={functions_to_rename:[],functions_to_delete:[],functions_to_add:Array.from(r).filter(o=>!n.has(o))};return{fileMapContents:JSON.stringify(s),functionsMapContents:JSON.stringify(i)}}const Kf=new Set(["CustomWidget","CustomAction","CustomFunction","CustomClass","CodeFile"]),Zl={CustomWidget:"custom_code/widgets/",CustomAction:"custom_code/actions/",CustomFunction:"flutter_flow/custom_functions.dart",CustomClass:"custom_code/",CodeFile:"custom_code/"},Jf=new Set(["void","dynamic","String","int","double","num","bool","Color","DateTime","DateTimeRange","LatLng","FFPlace","FFUploadedFile","DocumentReference","List"]),Yf=["Struct","Record"],Zf=[{id:"required-public-param",severity:"error",message:"CustomWidget constructor uses `required` on a parameter FlutterFlow can leave unset. FlutterFlow omits unset Define Parameters fields from the constructor call, so the widget will not compile when placed. Make the parameter optional and nullable (`this.value` with `final double? value`), or give it a constructor default (`this.value = 0.0`).",detect:t=>Ii(t).some(e=>/\brequired\s+this\.\w+/.test(e)),pos:"class W extends StatefulWidget { const W({required this.value}); final double value; }",neg:`class _P { const _P({required this.t}); final double t; } -class W extends StatefulWidget { const W({this.value}); final double? value; }`},{id:"non-nullable-public-field",severity:"error",message:"CustomWidget declares a non-nullable field with no constructor default. FlutterFlow omits unset Define Parameters fields, so the emitted call cannot supply it. Make the field nullable (`final double? value`) or give the parameter a default (`this.value = 0.0`).",detect:t=>Ii(t).some(e=>{const s=/^\s*final\s+(?:double|int|String|bool|Color|num)\s+(\w+)\s*;/gm;let r;for(;(r=s.exec(e))!==null;){const n=r[1];if(!(new RegExp(`this\\.${n}\\s*=(?!=)`).test(e)||new RegExp(`[:,]\\s*${n}\\s*=(?!=)`).test(e)))return!0}return!1}),pos:`class W extends StatefulWidget { - const W({required this.value}); - final double value; -}`,neg:`class _P { - const _P({required this.t}); - final double t; -} -class W extends StatefulWidget { - const W({this.value = 1.0}); - final double value; -}`},{id:"asset-without-anchor",severity:"warning",message:'CustomWidget calls Image.asset with a path arriving as a String parameter. An asset reaches the build only when a FlutterFlow widget NODE references it - a filename passed as a parameter does not count, so the image renders as a broken-image icon on device. "Download Unused Project Assets" does not fix it (FlutterFlow issues 522, 2271, 3799). Keep something in the UI referencing the file, or load it over the network instead.',detect:t=>/Image\.asset\s*\(/.test(t)&&/final\s+String\??\s+\w*[Pp]ath\b/.test(t),pos:`class W extends StatefulWidget { final String? imagePath; } -var x = Image.asset(widget.imagePath);`,neg:`class W extends StatefulWidget { final String? imagePath; } -var x = Image.network(widget.imagePath);`},{id:"unsupported-param-type",severity:"error",message:"CustomWidget exposes a Flutter data type FlutterFlow cannot express as a Define Parameter: TextStyle, BoxShadow, FontWeight, FontStyle, TextDirection, TextAlign, EdgeInsets, Offset, Alignment/AlignmentGeometry, Border, BorderRadius, BoxDecoration, BoxConstraints, BorderSide, Gradient, or ThemeData. FlutterFlow's supported data types (docs.flutterflow.io/resources/data-representation/data-types) are only int, double, bool, string, Color, Image, DateTime, Json, LatLng, and the FF objects, so this parameter cannot be configured in the editor and the widget will not place or compile. Expose primitives instead (color, fontSize as double?, fontWeight via a custom enum, doubles for spacing).",detect:t=>Ii(t).some(e=>/final\s+(TextStyle|BoxShadow|FontWeight|FontStyle|TextDirection|TextAlign|EdgeInsets|Offset|Alignment(?:Geometry)?|Border(?:Radius|Side)?|BoxDecoration|BoxConstraints|Gradient|LinearGradient|RadialGradient|ThemeData)\??\s+\w+\s*;/.test(e)),pos:`class W extends StatefulWidget { - const W({this.textStyle}); - final TextStyle? textStyle; - @override _S createState() => _S(); -} -class _S extends State { @override Widget build(BuildContext c) => const SizedBox(); }`,neg:`class W extends StatefulWidget { - const W({this.width}); - final double? width; - @override _S createState() => _S(); -} -class _S extends State { @override Widget build(BuildContext c) => Padding(padding: const EdgeInsets.all(8), child: const SizedBox()); }`}];function Qe(t,e,s){return{artifactId:t.id,artifactName:t.artifactName,artifactType:t.artifactType,severity:e,message:s}}function ar(t){let e="",s=0;for(;s"&&(s--,s===0))return{inner:t.slice(e+1,r),end:r+1};return null}function Qf(t,e){const s=new RegExp(`class\\s+${e}\\b[^{]*\\{`).exec(t);if(!s)return null;let r=0;for(let n=s.index+s[0].length-1;neg(t).usable);function sg(t=""){const e=ar(t);return tg.filter(s=>s.detect(e)).map(({id:s,severity:r,message:n})=>({id:s,severity:r,message:n}))}function rg(t){const e=[],s=t.matchAll(/\bFuture\b/g);for(const r of s){let n=r.index+6,i=null;const o=n;for(;no;if(t[n]==="<"){const u=Xf(t,n);if(!u||(i=u.inner.replace(/\s+/g," ").trim(),n=u.end,!/\s/.test(t[n]||"")))continue;for(;nXl(o.functionName)===r);if(n)return n;const i=o=>!o.functionName.startsWith("_");return s.find(i)||s[0]}function Tn(t=""){return Array.from(ar(t).matchAll(/\b(?:class|enum)\s+([A-Za-z_]\w*)/g),e=>e[1])}function ng(t="",e=""){return ta(t,e)?.returnType||null}function Ql(t){return String(t||"").replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").toLowerCase()}function ig(t,e){const s=Tn(e);if(s.length===0)return null;const n=String(t||"").split("/").pop().replace(/\.dart$/,"");if(s.some(l=>Ql(l)===n)||s.length>1)return null;const[o]=s,a=`${Ql(o)}.dart`;return`File name "${t}" does not match declared class "${o}". FlutterFlow accepts this, but naming the file "${a}" keeps the Code File recognisable in the editor.`}function sa(t){return String(t||"").replace(/([A-Z])/g,"_$1").toLowerCase().replace(/^_/,"")}function og(t,e,s=""){const r=ta(e,s)?.functionName;if(!r)return null;const n=String(t||"").split("/").pop(),i=ea(n,"A");if(i===r)return null;const o=`${sa(r)}.dart`;return`File name "${n}" does not match Action "${r}". FlutterFlow derives the action from the file name, so it looks for "${i}" and reports Action "${i}" declaration not found. Rename the file to "${o}" - FlutterFlow puts an underscore before every capital - or rename the function to "${i}".`}function ag(t="",e=""){return ta(t,e)!==null}function lg(t,e=new Set){return(t?.match(/[A-Za-z_]\w*/g)||[]).filter(r=>Jf.has(r)?!1:!Yf.some(i=>r.endsWith(i))||e.has(r))}function cg(t,{functionName:e="",declaredTypes:s=new Set}={}){const r=ng(t,e),n=lg(r,s);if(n.length===0)return null;const[i]=n;let o;return s.has(i)?o=`uses Code File type "${i}", which FlutterFlow cannot process as an Action Return Value`:r===i?o="is not a FlutterFlow Action Return Value":o=`uses type "${i}", which is not a FlutterFlow Action Return Value`,`CustomAction return type "${r}" ${o}. Return JSON (Future) or an existing FlutterFlow Data Type (*Struct) instead.`}function ug(t,e={}){const s=[],r=t.fileName||"",n=t.code||"";if(Kf.has(t.artifactType)||s.push(Qe(t,"error",`Unsupported artifact type "${t.artifactType}".`)),r.endsWith(".dart")||s.push(Qe(t,"error","FlutterFlow custom code artifacts must use .dart files.")),!n.trim())return s.push(Qe(t,"warning","Generated artifact has no Dart code yet.")),s;if(t.artifactType==="CustomWidget"){/class\s+\w+\s+extends\s+(StatelessWidget|StatefulWidget)/.test(n)||s.push(Qe(t,"warning","CustomWidget code should declare a widget class extending StatelessWidget or StatefulWidget."));for(const i of sg(n))s.push(Qe(t,i.severity,i.message))}if(t.artifactType==="CustomAction"&&!ag(n,t.artifactName)&&s.push(Qe(t,"warning","CustomAction code should expose an async Future function callable from FlutterFlow.")),t.artifactType==="CustomAction"){const i=e.declaredTypes||new Set(Tn(n)),o=cg(n,{functionName:t.artifactName,declaredTypes:i});o&&s.push(Qe(t,"error",o));const a=og(r,n,t.artifactName);a&&s.push(Qe(t,"error",a))}if(t.artifactType==="CustomFunction"&&/class\s+\w+\s+extends\s+(StatelessWidget|StatefulWidget)/.test(n)&&s.push(Qe(t,"warning","CustomFunction should be a callable function, not a widget class.")),t.artifactType==="CustomClass"||t.artifactType==="CodeFile"){const i=ig(r,n);i&&s.push(Qe(t,"info",i))}return s}function dg(t){const e=Array.isArray(t?.artifacts)?t.artifacts:[],s=new Set(e.flatMap(i=>Tn(i.code||""))),r=e.flatMap(i=>ug(i,{declaredTypes:s})),n=e.map(i=>({artifactId:i.id,fileName:i.fileName,pathHint:Zl[i.artifactType]||Zl.CodeFile}));return{valid:r.every(i=>i.severity!=="error"),findings:r,deployHints:n}}const ec="// DO NOT REMOVE OR MODIFY THE CODE ABOVE!";function tc(t){return(/^\s*import\s+['"]([^'"]+)['"]/.exec(t)||[])[1]||null}function hg(t=""){const e=t.indexOf(ec);return e===-1?t:t.slice(e+ec.length).replace(/^\s*\n/,"")}const pg=/^\s*import\s+['"][^'"]+['"]\s*;\s*(?:\/\/.*)?$/;function fg(t="",e=""){const s=hg(t),r=new Set((e.match(/^\s*import .*$/gm)||[]).map(tc).filter(Boolean)),n=s.split(` -`).filter(i=>{const o=tc(i);return o===null||!r.has(o)?!0:!pg.test(i)}).join(` -`).replace(/^\s*\/\/ Automatic FlutterFlow imports\s*$/m,"").replace(/^\s*\n+/,"");return e+n}const gg=new Set(["flutter","flutter_test","flutter_driver","flutter_localizations"]);function vd(t){let e="",s=0;for(;s{const r=s.name||s.package;if(!r||r==="flutter")return e;const n=s.versionRequired||s.required;return e[r]=n&&s.version||"",e},{})}function yg(t){const e=new Map,s=new Map,r=[];for(const n of t)e.has(n.fileName)?r.push(`Duplicate deploy file name "${n.fileName}" for artifacts "${e.get(n.fileName)}" and "${n.artifactId}".`):e.set(n.fileName,n.artifactId),s.has(n.path)?r.push(`Duplicate deploy path "${n.path}" for artifacts "${s.get(n.path)}" and "${n.artifactId}".`):s.set(n.path,n.artifactId);return r}function wg(t,e={}){const s=Array.isArray(t?.artifacts)?t.artifacts:[],n=(e.selectedArtifactIds||t?.deployOrder||s.map(p=>p.id)).map(p=>s.find(f=>f.id===p)).filter(Boolean),i=[...t?.warnings||[]];let o=[];n.forEach(p=>{const f=_g(p),g=p.fixedCode||p.code||"",m=p.codeType||mg[p.artifactType]||Ne.OTHER;g.trim()||i.push(`${p.artifactName||p.id} has no generated code.`),o.push({artifactId:p.id,artifactName:p.artifactName,artifactType:p.artifactType,fileName:f,content:g,type:m,path:p.deployPath||vg(f,m),deployPath:p.deployPath||"",deployMode:"customCodeSync"})});const a="lib/flutter_flow/custom_functions.dart",l=o.map((p,f)=>({entry:p,index:f})).filter(({entry:p})=>p.type===Ne.FUNCTION&&p.path===a);if(l.length>1){const p=l[0],f={...p.entry,artifactId:l.map(({entry:m})=>m.artifactId).join("+"),artifactName:p.entry.artifactName,content:l.map(({entry:m})=>`// ${m.artifactId} -${m.content}`).join(` - -`)},g=new Set(l.slice(1).map(({index:m})=>m));o=o.filter((m,_)=>!g.has(_)),o[p.index]=f}const u={...sc(t?.dependencies),...n.reduce((p,f)=>({...p,...sc(f.dependencies)}),{})},c={};n.forEach(p=>{ra(p.code||"").forEach(f=>{f in u||(c[f]="")})});const d={...c,...u},h=yg(o);return{bundleId:t?.id||"bundle-current",title:t?.title||"Generated artifact bundle",fileEntries:o,dependencies:d,relationships:t?.relationships||[],warnings:i,errors:h}}function bg(t){return String(t||"").match(/\bclass\s+([A-Z][A-Za-z0-9_]*)\b/)?.[1]}function Eg(t){return String(t||"").split("/").pop().replace(/\.dart$/,"").split(/[^A-Za-z0-9]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join("")}function Sg(t,e){const r=[Eg(t),bg(e.content),e.artifactName].find(n=>/^[A-Z][A-Za-z0-9_]*$/.test(String(n||"")));if(!r)throw new Error(`Cannot derive a FlutterFlow custom class name for ${t}.`);return r}function xg(t,e=new Map){const s=[];for(const[r,n]of t.entries())n.type!=="C"||e.has(n.path)||s.push({artifactId:n.artifactId||r,className:Sg(r,n),content:n.content,fileName:r,path:n.path});return s}function kg(t,e){const s=new Set(e.map(r=>r.path));return new Map(Array.from(t.entries()).filter(([,r])=>!s.has(r.path)))}const rc={pass:0,warning:1,fail:2},Ig=["manualActions"];function De(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}function gt(...t){for(const e of t){if(typeof e=="string"&&e.trim())return e.trim();if(Array.isArray(e)&&e.length>0){const s=e.filter(r=>typeof r=="string").join(` -`);if(s)return s}}return""}function tt(t){return t==null?[]:Array.isArray(t)?t:[t]}function Cg(t){const e=De(t).value??t;if(e==null||typeof e=="string"&&e.trim()==="")return null;const s=Number(e);if(Number.isFinite(s))return s;const r=String(t||"").match(/\bscore\b[^\d]{0,12}(\d{1,3})(?:\s*\/\s*100)?/i);return r?Number(r[1]):null}function We(t){return String(t||"").trim().replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function na(t){const e=String(t||"").toLowerCase();return/(fail|error|critical|block|reject|invalid)/.test(e)?"fail":/(warn|attention|manual|partial|incomplete|concern)/.test(e)?"warning":/(pass|success|ready|approve|valid|clean|info|notice)/.test(e)?"pass":null}function vo(...t){return t.filter(Boolean).reduce((e,s)=>rc[s]>rc[e]?s:e,"pass")}function yd(t,e="warning",s="review"){if(typeof t=="string")return{severity:e,message:t,suggestion:"",source:s};const r=De(t),n=gt(r.message,r.title,r.issue,r.description,r.summary);return n?{severity:na(r.severity||r.status||r.level)||e,message:n,suggestion:gt(r.suggestion,r.fix,r.recommendation,r.action),source:r.source||s}:null}function _o(t,e="review"){const s=De(t);return[["findings","warning"],["issues","warning"],["criticalIssues","fail"],["errors","fail"],["warnings","warning"],["recommendations","warning"],["requiredFixes","fail"],["suggestions","warning"]].flatMap(([n,i])=>tt(s[n]).map(o=>yd(o,i,e)).filter(Boolean))}function Fg(t,e,s=null){if(typeof t=="string")return{id:`${s||"bundle"}-manual-${e+1}`,title:t,detail:"",location:"",timing:"unspecified",artifactId:s,source:"Code Review"};const r=De(t),n=gt(r.title,r.action,r.step,r.message,r.name,r.description);return n?{id:r.id||`${s||"bundle"}-manual-${e+1}`,title:n,detail:gt(r.detail,r.instructions,r.description),location:gt(r.location,r.flutterFlowPath,r.path),timing:gt(r.timing,r.phase)||"unspecified",artifactId:s,source:gt(r.source)||"Code Review"}:null}function yo(t,e=null){const s=De(t);return Ig.flatMap(r=>tt(s[r])).map((r,n)=>Fg(r,n,e)).filter(Boolean)}function Pg(t){let e=typeof t=="string"?go(t):t;if(!e&&typeof t=="string")return{rawText:t,root:{}};const s=De(e);typeof s.content=="string"&&(e=go(s.content)||e);const r=De(e),n=De(r.reviewResult||r.codeReview||r.result);return{rawText:"",root:Object.keys(n).length?n:r}}function Ag(t,e){const s=[e.id,e.fileName,e.artifactName].map(We);return t.find(r=>{const n=De(r);return[n.id,n.fileName,n.artifactName,n.name].map(We).some(i=>i&&s.includes(i))})||null}function $g(t,e){return tt(t?.metadata?.compatibility?.deployHints).find(n=>We(n?.artifactId)===We(e.id)||We(n?.fileName)===We(e.fileName))?.pathHint||""}function Rg(t,e){return tt(t?.relationships).filter(s=>We(s?.from)===We(e.id)||We(s?.to)===We(e.id))}function Tg(t,e){return tt(t?.metadata?.compatibility?.findings).filter(s=>!s?.artifactId||We(s.artifactId)===We(e.id)).map(s=>yd(s,"warning","Compatibility check")).filter(Boolean)}function Ng(t,e,s,r){const n=Ag(e,s),i=De(n?.review||n||s.review),o=Object.keys(i).length>0,a=[..._o(i),...Tg(t,s)],l=yo(i,s.id),u=na(i.status||i.verdict||i.outcome||i.result),c=a.length?vo(...a.map(h=>h.severity)):null,d=vo(u,c,o?null:"warning");return{...s,index:r,status:d,statusReason:o?gt(i.summary,i.overview,i.assessment,i.conclusion)||(a.length?`${a.length} review finding${a.length===1?"":"s"}`:"No file-level findings"):"No file-level verdict was returned",reviewComplete:o,findings:a,manualSteps:l,fixedSource:typeof i.fixedSource=="string"&&i.fixedSource.trim()?i.fixedSource.trim():null,pathHint:$g(t,s),relationships:Rg(t,s)}}function Mg({status:t,score:e,artifactPresentations:s,manualSteps:r}){const n=s.length;if(n===0&&r.length===0)return e==null?"Code review returned no overall summary and no score.":`Reviewed bundle with score ${e}/100.`;const i=s.reduce((a,l)=>(a[l.status]+=1,a),{pass:0,warning:0,fail:0}),o=[];return t&&o.push(`Overall verdict: ${t}.`),n&&o.push(`${n} artifact${n===1?"":"s"}: ${i.pass} pass, ${i.warning} warn, ${i.fail} fail.`),r.length&&o.push(`Do before deploy: ${r.map(a=>a.title).join("; ")}.`),e==null&&o.push("No numeric score (0-100) was returned."),o.join(" ")}function Lg({bundle:t,reviewResult:e}){const s=De(t),r=tt(s.artifacts),{root:n,rawText:i}=Pg(e),o=[n.bundleReview,n.overallReview,n.overall,n.bundleSummary,n.summaryReview,n.review].map(De).find(E=>Object.keys(E).length)||{},a=tt(n.artifacts||n.files||n.reviews),l=r.map((E,I)=>Ng(s,a,E,I)),u=_o(n),d=[..._o(o),...u],h=[...yo(o),...yo(n),...l.flatMap(E=>E.manualSteps)].filter((E,I,F)=>F.findIndex(P=>P.title===E.title&&P.artifactId===E.artifactId)===I),p=na(o.status||o.verdict||o.overallStatus||n.status||n.verdict||n.overallStatus||n.outcome),f=vo(p,...d.map(E=>E.severity),...l.map(E=>E.status)),g=o.score??n.score??n.overallScore??i,m=Cg(g),_=gt(o.headline,o.summary,o.executiveSummary,o.overview,o.assessment,o.conclusion,n.overallSummary,n.headline,n.summary,n.executiveSummary,n.overview,n.assessment,n.conclusion,i)||Mg({status:f,score:m,artifactPresentations:l,manualSteps:h}),w=l.reduce((E,I)=>(E[I.status]+=1,E),{pass:0,warning:0,fail:0});return{title:s.title||"Generated artifact bundle",description:s.description||"",status:f,score:m,summary:_,findings:d,manualSteps:h,artifacts:l,counts:w,reviewCoverage:{reviewed:l.filter(E=>E.reviewComplete).length,total:l.length},deployOrder:tt(s.deployOrder),relationships:tt(s.relationships),warnings:tt(s.warnings),compatibility:De(s.metadata?.compatibility)}}const Og=/^\uFEFF/;function Os(t){let e=0,s=t.length;for(;ee&&!t[s-1].trim();)s--;return t.slice(e,s).join(` -`)}function Dg(t){const e=String(t??"").replace(Og,"");if(!e.trim())return"";const s=e.split(` -`),r=c=>{const d=c.trim();return/^`{3,}[A-Za-z0-9+#_.-]*$/.test(d)?c.length-c.trimStart().length:-1};let n=0,i=-1;const o=[];{let c=0;for(let d=0;d=0&&(n++,i<0&&(i=d),o.push(c+h)),c+=s[d].length+1}}if(n===0)return Os(s);{const c=wo(e);if(!c.error&&o.every(h=>ic(h,c.commentAndStringRanges)))return Os(s)}if(n===1){const c=Os(s.slice(0,i)),d=Os(s.slice(i+1));return d.length>=c.length?d:c}const a=[];let l=null;for(let c=0;cc.length>0);return u.length===0?"":u.join(` - -`)}function Bg(t){return String(t??"").replace(/\/\*[\s\S]*?\*\//g," ").replace(/\/\/[^\n]*/g,"").replace(/'''[\s\S]*?'''/g,'""').replace(/"""[\s\S]*?"""/g,'""').replace(/'(?:\\.|[^'\\\n])*'/g,'""').replace(/"(?:\\.|[^"\\\n])*"/g,'""')}function wd(t){const e=Bg(t);return Array.from(e.matchAll(/class\s+([A-Z]\w*)\s+extends\s+[A-Za-z_]\w*Widget\b/g),s=>s[1])}function bd(t){return`${sa(t)}.dart`}function jg(t){return ea(t,"W")}const nc={"(":")","[":"]","{":"}"},Ug={")":"(","]":"[","}":"{"},Hg=/[A-Za-z0-9_]/;function wo(t){const e=[{kind:"code",opener:null,openedLine:0}],s=[];let r=1,n=0;const i=(c,d)=>{(c===` -`||c==="\r"&&d!==` -`)&&r++};let o=null;const a=()=>{for(const c of e)(c.kind==="string"||c.kind==="block-comment"||c.kind==="line-comment")&&s.push({start:c.startIndex,end:t.length})};for(;n0?t[n-1]:"",f=n>1?t[n-2]:"",g=(p==="r"||p==="R")&&!Hg.test(f);e.push({kind:"string",quote:c,triple:h,raw:g,startIndex:n,openedLine:r}),n+=h?3:1;continue}if(nc[c]){e.push({kind:"code",opener:c,openedLine:r}),n++;continue}if(Ug[c]){if(d.interpolation&&c==="}"){e.pop(),n++;continue}if(d.opener&&nc[d.opener]===c){e.pop(),n++;continue}return d.opener?(a(),{error:o??`line ${r}: "${c}" closes nothing - "${d.opener}" opened on line ${d.openedLine} is still open`,commentAndStringRanges:s}):(a(),{error:o??`line ${r}: unexpected "${c}" with no matching opener`,commentAndStringRanges:s})}i(c,t[n+1]),n++}a();let l=e.length-1;for(;l>0&&e[l].kind==="line-comment";)l--;let u=o;if(!u){const c=e[l];if(!(c.kind==="code"&&!c.opener&&!c.interpolation))if(c.kind==="string")u=`unclosed ${c.triple?"triple-quoted ":""}string starting on line ${c.openedLine} was never closed`;else if(c.kind==="block-comment")u=`unterminated /* comment starting on line ${c.openedLine}`;else if(c.interpolation){const d=e.findLast(p=>p.opener);u=`unclosed "\${" expression${d?` opened on line ${d.openedLine}`:""} was never closed`}else u=`"${c.opener}" opened on line ${c.openedLine} is never closed`}return{error:u,commentAndStringRanges:s}}function Wg(t){return wo(String(t??"")).error}function ic(t,e){return e.some(({start:s,end:r})=>t>=s&&ttypeof s=="string"?s:s?.errorMessage).filter(Boolean);return e.length>0?e.join("; "):JSON.stringify(t)}return t&&typeof t=="object"?t.errorMessage||JSON.stringify(t):String(t??"")}const zg=/^dependencies\s*:\s*(?:#.*)?$/,qg=/^(?:"([^"]+)"|'([^']+)'|([A-Za-z_][A-Za-z0-9_-]*))\s*:/;function Nn(t){const e=t.match(qg);return e?e[1]??e[2]??e[3]:null}function pr(t){const e=t.trim();return e===""||e.startsWith("#")}function xs(t){const e=t.match(/^(\s*)/);return e?e[1].length:0}function ia(t,e){const s=t.findIndex(i=>e.test(i));if(s===-1)return null;let r=s,n=null;for(let i=s+1;i=0.0.0"}`}function Kg(t,e={}){const s=String(t||""),r=Object.entries(e).filter(([u])=>u&&u!=="flutter");if(r.length===0)return{yaml:s,added:[],alreadyPresent:[]};const n=s.split(` -`),i=new Set(xd(s)),o=[],a=[];for(const[u,c]of r)i.has(u)?a.push(u):(o.push([u,c]),i.add(u));if(o.length===0)return{yaml:s,added:[],alreadyPresent:a};const l=oa(n);if(l){const u=o.map(([c,d])=>oc(l.childIndent,c,d));n.splice(l.endIndex,0,...u)}else n.length>0&&n[n.length-1].trim()!==""&&n.push(""),n.push("dependencies:"),o.forEach(([u,c])=>{n.push(oc(" ",u,c))});return{yaml:n.join(` -`),added:o.map(([u])=>u),alreadyPresent:a}}function Jg(t,e={}){const s=String(t||""),r=Object.entries(e).filter(([l])=>l&&l!=="flutter");if(r.length===0)return{yaml:s,overridden:[],skipped:[]};const n=s.split(` -`),i=Ln(s),o=[],a=[];for(const[l,u]of r){const c=i.get(l);if(!c||!c.isScalar||!String(u||"").trim()){a.push(l);continue}const d=" ".repeat(xs(n[c.lineIndex]));n[c.lineIndex]=`${d}${l}: ${Id(String(u).trim())}${c.comment}`,o.push({name:l,from:c.constraint,to:u})}return{yaml:n.join(` -`),overridden:o,skipped:a}}function Cd(t){const e=String(t||""),s=[];return e.trim()?(/^name:\s*\S+/m.test(e)||s.push("pubspec.yaml missing name field"),oa(e.split(` -`))||s.push("pubspec.yaml missing dependencies section"),xd(e).includes("flutter")||s.push("pubspec.yaml missing Flutter SDK dependency"),{valid:s.length===0,errors:s}):(s.push("pubspec.yaml is empty"),{valid:!1,errors:s})}const Yg=">=3.0.0 <4.0.0";function bo(t){const e=String(t||"").trim(),s=e[0];return s!=="'"&&s!=='"'||e[e.length-1]!==s?e:e.slice(1,-1).replaceAll(`${s}${s}`,s)}function Zg(t=""){const e=_d(t).filter(s=>!s.startsWith("dart:")&&!s.startsWith("package:"));return{selfContained:e.length===0,unresolvableImports:e}}function ac(t,e,s){const r=[];for(const[n,i]of t){if(i.isScalar){e[n]=bo(i.constraint);continue}if(i.sourceKey==="sdk"){s.add(n);continue}if(i.sourceKey==="version"){e[n]=bo(i.sourceValue);continue}r.push(n)}return r}function Xg(t){const e=new Set,s={},r={},n=ac(Ln(t),s,e);n.push(...ac(Vg(t,"dependency_overrides"),r,e));const i=new Set([...Object.keys(s),...e]),{sdk:o}=kd(t);return{sdkConstraint:bo(o)||Yg,dependencies:s,overrides:r,sdkPackages:[...e].sort(),availablePackages:i,unrepresentable:n}}function Qg(t,e,s){return e.length>0?`${t} imports ${e.join(", ")}, which FlutterFlow only generates once the app is built, so it could not be compiled before the deploy.`:`${t} imports ${s.join(", ")}, which your project's pubspec.yaml does not declare with a version constraint, so it could not be compiled before the deploy.`}function em(t,e){const{sdkConstraint:s,dependencies:r,overrides:n,sdkPackages:i,availablePackages:o,unrepresentable:a}=Xg(e),l={sdkConstraint:s,dependencies:r,overrides:n,sdkPackages:i},u=[],c=[];for(const d of t){const{className:h,content:p}=d,f=ra(p),g=_d(p).some(w=>w.startsWith("package:"));if(a.length>0&&g){const w=f.filter(E=>a.includes(E));c.push({className:h,reason:w.length>0?`${h} was not compiled before deploying: it imports or exports ${w.join(", ")}, which your project declares from a source that cannot be reproduced outside it, so package resolution could not be matched exactly.`:`${h} was not compiled before deploying: your project declares ${a.join(", ")} from a source that cannot be reproduced outside it, and such a source can alter package resolution anywhere in the dependency graph, so resolution could not be matched exactly.`});continue}const{unresolvableImports:m}=Zg(p),_=f.filter(w=>!o.has(w));if(m.length>0||_.length>0){c.push({className:h,reason:Qg(h,m,_)});continue}u.push({fileName:`${sa(h)}.dart`,content:p})}return{manifest:l,sources:u,skipped:c}}function lc(t,e){const s=`${t}${e}`.split(` -`),r=s.pop()??"",n=[];for(const i of s){const o=Fd(i);o&&n.push(o)}return{events:n,buffer:r}}function tm(t){const e=Fd(t);return e?[e]:[]}function Fd(t){const e=t.trim();if(!e)return null;try{const s=JSON.parse(e);return s&&typeof s=="object"&&!Array.isArray(s)?s:null}catch{return null}}async function sm(t,e={}){const{onPhase:s,onLog:r}=e;let n=null,i="";const o=a=>{if(a.event==="phase"){a.message&&s&&s(a.message);return}if(a.event==="log"){a.message&&r&&r(a.message);return}n=a};if(t.body?.getReader){const a=t.body.getReader(),l=new TextDecoder;for(;;){const{done:u,value:c}=await a.read();if(u)break;const d=lc(i,l.decode(c,{stream:!0}));i=d.buffer,d.events.forEach(o)}}else{const a=lc("",await t.text());i=a.buffer,a.events.forEach(o)}return tm(i).forEach(o),n?{...n,success:n.success===!0||n.success===void 0&&t.ok}:{success:!1,error:t.ok?"The FlutterFlow deploy runner closed the connection before it finished.":`FlutterFlow custom class provisioning failed (HTTP ${t.status}).`}}const rm=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;function wt(t){const e=String(t||"").trim().match(rm);return e?{major:Number(e[1]),minor:Number(e[2]),patch:Number(e[3]),prerelease:e[4]?e[4].split("."):[]}:null}function nm(t,e){if(t.length===0&&e.length===0)return 0;if(t.length===0)return 1;if(e.length===0)return-1;for(let s=0;s0)}function om(t){const e=wt(t);return e?e.major>0?`${e.major+1}.0.0`:`0.${e.minor+1}.0`:null}function aa(t){let e=String(t??"").trim();if((e.startsWith("'")||e.startsWith('"'))&&(e=e.slice(1,-1).trim()),e===""||e==="any"||e==="*")return{min:null,minInclusive:!1,max:null,maxInclusive:!1};if(e.startsWith("^")){const o=e.slice(1).trim();return wt(o)?{min:o,minInclusive:!0,max:om(o),maxInclusive:!1}:null}if(wt(e))return{min:e,minInclusive:!0,max:e,maxInclusive:!0};const s={min:null,minInclusive:!1,max:null,maxInclusive:!1},r=/(>=|<=|>|<)\s*([0-9][0-9A-Za-z.+-]*)/g;let n=!1,i;for(;(i=r.exec(e))!==null;){const[,o,a]=i;if(!wt(a))return null;n=!0,o===">="||o===">"?(s.min=a,s.minInclusive=o===">="):(s.max=a,s.maxInclusive=o==="<=")}return n?s:null}function cc(t,e){const s=aa(t);if(!s||!wt(e))return!1;if(s.min!==null){const r=vn(e,s.min);if(r<0||r===0&&!s.minInclusive)return!1}if(s.max!==null){const r=vn(e,s.max);if(r>0||r===0&&!s.maxInclusive)return!1}return!0}function am(t,e){const s=aa(t);if(!s||!wt(e))return!1;if(s.max===null)return!0;const r=vn(s.max,e);return r>0?!0:r===0&&s.maxInclusive}function ns(t){const e=aa(t);return e?e.min:null}const lm="https://pub.dev/api/packages/",cm=8e3;function um(t,e={}){const{dartSdkFloor:s=null,flutterSdkFloor:r=null}=e,n=Array.isArray(t?.versions)?t.versions:[];let i=null;for(const o of n){const a=o?.version;if(!a||o.retracted||im(a))continue;const l=o.pubspec?.environment||{};s&&l.sdk&&!cc(l.sdk,s)||r&&l.flutter&&!cc(l.flutter,r)||(!i||vn(a,i)>0)&&(i=a)}return i?{version:i,constraint:`^${i}`}:null}async function dm(t,e={}){const{dartSdkFloor:s=null,flutterSdkFloor:r=null,fetchImpl:n=fetch}=e;let i;try{const a=await n(`${lm}${encodeURIComponent(t)}`,{signal:AbortSignal.timeout(cm)});if(!a.ok)return{name:t,constraint:null,version:null,error:a.status===404?`"${t}" was not found on pub.dev`:`pub.dev returned ${a.status} for "${t}"`};i=await a.json()}catch(a){return{name:t,constraint:null,version:null,error:`could not reach pub.dev for "${t}" (${a.message})`}}const o=um(i,{dartSdkFloor:s,flutterSdkFloor:r});return o?{name:t,...o,error:null}:{name:t,constraint:null,version:null,error:s?`no published "${t}" release supports Dart ${s}`:`no published "${t}" release could be read`}}async function hm(t,e={}){const s=await Promise.all(t.map(r=>dm(r,e)));return new Map(s.map(({name:r,...n})=>[r,n]))}async function pm(t,e={},s={}){const{resolveVersions:r=hm}=s,n=Object.entries(e).filter(([c])=>c&&c!=="flutter"),i=kd(t),o={dartSdkFloor:ns(i.sdk),flutterSdkFloor:ns(i.flutter)},a={additions:{},overrides:{},kept:[],warnings:[],sdk:o};if(n.length===0)return a;const l=Ln(t),u=[];for(const[c,d]of n){const h=l.get(c);if(!h){u.push(c);continue}const p=ns(d);if(!p){a.kept.push({name:c,constraint:h.constraint});continue}if(!h.isScalar){a.warnings.push(`"${c}" is declared in your project from a git, path, or SDK source, but the generated code needs at least ${p}. Left as-is — update it yourself if the build fails.`),a.kept.push({name:c,constraint:h.constraint});continue}if(am(h.constraint,p)){a.kept.push({name:c,constraint:h.constraint});continue}a.overrides[c]=`^${p}`,a.warnings.push(`"${c}" was pinned to ${h.constraint} in your project, which cannot resolve the ${p} the generated code needs. Raising it to ^${p} — this changes a dependency the rest of your app also uses.`)}if(u.length>0){const c=await r(u,o);for(const d of u){const h=c.get(d);if(h?.constraint){a.additions[d]=h.constraint;continue}const p=e[d]||"";if(ns(p)){a.additions[d]=`^${ns(p)}`,a.warnings.push(`Could not confirm "${d}" version on pub.dev (${h?.error||"lookup failed"}). Using ^${ns(p)} from the AI's recommendation — verify this is current.`);continue}a.additions[d]=">=0.0.0",a.warnings.push(`Could not determine a version for "${d}" (${h?.error||"lookup failed"}) and the AI supplied none. Added with a wide-open >=0.0.0 constraint — pin a concrete version in FlutterFlow before deploying.`)}}return a}const fm={"&":"&","<":"<",">":">",'"':""","'":"'"};function bt(t){return String(t??"").replace(/[&<>"']/g,e=>fm[e])}function j(t){return t?bt(t).replace(/\n/g,"
"):""}function It(t){return bt(t).replace(/\r?\n/g," ")}function gm(t,e={}){const s=t?.pipelineStep;if(s!=null&&e[s]!=null)return e[s];const r=t?.message||"";return r.includes("Code Generator")?2:r.includes("Code Review")?3:1}function mm(t){const e={"Integration Audit Report":"📋","Critical Issues":"❌",Warnings:"⚠️",Recommendations:"✅","Overall Score":"📊"};for(const[s,r]of Object.entries(e))if(t.toLowerCase().includes(s.toLowerCase()))return r;return"📄"}function vm(t){const e={critical:"❌",warning:"⚠️",recommendation:"✅",score:"📊",issue:"🔍",fix:"🔧"};for(const[s,r]of Object.entries(e))if(t.toLowerCase().includes(s.toLowerCase()))return r;return"📝"}function _m(t){return t.includes("class ")&&t.includes("extends ")||t.includes("StatelessWidget")||t.includes("StatefulWidget")||t.includes("import 'package:flutter/")?"dart":t.includes("def ")||t.includes("import ")||t.includes("print(")?"python":t.includes("function ")||t.includes("const ")||t.includes("console.")?"javascript":"dart"}function ws(t){if(!t)return"";if(typeof t!="string")return String(t);const e=/```(?:\w+)?\n?([\s\S]*?)```/,s=t.match(e);return s?s[1].trim():t.trim()}function uc(t){return t=bt(t),t=t.replace(/\*\*(.*?)\*\*/g,'$1'),t=t.replace(/\*(.*?)\*/g,'$1'),t=t.replace(/`(.*?)`/g,'$1'),t=t.replace(/\b(FAIL|ERROR|CRITICAL)\b/g,'$1'),t=t.replace(/\b(WARN|WARNING)\b/g,'$1'),t=t.replace(/\b(PASS|SUCCESS|OK)\b/g,'$1'),t}function Pd(t,e="dart",s=globalThis.hljs){if(!t)return"";const r=ws(t);try{return s.highlight(r,{language:e}).value}catch(n){console.warn("Syntax highlighting failed:",n);try{return s.highlight(r,{language:"json"}).value}catch{return bt(r)}}}function On(t,e={}){const{highlighter:s=globalThis.hljs}=e;let r='
';const n=String(t??"").split(` -`);let i=!1,o="";for(const a of n){if(a.startsWith("```")){if(i){const l=_m(o),u=Pd(o.trim(),l,s);r+=`
-
${u}
-
`,o="",i=!1}else i=!0;continue}if(i){o+=a+` -`;continue}if(a.startsWith("# ")){const l=a.substring(2).trim();r+=`
-

- ${mm(l)} - ${bt(l)} -

-
`;continue}if(a.startsWith("## ")){const l=a.substring(3).trim();r+=`
-

- ${vm(l)} - ${bt(l)} -

-
`;continue}if(/^[-*+]\s+/.test(a)||/^\d+\.\s+/.test(a)){const l=a.replace(/^([-*+]|\d+\.)\s+/,"").trim();r+=`
- • - ${uc(l)} -
`;continue}a.trim()!==""&&(r+=`

${uc(a)}

`)}return r+="
",` -
-
-
- Live Audit Report -
- ${r} -
- `}const ym="https://ccc-ffai-runner-y5cyj3473a-uw.a.run.app/deployCustomClasses";const Je="https://4tgke4.buildship.run",Ad={professional:"price_1T2ldCKszA2slvDXatdeCpbI",power:"price_1T2le9KszA2slvDXR4mPvw7M"},_n="ccc_auth_session",dc=new WeakSet;let G={email:null,sessionToken:null,isVerified:!1};function bs(t={}){return{tier:"free",status:"none",periodEnd:null,isLoading:!1,isResolved:!1,error:null,...t}}let fe=bs({isResolved:!0});const wm=`${Je}/service/runpipeline`,bm="bs_user_id",Em="bs_identity_token",Sm=`${Je}/authUserCheck`;let Ge={userId:null,token:null,status:null,resolved:!1};const yn={free:2,professional:50,power:2e3},wn="ccc_subscription",hc=3,xm=new Set(["active","trialing","paid"]),lr="google/gemini-3.7-flash",jr=["anthropic/claude-opus-5","openai/gpt-5.6-sol","z-ai/glm-5.2","moonshotai/kimi-k3","openrouter/auto-beta","openrouter/free","openrouter/deepseek/deepseek-v4-pro"],km={"google/gemini-3.7-flash":"Gemini 3.7 Flash","anthropic/claude-opus-5":"Claude Opus 5","openai/gpt-5.6-sol":"GPT-5.6 Sol","z-ai/glm-5.2":"GLM 5.2","moonshotai/kimi-k3":"Kimi K3","openrouter/auto-beta":"OpenRouter: Auto Router","openrouter/free":"OpenRouter: Free Models","openrouter/deepseek/deepseek-v4-pro":"DeepSeek v4 Pro"};function zt(t){return km[t]||t}const Im=new Set(["google/gemini-3.7-flash","anthropic/claude-opus-5","openai/gpt-5.6-sol","z-ai/glm-5.2","moonshotai/kimi-k3","openrouter/auto-beta"]);function $d(t){return Im.has(t)}const Eo=4,Ci=8*1024*1024,Cm="https://4tgke4.buildship.run/service/runpipeline-image";let Pt=[];function Fm(t){return new Promise(e=>{const s=new FileReader;s.onload=()=>e(s.result),s.onerror=()=>e(null),s.readAsDataURL(t)})}async function Pm(t){const e=new FormData;return e.append("file",t),(await fetch(Cm,{method:"POST",body:e})).json()}function Am(t){if(Array.isArray(t)){const e=t[0];if(e&&typeof e=="object")for(const s of Object.keys(e)){if(s==="item"||s==="index")continue;const r=e[s];if(r&&typeof r=="object"){if(typeof r.file=="string")return r.file;if(typeof r.url=="string")return r.url}if(typeof r=="string")return r}return""}return typeof t=="string"?t:t&&typeof t=="object"&&(t.url||t.fileUrl||t.file_url||t.downloadUrl||t.imageUrl||t.image_url||t.file)||""}async function $m(t){const e=Array.from(t.target.files||[]);if(!e.length)return;const s=e.filter(l=>l.size>Ci);s.length&&ue(`Skipped ${s.length} image(s) over the ${(Ci/1024/1024).toFixed(0)} MB limit.`,"warning");const r=e.filter(l=>l.size<=Ci);if(!r.length){t.target.value="";return}const n=Eo-Pt.length,o=r.slice(0,n).map(async l=>{const u=await Fm(l);if(!u)return null;let c="";try{c=Am(await Pm(l))}catch{c=""}return{dataUrl:u,name:l.name,url:c}}),a=(await Promise.all(o)).filter(Boolean);t.target.value="",!(a.length&&!$d(document.getElementById("code-generator-model")?.value))&&(Pt.push(...a),r.length>n&&ue(`You can attach up to ${Eo} images.`,"info"),la())}function Rm(t){Pt.splice(t,1),la()}function la(){const t=document.getElementById("prompt-image-thumbnails"),e=document.getElementById("prompt-image-btn-label");t&&(t.innerHTML="",Pt.forEach((s,r)=>{const n=document.createElement("div");n.className="prompt-img-thumb",n.innerHTML=`Prompt image`,t.appendChild(n)}),e&&(e.textContent=Pt.length>=Eo?"Image limit reached":"Add images"))}function Rd(){const t=document.getElementById("prompt-image-upload");if(!t)return;const e=document.getElementById("code-generator-model"),s=$d(e?.value);t.classList.toggle("hidden",!s),!s&&Pt.length&&(Pt=[],la())}const Gt="ccc_usage",Td="google/gemini-3.7-flash",Nd="google/gemini-3.7-flash",Fi="google/gemini-3.7-flash",pc={professional:11,power:49},So={en_US:"USD",en_GB:"GBP",en_AU:"AUD",en_NZ:"NZD",en_CA:"CAD",en_IN:"INR",en_SG:"SGD",en_HK:"HKD",en_PH:"PHP",en_ZA:"ZAR",en:"USD",de:"EUR",fr:"EUR",es:"EUR",it:"EUR",nl:"EUR",pt_PT:"EUR",pt_BR:"BRL",pt:"BRL",ja:"JPY",ko:"KRW",zh_CN:"CNY",zh_TW:"TWD",zh:"CNY",th:"THB",vi:"VND",id:"IDR",ms_MY:"MYR",ms:"MYR",sv:"SEK",nb:"NOK",da:"DKK",pl:"PLN",cs:"CZK",hu:"HUF",ro:"RON",tr:"TRY",ar:"AED",he:"ILS",ru:"RUB",uk:"UAH"},Ur={AUD:1,USD:.65,EUR:.6,GBP:.52,CAD:.88,NZD:1.08,JPY:97,KRW:870,INR:54,SGD:.87,HKD:5.08,BRL:3.18,CNY:4.7,TWD:20.5,THB:22.5,VND:16200,IDR:10200,MYR:2.88,SEK:6.8,NOK:6.95,DKK:4.48,PLN:2.6,CZK:15.2,HUF:238,RON:2.98,TRY:20.9,AED:2.39,ILS:2.38,PHP:36.4,ZAR:11.8,RUB:58,UAH:26.8,CHF:.57,MXN:11.1,ARS:580,CLP:610,COP:2700,PEN:2.44};let Hr={...Ur};async function Tm(){const t=new AbortController,e=setTimeout(()=>t.abort(),5e3);try{const s=await fetch("https://open.er-api.com/v6/latest/AUD",{signal:t.signal});if(!s.ok)return;const r=await s.json();if(r.result!=="success"||!r.rates)return;const n=r.rates,i={AUD:1},o=new Set([...Object.keys(Ur),...Object.values(xo),...Object.values(So)]);for(const a of o)a!=="AUD"&&(typeof n[a]=="number"&&n[a]>0?i[a]=n[a]:Ur[a]&&(i[a]=Ur[a]));Hr=i}catch{}finally{clearTimeout(e)}}const xo={"America/Sao_Paulo":"BRL","America/Fortaleza":"BRL","America/Recife":"BRL","America/Bahia":"BRL","America/Belem":"BRL","America/Manaus":"BRL","America/Cuiaba":"BRL","America/Campo_Grande":"BRL","America/Araguaina":"BRL","America/Noronha":"BRL","America/Rio_Branco":"BRL","America/Porto_Velho":"BRL","America/Boa_Vista":"BRL","America/Maceio":"BRL","America/Santarem":"BRL","America/Eirunepe":"BRL","Europe/London":"GBP","Europe/Paris":"EUR","Europe/Berlin":"EUR","Europe/Madrid":"EUR","Europe/Rome":"EUR","Europe/Amsterdam":"EUR","Europe/Brussels":"EUR","Europe/Vienna":"EUR","Europe/Lisbon":"EUR","Europe/Dublin":"EUR","Europe/Helsinki":"EUR","Europe/Athens":"EUR","Europe/Bucharest":"RON","Europe/Budapest":"HUF","Europe/Warsaw":"PLN","Europe/Prague":"CZK","Europe/Copenhagen":"DKK","Europe/Stockholm":"SEK","Europe/Oslo":"NOK","Europe/Zurich":"CHF","Europe/Istanbul":"TRY","Europe/Moscow":"RUB","Europe/Kiev":"UAH","Europe/Kyiv":"UAH","Asia/Tokyo":"JPY","Asia/Seoul":"KRW","Asia/Shanghai":"CNY","Asia/Taipei":"TWD","Asia/Hong_Kong":"HKD","Asia/Singapore":"SGD","Asia/Kolkata":"INR","Asia/Calcutta":"INR","Asia/Bangkok":"THB","Asia/Ho_Chi_Minh":"VND","Asia/Jakarta":"IDR","Asia/Kuala_Lumpur":"MYR","Asia/Dubai":"AED","Asia/Jerusalem":"ILS","Asia/Tel_Aviv":"ILS","Asia/Manila":"PHP","Pacific/Auckland":"NZD","Australia/Sydney":"AUD","Australia/Melbourne":"AUD","Australia/Brisbane":"AUD","Australia/Perth":"AUD","Australia/Adelaide":"AUD","Australia/Hobart":"AUD","Australia/Darwin":"AUD","Australia/Lord_Howe":"AUD","America/Toronto":"CAD","America/Vancouver":"CAD","America/Edmonton":"CAD","America/Winnipeg":"CAD","America/Halifax":"CAD","America/St_Johns":"CAD","America/Regina":"CAD","America/New_York":"USD","America/Chicago":"USD","America/Denver":"USD","America/Los_Angeles":"USD","America/Phoenix":"USD","America/Anchorage":"USD","Pacific/Honolulu":"USD","America/Mexico_City":"MXN","America/Cancun":"MXN","America/Tijuana":"MXN","America/Argentina/Buenos_Aires":"ARS","America/Santiago":"CLP","America/Bogota":"COP","America/Lima":"PEN","Africa/Johannesburg":"ZAR"};function Md(){try{const i=Intl.DateTimeFormat().resolvedOptions().timeZone;if(i&&xo[i])return xo[i]}catch{}const e=(navigator.language||"en-US").replace("-","_"),s=So[e];if(s)return s;const r=e.split("_")[0],n=So[r];return n||"USD"}function fc(t,e){const s=Hr[e]??Hr.USD,r=t*s,n=Math.round(r*100)/100;try{return new Intl.NumberFormat("en-US",{style:"currency",currency:e,minimumFractionDigits:0,maximumFractionDigits:n>=100||n%1===0?0:2}).format(n)}catch{return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:0,maximumFractionDigits:2}).format(t*Hr.USD)}}const st="ccc_api_key_",_t="ccc_session_api_key_",it="ccc_encryption_key",cr="ccc_encryption_key_scope",Nm="ccc_keystore",bn="keys",ur="ccc_encryption_key_version";let ko=null,En=null,dr=!1,Sn=!1,gc=!1;class xn extends Error{constructor(){super("Secure browser key storage is unavailable."),this.name="CredentialStorageUnavailableError"}}function mc(){if(gc)return;gc=!0;const t="Secure browser key storage is unavailable. Existing credentials were left untouched; new credentials will be available only in this tab session.";console.warn(t),document.body&&ue(t,"warning")}function Ld(){return localStorage.getItem(ur)||""}function Io(){return crypto.randomUUID?.()||Dd(crypto.getRandomValues(new Uint8Array(16)))}function Mm(){const t=Ld();if(t)return t;const e=Io();return localStorage.setItem(ur,e),e}function Es(){ko=null,En=null,dr=!1,Sn=!1}window.addEventListener("storage",t=>{t.key===ur&&Es()});function Lm(){return new Promise((t,e)=>{const s=indexedDB.open(Nm,1);s.onupgradeneeded=()=>{const r=s.result;r.objectStoreNames.contains(bn)||r.createObjectStore(bn)},s.onsuccess=()=>t(s.result),s.onerror=()=>e(s.error)})}async function ca(t,e){const s=await Lm();return new Promise((r,n)=>{const i=s.transaction(bn,t);let o;try{o=e(i.objectStore(bn))}catch(l){s.close(),n(l);return}let a;o.onsuccess=()=>{a=o.result},o.onerror=()=>n(o.error),i.oncomplete=()=>{s.close(),r(a)},i.onerror=()=>{s.close(),n(i.error||new Error("Encryption key transaction failed."))},i.onabort=()=>{s.close(),n(i.error||new Error("Encryption key transaction aborted."))}})}function Om(t){return t instanceof CryptoKey&&t.algorithm?.name==="AES-GCM"&&t.extractable===!1&&t.usages.includes("encrypt")&&t.usages.includes("decrypt")}async function Dm(){const t=await ca("readonly",e=>e.get(it));return Om(t)?t:null}async function Od(t){await ca("readwrite",e=>e.put(t,it))}async function Bm(){Es();try{await ca("readwrite",t=>t.delete(it))}catch(t){console.warn("Could not delete the stored encryption key:",t)}}async function jm(){const t=sessionStorage.getItem(it);if(!t)return null;const e=await crypto.subtle.importKey("jwk",JSON.parse(t),{name:"AES-GCM",length:256},!1,["encrypt","decrypt"]);return await Od(e),sessionStorage.removeItem(it),sessionStorage.removeItem(cr),localStorage.removeItem(st+"salt"),e}async function vc(t){const e=sessionStorage.getItem(it);if(e)return Sn=sessionStorage.getItem(cr)!=="session",crypto.subtle.importKey("jwk",JSON.parse(e),{name:"AES-GCM",length:256},!1,["encrypt","decrypt"]);if(!t)throw new xn;const s=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),r=await crypto.subtle.exportKey("jwk",s);return sessionStorage.setItem(it,JSON.stringify(r)),sessionStorage.setItem(cr,"session"),Sn=!1,crypto.subtle.importKey("jwk",r,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async function Um(t){if(sessionStorage.getItem(cr)==="session"&&sessionStorage.getItem(it))return mc(),dr=!0,vc(t);try{const e=await Dm();if(e)return e;const s=await jm();if(s)return s;const r=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!1,["encrypt","decrypt"]);return await Od(r),r}catch(e){return console.warn("IndexedDB encryption-key storage failed:",e),mc(),dr=!0,vc(t)}}async function ua(t={}){const{allowSessionFallbackCreation:e=!0}=t,s=Mm();En!==s&&Es();const r=ko||Um(e);ko=r,En=s;try{return await r}catch(n){throw Es(),n}}async function Hm(t){const e=await ua(),s=En,r=new TextEncoder,n=crypto.getRandomValues(new Uint8Array(12)),i=await crypto.subtle.encrypt({name:"AES-GCM",iv:n},e,r.encode(t)),o=new Uint8Array(n.length+i.byteLength);return o.set(n),o.set(new Uint8Array(i),n.length),{ciphertext:Dd(o),keyVersion:s,sessionFallback:dr}}async function Wm(t,e={}){const{isSessionCredential:s=!1}=e;try{const r=await ua({allowSessionFallbackCreation:!1});if(dr&&!s&&!Sn)throw new xn;const n=zm(t),i=n.slice(0,12),o=n.slice(12),a=await crypto.subtle.decrypt({name:"AES-GCM",iv:i},r,o);return new TextDecoder().decode(a)}catch(r){if(r instanceof xn)throw r;return console.error("Decryption failed:",r),null}}function Dd(t){const e=new Uint8Array(t);let s="";for(let r=0;r0}let hr="",kn="",Zs=null,yc=0;async function da(){sessionStorage.getItem(it)&&await ua(),hr=await Ee("flutterflow"),kn=await Ee("flutterflow_project_id"),Jm(),Zt()}function ha(){document.getElementById("api-keys-modal").classList.add("open"),fa(),hr&&Hd(hr)}function Bd(t){if(t&&t.target!==t.currentTarget)return;const e=document.getElementById("api-keys-modal");e&&e.classList.remove("open");const s=document.getElementById("walkthrough-modal");s&&(pa(),s.classList.add("open"))}let Et=1;function jd(){const t=document.querySelector(".wt-steps");return t?Array.from(t.querySelectorAll(".wt-step-card")):[]}function Dn(){const t=jd();t.length&&t.forEach((e,s)=>{const r=s+1;if(r===Et){e.classList.remove("opacity-60","bg-gray-50","border-gray-200"),e.classList.add("bg-blue-50","border-blue-200");const n=e.querySelector("div:first-child");n&&(n.classList.remove("bg-gray-400"),n.classList.add("bg-blue-500"),n.innerHTML=r)}else if(r0&&Et<=t&&(Et++,Dn())}function Vm(){const t=document.getElementById("walkthrough-modal");t&&(Et=1,Dn(),t.classList.add("open"))}function Gm(t){if(t&&t.target!==t.currentTarget)return;const e=document.getElementById("walkthrough-modal");e&&e.classList.remove("open");const s=document.getElementById("walkthrough-dont-show");s&&s.checked&&localStorage.setItem("hasSeenWalkthrough","true")}function Ud(){if(G.isVerified&&Jt()&&fe.tier!=="free")return;if(!localStorage.getItem("hasSeenWalkthrough")){const e=document.getElementById("walkthrough-modal");e&&(Et=1,Dn(),e.classList.add("open"))}}async function fa(){const t=document.getElementById("flutterflow-api-key-input");hr?(t.value="",t.placeholder="Key saved (enter new to replace)"):t.placeholder="Enter your FlutterFlow API key",Km()}function Km(){wc("flutterflow","flutterflow-key-status"),wc("flutterflow_project_id","flutterflow-project-status")}function wc(t,e){const s=document.getElementById(e);if(!s)return;const r=s.querySelector(".key-status-dot"),n=s.querySelector("span");as(t)?(r.className="key-status-dot configured",n.className="text-green-600",n.textContent="User key configured"):(r.className="key-status-dot missing",n.className="text-gray-500",n.textContent="Not configured")}function Zt(){const t=y.step2Result&&y.step2Result.length>0,e=document.getElementById("btn-deploy-to-ff"),s=document.getElementById("btn-run-pipeline");s&&s.classList.remove("hidden"),e&&e.classList.toggle("hidden",!t)}function Jm(){const t=document.getElementById("api-keys-status");if(!t)return;const e=t.querySelectorAll(".key-status-dot"),s=["flutterflow"];e.forEach((r,n)=>{const i=s[n];i==="flutterflow"?as("flutterflow")&&as("flutterflow_project_id")?(r.className="key-status-dot configured",r.title="FlutterFlow (Fully configured)"):as("flutterflow")||as("flutterflow_project_id")?(r.className="key-status-dot env",r.title="FlutterFlow (Partially configured)"):(r.className="key-status-dot missing",r.title="FlutterFlow (Not configured)"):as(i)?(r.className="key-status-dot configured",r.title=i.charAt(0).toUpperCase()+i.slice(1)+" (User key)"):(r.className="key-status-dot missing",r.title=i.charAt(0).toUpperCase()+i.slice(1)+" (Not configured)")}),Zt()}async function Ym(){const t=document.getElementById("flutterflow-api-key-input"),e=document.getElementById("flutterflow-projects-select");t.value.trim()&&await _c("flutterflow",t.value);const s=e?.value.trim()||"";if(s){if(!Bn(s)){ue("The selected FlutterFlow project has an unexpected ID format.","error"),e.focus();return}await _c("flutterflow_project_id",s)}await da(),fa();const r=document.querySelector("#api-keys-modal .bg-blue-500"),n=r.textContent;r.textContent="Saved!",r.classList.remove("bg-blue-500","hover:bg-blue-600"),r.classList.add("bg-green-500"),setTimeout(()=>{r.textContent=n,r.classList.remove("bg-green-500"),r.classList.add("bg-blue-500","hover:bg-blue-600"),Bd()},1e3)}async function Zm(){if(!confirm("Are you sure you want to clear all stored API keys?"))return;localStorage.setItem(ur,Io()),Es(),localStorage.removeItem(st+"flutterflow"),localStorage.removeItem(st+"flutterflow_project_id"),sessionStorage.removeItem(_t+"flutterflow"),sessionStorage.removeItem(_t+"flutterflow_project_id"),sessionStorage.removeItem(it),sessionStorage.removeItem(cr),localStorage.removeItem(st+"salt"),await Bm(),localStorage.setItem(ur,Io()),localStorage.removeItem(st+"flutterflow"),localStorage.removeItem(st+"flutterflow_project_id"),sessionStorage.removeItem(_t+"flutterflow"),sessionStorage.removeItem(_t+"flutterflow_project_id"),await da();const t=document.getElementById("flutterflow-projects-select");t&&(t.innerHTML=''),fa()}function Bn(t){return!t||t.trim().length<5||t.includes(" ")?!1:/^[a-zA-Z0-9-]+$/.test(t)}function Xm(t,e){const s=document.getElementById(t);s&&(s.value?e?s.style.borderColor="#22c55e":s.style.borderColor="#ef4444":s.style.borderColor="")}function Qm(){const t=document.getElementById("flutterflow-api-key-input");t&&(t.addEventListener("input",e=>{const s=e.target.value.trim().length>0;Xm("flutterflow-api-key-input",s)}),t.addEventListener("blur",ev(async e=>{const s=e.target.value.trim();s&&await Hd(s)},500)))}function ev(t,e){let s;return function(...n){const i=()=>{clearTimeout(s),t(...n)};clearTimeout(s),s=setTimeout(i,e)}}async function Hd(t){const e=document.getElementById("flutterflow-projects-select"),s=document.getElementById("flutterflow-projects-error");if(!e){console.error("Projects dropdown element not found");return}e.innerHTML='',s&&s.classList.add("hidden");try{const n=await new gr(t,"").listProjects();if(!n||n.length===0){e.innerHTML='';return}e.innerHTML='',n.forEach(i=>{const o=document.createElement("option");o.value=i.id||i.projectId||"",o.textContent=i.name||i.projectName||`Project ${i.id}`,e.appendChild(o)}),kn&&(e.value=kn)}catch(r){console.error("Failed to fetch projects:",r),e.innerHTML='',s&&(s.textContent=`Failed to load projects: ${r.message}`,s.classList.remove("hidden"))}}function tv(t){const e=document.getElementById(t),r=e.nextElementSibling.querySelector("svg");e.type==="password"?(e.type="text",r.innerHTML=` - - `):(e.type="password",r.innerHTML=` - - - `)}let y={step1Result:null,step2Result:null,step3Result:null,bundleSpec:null,artifactBundle:null,bundleReview:null,selectedArtifactId:null,resultsViewMode:"summary",currentStep:0,isRunning:!1};function sv(){y.step1Result=null,y.step2Result=null,y.step3Result=null,y.bundleSpec=null,y.artifactBundle=null,y.bundleReview=null,y.selectedArtifactId=null,y.resultsViewMode="summary"}function rv(){y.bundleSpec=or(y.step1Result,{artifactType:"CustomWidget",artifactName:"GeneratedWidget"})}function jn(){const t=gn(y.bundleSpec);y.artifactBundle=or(y.step2Result,{id:y.bundleSpec?.id,title:y.bundleSpec?.title,description:y.bundleSpec?.description,artifactType:t.artifactType,artifactName:t.artifactName,fileName:t.fileName,dependencies:t.dependencies,relationships:y.bundleSpec?.relationships,code:y.step2Result||""});const e=dg(y.artifactBundle);y.artifactBundle={...y.artifactBundle,warnings:[...y.artifactBundle.warnings,...e.findings.map(s=>s.message)],metadata:{...y.artifactBundle.metadata,compatibility:e}},y.selectedArtifactId=gn(y.artifactBundle).id}function Un(){const t=or(y.step3Result,{id:y.artifactBundle?.id,title:y.artifactBundle?.title}),e=new Map(t.artifacts.map(r=>[r.id,r.review])),s=new Map(t.artifacts.filter(r=>{const n=r.review;return n&&typeof n.fixedSource=="string"&&n.fixedSource.trim()}).map(r=>[r.id,r.review.fixedSource.trim()]));y.bundleReview=or({id:y.artifactBundle?.id,title:y.artifactBundle?.title,artifacts:y.artifactBundle?.artifacts?.map(r=>{const n=s.get(r.id)||null;return{...r,review:e.get(r.id)||r.review||y.step3Result||null,...n?{fixedCode:n}:{}}})||[],relationships:y.artifactBundle?.relationships,warnings:y.artifactBundle?.warnings})}function Wd(){const t=ga();return{artifactType:t.artifactType||"CustomWidget",artifactName:t.artifactName||"GeneratedWidget",fileName:t.fileName||""}}function ga(){const t=y.artifactBundle||y.bundleSpec||null;return(Array.isArray(t?.artifacts)?t.artifacts:[]).find(s=>s.id===y.selectedArtifactId)||gn(t)}function ma(){return ga().code||y.step2Result||""}async function nv(){try{await da()}catch(t){return console.error("checkConnection: initializeApiKeys failed:",t),!1}return!0}const Wr={production:"https://api.flutterflow.io/v2/",staging:"https://api.flutterflow.io/v2-staging/"};function iv(t,e){const s=e?.trim()?` (${e.trim().slice(0,200)})`:"";return t===401?`Your FlutterFlow API key was rejected (401 Unauthorized)${s}. Re-enter a current key under API Keys settings, then try again.`:`Listing FlutterFlow projects was denied (403)${s}. The key may be scoped to sync a single project without list permission - verify the key's access in FlutterFlow, re-enter it under API Keys settings, then retry.`}class gr{constructor(e,s,r="main",n=Wr.production){this.apiKey=e,this.baseUrl=n,this._projectId=s,this._branchName=r,this._endpoint=n}get projectId(){return this._projectId}get branchName(){return this._branchName==="main"?"":this._branchName}async exportProjectZip(){console.log(`Exporting code from FlutterFlow project: ${this.projectId}, branch: ${this.branchName||"main"}`);const e=[{project:{path:`projects/${this.projectId}`},...this.branchName?{branch_name:this.branchName}:{},export_as_module:!1,include_assets_map:!1,format:!1,export_as_debug:!1},{project_id:this.projectId,branch_name:this.branchName,include_assets:!1,export_as_module:!1}];let s=null;for(const r of e)try{const n=await fetch(`${this.baseUrl}exportCode`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`},body:JSON.stringify(r)});if(!n.ok){const a=await n.text();s=new Error(`Export failed: ${n.status} - ${a}`);continue}const i=await n.json(),o=i?.value?.project_zip||i?.project_zip;if(!o){s=new Error("Export response did not include project source.");continue}return o}catch(n){s=n}throw s||new Error("Export failed for an unknown reason.")}async fetchProjectSource(){const e=await this.exportProjectZip(),s=await JSZip.loadAsync(e,{base64:!0}),r=Object.keys(s.files).filter(a=>!s.files[a].dir&&(a==="pubspec.yaml"||a.endsWith("/pubspec.yaml"))).sort((a,l)=>a.split("/").length-l.split("/").length)[0];if(!r)throw new Error("Export did not contain a pubspec.yaml.");const n=r.slice(0,r.length-12),i=new Map,o=Object.keys(s.files).filter(a=>{if(s.files[a].dir||!a.startsWith(n))return!1;const l=a.slice(n.length);return l==="lib/flutter_flow/custom_functions.dart"||l.startsWith("lib/custom_code/")&&l.endsWith(".dart")});return await Promise.all(o.map(async a=>{i.set(a.slice(n.length),await s.files[a].async("string"))})),{pubspecYaml:await s.files[r].async("string"),files:i}}async pushCodeWithRetry(e,s=3){const r=[Wr.production,Wr.staging],n=Math.max(0,r.indexOf(this._endpoint));for(let i=0;isetTimeout(d,1e3*(i+1)));continue}return l}catch(l){console.warn(`Push to ${a} failed: ${l.message}, trying next...`),await new Promise(u=>setTimeout(u,1e3*(i+1)))}}throw new Error("All API endpoints failed after retries")}async pushCode(e){return this.pushCodeWithRetry(e)}parseProjectsResponse(e){if(e?.success&&typeof e.value=="string")try{const r=JSON.parse(e.value);if(r&&Array.isArray(r.entries))return r.entries.map(n=>({id:n.id,name:n.project?.name||n.id}))}catch(r){console.error("Failed to parse stringified project value:",r)}const s=e?.projects||e?.items||e?.entries||(Array.isArray(e)?e:[]);return Array.isArray(s)?s:[]}async listProjects(){console.log("Listing projects for API key");const e=[`${this.baseUrl}listProjects`,"https://api.flutterflow.io/v2/l/listProjects"];let s=0,r="";for(const n of e){const i=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`},body:JSON.stringify({project_type:"ALL",deserialize_response:!0})});if(i.ok)return n!==e[0]&&console.log(`listProjects answered on legacy path ${n}`),this.parseProjectsResponse(await i.json());if(s=i.status,r=await i.text(),console.warn(`listProjects via ${n} returned ${s}: ${r}`),i.status===401||i.status===403)throw new Error(iv(i.status,r));if(i.status!==404)throw new Error(`List projects failed: ${i.status} - ${r}`)}throw new Error(`List projects failed: ${s} - ${r}`)}}async function va(t){const e=t.clone();let s;try{s=await t.json()}catch{const i=await e.text();if(!t.ok)return{success:!1,responseCode:t.status,errorMessage:i||`HTTP ${t.status}`,errorMap:new Map};throw new Error(`Invalid JSON response: ${i}`)}if(!t.ok){let n=s.message||`HTTP ${t.status}`,i=new Map;if(s.errors)i=new Map(Object.entries(s.errors));else if(!s.message&&typeof s=="object"){const o=Object.keys(s).filter(a=>a.endsWith(".dart")&&Array.isArray(s[a]));o.length>0&&(i=new Map(Object.entries(s)),n=o.flatMap(l=>s[l].map(u=>`${l}: ${u.errorMessage}`)).join(` -`)||`HTTP ${t.status}`)}return{success:!1,responseCode:t.status,errorMessage:n,errorMap:i}}let r={};if(s.value)try{r=typeof s.value=="string"?JSON.parse(s.value):s.value}catch(n){console.warn("Ignoring malformed push response value:",n)}return{success:!0,responseCode:t.status,errorMap:new Map(Object.entries(r))}}function _a(t,e){return{401:"Authentication failed. Please check your FlutterFlow API key.",403:"Access denied. You may not have permission to modify this project.",404:"Project not found. Please check your Project ID.",409:"Conflict detected. The project may have been modified elsewhere.",422:"Validation failed: Invalid request format",429:"Rate limit exceeded. Please try again in a few minutes.",500:"FlutterFlow server error. Please try again later.",503:"FlutterFlow service temporarily unavailable."}[t]||`FlutterFlow API error: ${`HTTP ${t}`}`}const U={ACTION:"A",WIDGET:"W",FUNCTION:"F",CODE_FILE:"C",DEPENDENCIES:"D",OTHER:"O"},zd=/class\s+\w+\s+extends\s+(?:StatelessWidget|StatefulWidget)\b/,qd=/extends\s+State<\w+>/;function ov(t,e=""){if(t==="pubspec.yaml")return U.DEPENDENCIES;if(!t.endsWith(".dart")||t.endsWith("index.dart"))return U.OTHER;if(t==="custom_functions.dart")return U.FUNCTION;if(e){const s=zd.test(e),r=qd.test(e);if(s||r)return U.WIDGET;if(/^\s*Future(?:<[^>]+>)?\s+\w+\s*\(/m.test(e))return U.ACTION;if(e.match(/^\s*(String|int|double|bool|List|Map|dynamic|void)\s+\w+\s*\(/m))return U.FUNCTION}return U.CODE_FILE}function Vd(t,e){switch(e){case U.ACTION:return`lib/custom_code/actions/${t}`;case U.WIDGET:return`lib/custom_code/widgets/${t}`;case U.FUNCTION:return"lib/flutter_flow/custom_functions.dart";case U.CODE_FILE:return`lib/custom_code/${t}`;case U.DEPENDENCIES:return"pubspec.yaml";case U.OTHER:return`lib/custom_code/${t}`;default:return t}}async function ya(t,e=new Map){return Gf(t,e)}const Co=new Map;function Gd(t){return`${t.baseUrl}|${t.projectId}|${t.branchName}`}function Hn(t){Co.delete(Gd(t))}async function wa(t,e,s,r,n=""){const i=xg(e,s);if(i.length===0)return{remoteFiles:s,syncFileMap:e,unverified:[]};const o=em(i,n),a={...o.manifest,sources:o.sources},l=o.skipped.map(d=>d.reason);l.forEach(d=>console.warn(`[custom class deploy] ${d}`)),console.log(`Provisioning ${i.length} new FlutterFlow custom code file(s) before sync.`),be.set("provision");const u=await fetch(ym,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:t.apiKey,projectId:t.projectId,baseUrl:t.baseUrl,commitMessage:r,customClasses:i,verification:a,stream:!0})}),c=await sm(u,{onPhase:d=>be.setSubstatus(d),onLog:d=>console.log(`[custom class deploy] ${d}`)});if(!c.success){const d=c.details?` ${c.details}`:"";throw new Error(`${c.error||"FlutterFlow custom class provisioning failed."}${d}`)}return Hn(t),c.verificationSkipped&&(console.warn(`[custom class deploy] ${c.verificationSkipped}`),l.push(c.verificationSkipped)),{remoteFiles:s,syncFileMap:kg(e,i),unverified:l}}async function ba(t,e={}){const s=Gd(t);let r=Co.get(s);if(r===void 0){try{r=await t.fetchProjectSource()}catch(l){throw new Error(`Could not read your project's pubspec.yaml (${l.message}). Deploy was stopped so your existing package dependencies aren't overwritten. Check your FlutterFlow API key and project, then try again.`)}const a=Cd(r.pubspecYaml);if(!a.valid)throw new Error(`Your project's pubspec.yaml could not be read reliably (${a.errors.join("; ")}). Deploy was stopped so your existing package dependencies aren't overwritten.`);Co.set(s,r)}const n=await pm(r.pubspecYaml,e),i=Jg(r.pubspecYaml,n.overrides),o=Kg(i.yaml,n.additions);return n.warnings.forEach(a=>console.warn(`[pubspec] ${a}`)),o.added.length>0&&console.log("Adding dependencies:",o.added.map(a=>`${a}: ${n.additions[a]||"any"}`).join(", "),n.sdk.dartSdkFloor?`(resolved for Dart ${n.sdk.dartSdkFloor})`:""),n.kept.forEach(({name:a,constraint:l})=>console.log(`Keeping your existing ${a}: ${l||"(non-version source)"}`)),{...o,overridden:i.overridden,warnings:n.warnings,remoteFiles:r.files}}function av(t){const e=[],s=[];t.content.length>5e4&&s.push("Code file is large (>50KB). This may take longer to commit."),t.content.length>1e5&&e.push("Code file is too large (>100KB). Consider splitting into smaller components.");const r=t.content.split(` -`).length;r>500&&s.push(`Code has ${r} lines. Consider breaking it into smaller widgets.`),t.content.includes("setState")&&t.codeType===U.ACTION&&s.push("Using setState in a Custom Action may not work as expected. Consider using a Custom Widget."),t.content.includes("dynamic")&&!t.content.includes("?")&&s.push('Code uses "dynamic" types. Consider adding explicit types for better null safety.'),t.content.match(/Color\(0xFF[0-9A-Fa-f]{6}\)/)&&s.push("Code contains hardcoded colors. Consider using FlutterFlowTheme.of(context) for theme consistency.");const n=t.content.match(/print\s*\(/g);n&&n.length>3&&s.push(`Code contains ${n.length} print statements. Consider removing debug prints before committing.`);const i=Wg(t.content);if(i&&e.push(`FlutterFlow cannot format this code - ${i}. Fix or regenerate before committing.`),t.codeType===U.WIDGET){const o=wd(t.content),a=jg(t.fileName);if(o.length===0)e.push("No public widget class found (must extend StatelessWidget or StatefulWidget).");else if(!o.includes(a)){const l=`${bd(o[0])}`;e.push(`Widget class name "${o[0]}" does not match the file name "${t.fileName}". FlutterFlow derives the widget from the file name, so it will report "No widget ${a} found". Rename the file to "${l}" or the class to match before committing.`)}}return{canProceed:e.length===0,issues:e,warnings:s}}function Kd(t,e={}){const{artifactType:s="CustomWidget",artifactName:r="GeneratedCode",fileName:n}=e,i=Dg(t);let o=n||r;if(s==="CustomFunction")o="custom_functions.dart";else if(s==="CustomWidget"){const u=wd(i)[0],c=u?bd(u):null;c&&o!==c?(console.warn(`Commit file name "${o}" does not match declared widget class "${u}"; renaming to "${c}" so FlutterFlow can find the widget.`),o=c):o.endsWith(".dart")||(o+=".dart")}else o.endsWith(".dart")||(o+=".dart");let a=U.CODE_FILE;switch(s){case"CustomAction":a=U.ACTION;break;case"CustomWidget":a=U.WIDGET;break;case"CustomFunction":a=U.FUNCTION;break;case"CustomClass":case"CodeFile":a=U.CODE_FILE;break}let l="";return a===U.WIDGET?l=`// Automatic FlutterFlow imports -import '/flutter_flow/flutter_flow_theme.dart'; -import '/flutter_flow/flutter_flow_util.dart'; -import 'package:flutter/material.dart'; -// Begin custom widget code -// DO NOT REMOVE OR MODIFY THE CODE ABOVE! - -`:a===U.ACTION?l=`// Automatic FlutterFlow imports -import '/flutter_flow/flutter_flow_theme.dart'; -import '/flutter_flow/flutter_flow_util.dart'; -import 'package:flutter/material.dart'; -// Begin custom action code -// DO NOT REMOVE OR MODIFY THE CODE ABOVE! - -`:a===U.FUNCTION&&(l=`// Automatic FlutterFlow imports -import 'dart:convert'; -import 'dart:math' as math; - -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:intl/intl.dart'; -import 'package:timeago/timeago.dart' as timeago; -import '/flutter_flow/lat_lng.dart'; -import '/flutter_flow/place.dart'; -import '/flutter_flow/uploaded_file.dart'; - -`),{content:fg(i,l),fileName:o,codeType:a,artifactType:s,artifactName:r}}function lv(t){const e={};for(const s of ra(t))e[s]="";return e}function cv(t,e={}){return{timestamp:new Date().toISOString(),artifactType:t.artifactType,artifactName:t.artifactName,codeType:t.codeType,fileName:t.fileName,generatedFrom:e.step1Result?"pipeline":"direct",model:e.selectedModel||"unknown",codeSize:t.content.length}}function uv(t,e,s,r=new Set,n=""){const i=[],o=zd.test(e),a=qd.test(e);return s===U.WIDGET&&!o&&!a&&i.push("No widget class definition found (must extend StatelessWidget or StatefulWidget)"),{valid:i.length===0,errors:i}}function Wn(t){const e=[],s=[];if(!t||t.size===0)return e.push("No files to commit"),{valid:!1,errors:e,warnings:s};const r=new Set(Array.from(t.values()).flatMap(n=>Tn(n.content||"")));for(const[n,i]of t.entries()){if((!i.content||i.content.trim().length===0)&&e.push(`File ${n} is empty`),i.content&&i.content.length>1e5&&s.push(`File ${n} is very large (>100KB)`),n.endsWith(".dart")){const o=uv(n,i.content,i.type,r,i.artifactName);o.valid||e.push(...o.errors.map(a=>`${n}: ${a}`))}if(n==="pubspec.yaml"){const o=Cd(i.content);o.valid||e.push(...o.errors)}}return{valid:e.length===0,errors:e,warnings:s}}const V={IDLE:"IDLE",PREPARING:"PREPARING",VALIDATING:"VALIDATING",PUSHING:"PUSHING",SUCCESS:"SUCCESS",ERROR:"ERROR"},K={currentState:V.IDLE,startTime:null,endTime:null,error:null,result:null,filesProcessed:0,totalFiles:0,reset(){this.currentState=V.IDLE,this.startTime=null,this.endTime=null,this.error=null,this.result=null,this.filesProcessed=0,this.totalFiles=0},setState(t){if(!Object.values(V).includes(t)){console.error(`Invalid commit state: ${t}`);return}this.currentState=t,t===V.PREPARING&&(this.startTime=Date.now()),(t===V.SUCCESS||t===V.ERROR)&&(this.endTime=Date.now()),typeof window<"u"&&window.dispatchEvent&&window.dispatchEvent(new CustomEvent("commitStateChange",{detail:{state:t,commitState:this}})),console.log(`Commit state changed to: ${t}`)},setError(t){this.error=t,this.setState(V.ERROR)},setSuccess(t){this.result=t,this.setState(V.SUCCESS)},setProgress(t,e){this.filesProcessed=t,this.totalFiles=e},getElapsedTime(){return this.startTime?(this.endTime||Date.now())-this.startTime:null},isInProgress(){return this.currentState===V.PREPARING||this.currentState===V.VALIDATING||this.currentState===V.PUSHING}};async function dv(t,e,s={}){let{codeType:r="W"}=s;const{pubspecDeps:n={},artifactName:i=e}=s;r==="CustomWidget"&&(r=U.WIDGET),r==="CustomAction"&&(r=U.ACTION),r==="CustomFunction"&&(r=U.FUNCTION),r==="CustomClass"&&(r=U.CODE_FILE),r==="CodeFile"&&(r=U.CODE_FILE),K.reset(),K.setState(V.PREPARING);try{const o=await Ee("flutterflow"),a=await Ee("flutterflow_project_id");if(!o||!a)throw new Error("FlutterFlow credentials not configured. Please set your API key and Project ID in the API Keys settings.");if(!Bn(a))throw new Error("Invalid FlutterFlow Project ID format.");const l=fr(),u=new gr(o,a,"main",l);K.setState(V.VALIDATING);const c=new Map,d=r||ov(e,t),h=Vd(e,d);c.set(e,{artifactName:i,content:t,type:d,path:h}),K.setProgress(0,c.size);const p=Wn(c);if(!p.valid)throw new Error(`Validation failed: -${p.errors.join(` -`)}`);const f=await ba(u,n),g=f.yaml,m=await wa(u,c,f.remoteFiles,`Provision ${i} custom class`,g),_=await ya(m.syncFileMap,m.remoteFiles),w=new Map(m.syncFileMap);w.set("pubspec.yaml",{content:g,type:"D",path:"pubspec.yaml"}),be.set("package");const E=await Ea(w),I={project_id:a,zipped_custom_code:E,uid:`web_${Date.now()}`,branch_name:u.branchName,serialized_yaml:g,file_map:_.fileMapContents,functions_map:_.functionsMapContents};K.setState(V.PUSHING),K.setProgress(1,c.size),Hn(u),be.set("push");const F=await u.pushCode(I),P=await va(F);if(P.success)K.setSuccess({fileCount:c.size,projectId:a,warnings:P.errorMap&&P.errorMap.size>0?Array.from(P.errorMap.entries()):[]});else{const B=P.errorMessage||_a(P.responseCode);throw new Error(B)}return{success:!0,message:`Successfully committed ${e} to FlutterFlow project ${a}`,addedDependencies:f.added,unverified:m.unverified,warnings:P.errorMap?Array.from(P.errorMap.entries()):[]}}catch(o){return console.error("Commit failed:",o),K.setError(o),{success:!1,error:o.message,state:K.currentState}}}async function Ea(t){const e=new JSZip;for(const[s,r]of t.entries())e.file(s,r.content);return e.generateAsync({type:"base64",compression:"DEFLATE",compressionOptions:{level:6}})}async function hv(t,e={}){const{artifactType:s,artifactName:r,fileName:n,pipelineResult:i}=e;console.log(`Starting commit for ${r} (${s})`);try{K.setState(V.PREPARING);const o=Kd(t,{artifactType:s,artifactName:r,fileName:n}),a=lv(o.content);console.log("Detected dependencies:",a),K.setState(V.VALIDATING);const l=await Ee("flutterflow"),u=Zs||await Ee("flutterflow_project_id");if(!l)throw new Error("FlutterFlow API Key not configured. Please add it in API Keys settings.");if(!u)throw new Error("FlutterFlow Project ID not configured. Please add it in API Keys settings.");if(!Bn(u))throw new Error("Invalid FlutterFlow Project ID format.");const c=new Map;c.set(o.fileName,{artifactName:r,content:o.content,type:o.codeType,path:Vd(o.fileName,o.codeType),functionName:o.codeType===U.FUNCTION?r:void 0}),K.setProgress(0,c.size);const d=Wn(c);if(!d.valid)throw new Error(`File validation failed: -${d.errors.join(` -`)}`);d.warnings.length>0&&console.warn("Validation warnings:",d.warnings),K.setState(V.PUSHING);const h=fr(),p=new gr(l,u,"main",h),f=await ba(p,a),g=f.yaml,m=await wa(p,c,f.remoteFiles,`Provision ${r} custom class`,g),_=await ya(m.syncFileMap,m.remoteFiles),w=new Map(m.syncFileMap);w.set("pubspec.yaml",{content:g,type:U.DEPENDENCIES,path:"pubspec.yaml"}),be.set("package");const E=await Ea(w),I={project_id:u,zipped_custom_code:E,uid:`web_${Date.now()}`,branch_name:p.branchName,serialized_yaml:g,file_map:_.fileMapContents,functions_map:_.functionsMapContents};K.setProgress(1,c.size),Hn(p),be.set("push");const F=await p.pushCode(I),P=await va(F);if(P.success){const B={...cv(o,i),projectId:u};return K.setSuccess({...B,fileCount:c.size,warnings:P.errorMap?Array.from(P.errorMap.entries()):[]}),{success:!0,message:`Successfully committed ${o.fileName} to FlutterFlow`,metadata:B,addedDependencies:f.added,unverified:m.unverified,warnings:P.errorMap?Array.from(P.errorMap.entries()):[],elapsedTime:K.getElapsedTime()}}else{const B=P.errorMessage||_a(P.responseCode),S=new Error(B);throw S.errorMap=P.errorMap,S}}catch(o){console.error("Commit execution failed:",o),K.setError(o);let a=new Map;if(o.errorMap)a=o.errorMap;else if(o.message&&o.message.includes("{"))try{const l=o.message.match(/\{[\s\S]*\}/);if(l){const u=JSON.parse(l[0]);a=new Map(Object.entries(u))}}catch(l){console.warn("Failed to parse error map from commit response:",l)}return{success:!1,error:o.message,errorMap:a,state:K.currentState,elapsedTime:K.getElapsedTime()}}}async function pv(t,e={}){const{pipelineResult:s}=e;try{if(K.setState(V.PREPARING),t.errors?.length>0)throw new Error(`Bundle validation failed: -${t.errors.join(` -`)}`);const r=new Map(t.fileEntries.map(I=>[I.fileName,{artifactId:I.artifactId,artifactName:I.artifactName,content:I.content,type:I.type,path:I.path,functionName:I.type===U.FUNCTION?I.artifactName:void 0}]));K.setProgress(0,r.size);const n=Wn(r);if(!n.valid)throw new Error(`File validation failed: -${n.errors.join(` -`)}`);K.setState(V.VALIDATING);const i=await Ee("flutterflow"),o=Zs||await Ee("flutterflow_project_id");if(!i)throw new Error("FlutterFlow API Key not configured. Please add it in API Keys settings.");if(!o)throw new Error("FlutterFlow Project ID not configured. Please add it in API Keys settings.");if(!Bn(o))throw new Error("Invalid FlutterFlow Project ID format.");K.setState(V.PUSHING);const a=fr(),l=new gr(i,o,"main",a),u=await ba(l,t.dependencies),c=u.yaml,d=await wa(l,r,u.remoteFiles,`Provision ${t.title} custom classes`,c),h=await ya(d.syncFileMap,d.remoteFiles),p=new Map(d.syncFileMap);p.set("pubspec.yaml",{content:c,type:U.DEPENDENCIES,path:"pubspec.yaml"}),be.set("package");const f=await Ea(p),g={project_id:o,zipped_custom_code:f,uid:`web_${Date.now()}`,branch_name:l.branchName,serialized_yaml:c,file_map:h.fileMapContents,functions_map:h.functionsMapContents};K.setProgress(1,r.size),Hn(l),be.set("push");const m=await l.pushCode(g),_=await va(m);if(_.success){const I={...s,artifactType:"Bundle",artifactName:t.title,fileName:`${t.fileEntries.length} artifacts`,codeSize:t.fileEntries.reduce((F,P)=>F+P.content.length,0),projectId:o};return K.setSuccess({...I,fileCount:r.size,warnings:_.errorMap?Array.from(_.errorMap.entries()):[]}),{success:!0,message:`Successfully committed ${t.fileEntries.length} artifacts to FlutterFlow`,metadata:I,addedDependencies:u.added,unverified:d.unverified,warnings:_.errorMap?Array.from(_.errorMap.entries()):[],elapsedTime:K.getElapsedTime()}}const w=_.errorMessage||_a(_.responseCode),E=new Error(w);throw E.errorMap=_.errorMap,E}catch(r){return console.error("Bundle commit execution failed:",r),K.setError(r),{success:!1,error:r.message,errorMap:r.errorMap||new Map,state:K.currentState,elapsedTime:K.getElapsedTime()}}}async function fv(t,e=[]){const s=Qo("architect");try{return await In("architect",Td,Mf(t),s,e)}catch(r){throw r.isModelArmor?r:new Error(`Prompt Architect failed: ${r.message}`)}}async function zn(t,e,s=[]){const r=Lf(t),n=Qo("generator",y.bundleSpec);try{return await In("generator",e,r,n,s)}catch(i){if(i.isModelArmor)throw i;if(e!==Fi){console.warn(`Code Generator failed with ${e}, retrying with fallback model:`,i.message);try{return await In("generator",Fi,r,n,s)}catch(o){throw o.isModelArmor?o:new Error(`Code Generator failed: primary (${e}): ${i.message} | fallback (${Fi}): ${o.message}`)}}throw new Error(`Code Generator failed: ${i.message}`)}}async function qn(t,e=null){const s={...Qo("review",y.artifactBundle||y.bundleSpec),architect_output:e};try{return await In("review",Nd,Of(t),s)}catch(r){throw r.isModelArmor?r:new Error(`Code Review failed: ${r.message}`)}}function Sa(t,e){return t.isModelArmor?`${t.userTitle}: ${t.userMessage}`:`${e}: ${t.message}`}function Fo(t,e){const s=document.getElementById(`step${t}-item`),r=document.getElementById(`step${t}-status`);!s||!r||(s.classList.remove("active","completed","error"),r.classList.remove("running","completed","error"),e==="active"?(s.classList.add("active"),r.classList.add("running"),r.innerHTML=` - - `):e==="completed"?(s.classList.add("completed"),r.classList.add("completed"),r.innerHTML=` - - `):e==="error"?(s.classList.add("error"),r.classList.add("error"),r.innerHTML=` - - `):r.innerHTML=` - - `)}function ve(t,e){const s=document.getElementById(`step${t}-loading`),r=document.getElementById(`step${t}-result`);e?(s.classList.remove("hidden"),r.classList.add("hidden"),Fo(t,"active")):(s.classList.add("hidden"),r.classList.remove("hidden"),Fo(t,"completed"))}function gv(t){const e=document.getElementById(`${t}-content`),s=document.getElementById(`${t}-chevron`);e.classList.contains("open")?(e.classList.remove("open"),s&&(s.style.transform="rotate(0deg)")):(e.classList.add("open"),s&&(s.style.transform="rotate(180deg)"))}function mv(t){ze(parseInt(t.replace("step","")))}function ze(t){for(let o=1;o<=3;o++){const a=document.getElementById(`step${o}-item`);a&&a.classList.remove("active")}const e=document.getElementById(`step${t}-item`);e&&e.classList.add("active"),Yt();const s=document.getElementById("ready-state");s&&s.classList.add("hidden");for(let o=1;o<=3;o++){const a=document.getElementById(`step${o}-content`);a&&a.classList.add("hidden")}const r=document.getElementById(`step${t}-content`);r&&r.classList.remove("hidden");const n=document.getElementById("stage-title"),i={1:"Prompt Architect",2:"Code Generator",3:"Code Review"};n&&(n.textContent=i[t]||"Active Workflow Stage")}function vv(t){const e=document.getElementById(t);if(!e)return;const s=e.dataset.raw||e.textContent;navigator.clipboard.writeText(s).then(()=>{const n=e.closest(".code-container")?.querySelector(".copy-btn");n&&(n.classList.add("copied"),n.innerHTML=' Copied!',setTimeout(()=>{n.classList.remove("copied"),n.innerHTML=' Copy'},2e3))}).catch(r=>{console.warn("Failed to copy to clipboard:",r)})}function Po(t){const e=$o(t);console.log(`Step 1 (Prompt Architect): ${zt(Td)}`),console.log(e!==t?`Step 2 (Code Generator): ${zt(t)} → ${zt(e)} (Free Tier fallback)`:`Step 2 (Code Generator): ${zt(t)}`),console.log(`Step 3 (Code Review): ${zt(Nd)}`)}async function _v(){if(console.log("runRefinement called"),y.isRunning)return;const t=document.getElementById("code-generator-model").value;y.isRunning=!0,xa("standardRegenerate",y.step2Result,y.step1Result);const e=document.querySelectorAll(".btn-refine-action");e.forEach(s=>{s.disabled=!0,s.innerHTML=` - - - Refining...`});try{const s=ga(),r=Df({bundleSpec:y.step1Result,artifactBundle:JSON.stringify(y.artifactBundle||y.step2Result),bundleReview:y.step3Result,artifactId:s.id,userFeedback:"Fix the issues listed in the audit report."});Kn(),nt(2),ze(2),ve(2,!0),y.step2Result=await zn(r,t),jn();const n=document.getElementById("step2-output"),i=ws(y.step2Result);n.textContent=i,n.dataset.raw=i,ve(2,!1),ze(3),nt(3),ve(3,!0),y.step3Result=await qn(y.step2Result,y.step1Result),Un();const o=document.getElementById("step3-output");o.textContent=y.step3Result,ve(3,!1),$t();const a=On(y.step3Result);Jn(i,a)}catch(s){console.error("Refinement failed:",s),$t(),ue(Sa(s,"Refinement failed"),"error")}finally{y.isRunning=!1,e.forEach(s=>{s.disabled=!1,s.textContent="Refine & Regenerate"}),Zt()}}async function xa(t,e,s){const r=`${Je}/connectFeedback`,n={type:t,code:e,input:s};try{const i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)});if(!i.ok){const a=await i.text();return console.error(`callEndpoint failed: ${i.status} ${i.statusText}`,a),{success:!1,status:i.status,error:a}}const o=await i.json();return console.log("Telemetry success:",o),o}catch(i){return console.error("callEndpoint failed:",i),{success:!1,error:i.message}}}function yv(){const t=document.getElementById("ff-error-paste-input");t&&(t.value="")}async function wv(){const t=document.getElementById("ff-error-paste-input"),e=t?.value?.trim();if(!e){t?.focus(),t?.classList.add("ring-2","ring-red-400","border-red-300"),setTimeout(()=>t?.classList.remove("ring-2","ring-red-400","border-red-300"),2e3);return}if(!y.step2Result){ue("No generated code found. Please run the full pipeline first.","warning");return}if(y.isRunning)return;const s=document.getElementById("code-generator-model").value;y.isRunning=!0,xa("flutterflowError",y.step2Result,e);const r=document.getElementById("btn-fix-from-errors");r&&(r.disabled=!0,r.innerHTML=` - - Fixing…`);try{const n=fd({bundleSpec:y.step1Result,artifactBundle:JSON.stringify(y.artifactBundle||y.step2Result),bundleReview:y.step3Result,userFeedback:e});ah(),Kn(),nt(2),ze(2),ve(2,!0),y.step2Result=await zn(n,s),jn();const i=document.getElementById("step2-output"),o=ws(y.step2Result);i.textContent=o,i.dataset.raw=o,ve(2,!1),ze(3),nt(3),ve(3,!0),y.step3Result=await qn(y.step2Result,y.step1Result),Un();const a=document.getElementById("step3-output");a.textContent=y.step3Result,ve(3,!1),$t();const l=On(y.step3Result);Jn(o,l),t&&(t.value="")}catch(n){console.error("Fix from errors failed:",n),$t(),ue(Sa(n,"Failed to fix errors"),"error")}finally{y.isRunning=!1,r&&(r.disabled=!1,r.textContent="Fix Errors & Regenerate"),Zt()}}async function Ao(){if(console.log("runThinkingPipeline called"),y.isRunning)return;localStorage.setItem("hasSeenWalkthrough","true");const t=document.getElementById("pipeline-input").value,e=document.getElementById("code-generator-model").value;if(!t.trim()){ue("Please describe your FlutterFlow widget first.","warning");return}if(!await jv())return;await Nv();const s=$o(e);t.length;const r=document.getElementById("btn-run-pipeline");y.isRunning=!0,sv(),r.disabled=!0,r.innerHTML=` - - - Running...`,Po(s);try{Yt();const n=document.getElementById("ready-state");n&&n.classList.add("hidden");const i=document.getElementById("paywall-exhausted");i&&i.classList.add("hidden"),Kn(),ze(1),nt(1),ve(1,!0);const o=Pt.filter(p=>p.url).map(p=>({url:p.url}));y.step1Result=await fv(t,o),rv();const a=document.getElementById("step1-output"),l=ws(y.step1Result);a.textContent=l,a.dataset.raw=l,ve(1,!1),ze(2),nt(2),ve(2,!0),y.step2Result=await zn(y.step1Result,s,o),jn();const u=document.getElementById("step2-output"),c=ws(y.step2Result);u.textContent=c,u.dataset.raw=c,ve(2,!1),ze(3),nt(3),ve(3,!0),y.step3Result=await qn(y.step2Result,y.step1Result),Un();const d=document.getElementById("step3-output");d.textContent=y.step3Result,ve(3,!1),$t();const h=On(y.step3Result);Jn(c,h)}catch(n){if(console.error("Pipeline failed:",n),$t(),n.isUsageLimit){const{count:c}=Vn();Aa(c,Pa(),{openModal:!0});return}n.message,$o(document.getElementById("code-generator-model").value);const o=gm(n,{architect:1,generator:2,review:3});ze(o);const a=document.getElementById(`step${o}-result`),l=document.getElementById(`step${o}-loading`),u=document.getElementById(`step${o}-output`);if(l&&l.classList.add("hidden"),a&&a.classList.remove("hidden"),u)if(n.isModelArmor)u.innerHTML=``;else{let c=n.message;n.message.includes("image input")?c=`This model doesn't support image input. Please use ${zt(lr)} for image-based requests or remove image references from your prompt.`:(n.message.includes("Load failed")||n.message.includes("CORS"))&&(c="API connection failed. This might be due to CORS restrictions or network issues. Please check your API key and try again."),u.innerHTML=`
-

Connection Error

-

${j(c)}

-
-

Check if API key is valid

-

Try using a different model

-

Ensure network allows API calls

-
-
`}Fo(o,"error")}finally{y.isRunning=!1,r.disabled=!1,r.innerHTML=` - - - Run Pipeline`,Zt()}}function bv(){const t=document.getElementById("code-generator-model").value,e=[lr,"anthropic/claude-opus-5","openai/gpt-5.6-sol"].filter(r=>r!==t),s=prompt(`Retry with different model? - -Current: ${t} - -Options: -1. ${e[0]} -2. ${e[1]} - -Enter 1 or 2:`);s==="1"?(document.getElementById("code-generator-model").value=e[0],Ao()):s==="2"&&(document.getElementById("code-generator-model").value=e[1],Ao())}async function Ev(){const t=ma();if(!t){ue("No code to commit. Please run the pipeline first.","warning");return}const e=await Ee("flutterflow"),s=await Ee("flutterflow_project_id");if(!e||!s){ue("FlutterFlow credentials not configured. Add your API Key and Project ID in settings.","warning"),ha();return}if(y.artifactBundle?.artifacts?.length>1){await Sv();return}const{artifactType:r,artifactName:n,fileName:i}=Wd(),o=Kd(t,{artifactType:r,artifactName:n,fileName:i}),a=av(o);if(!a.canProceed){ue(`Pre-commit checks failed: ${a.issues.join("; ")}`,"error");return}eh(o,a,null,null)}async function Sv(){const t=await Ee("flutterflow"),e=await Ee("flutterflow_project_id");if(!t||!e){ue("FlutterFlow credentials not configured. Add your API Key and Project ID in settings.","warning"),ha();return}const s=wg(y.artifactBundle);if(s.errors.length>0){ue(`Bundle validation failed: ${s.errors.join("; ")}`,"error");return}const r=new Map(s.fileEntries.map(a=>[a.fileName,{content:a.content,type:a.type,path:a.path}])),n=Wn(r),i={canProceed:n.valid&&s.errors.length===0,issues:[...s.errors,...n.errors],warnings:[...s.warnings,...n.warnings]};if(!i.canProceed){ue(`Bundle validation failed: ${i.issues.join("; ")}`,"error");return}const o={content:s.fileEntries.map(a=>`// ${a.fileName} -${a.content}`).join(` - -`),fileName:`${s.fileEntries.length} files`,codeType:"bundle",artifactType:"Bundle",artifactName:s.title};eh(o,i,s.dependencies,s)}function xv(t){let e=t.errorMap||new Map;!(e instanceof Map)&&typeof e=="object"&&(e=new Map(Object.entries(e)));let s=`
-

FlutterFlow Commit Failed

-

${j(t.error)}

`;if(e&&e.size>0){s+=`
-

Errors:

-
    `;for(const[n,i]of e.entries()){const o=Ed(i);s+=`
  • - ${j(n)}: ${j(o)} -
  • `}s+="
"}s+="
",s+=`
- -
`;const r=document.getElementById("step3-output");r&&(r.innerHTML=s,document.getElementById("btn-regenerate-from-error")?.addEventListener("click",()=>{kv(t.error,e)}))}async function kv(t,e){if(y.isRunning)return;const s=document.getElementById("code-generator-model").value;y.isRunning=!0;const r=document.getElementById("btn-regenerate-from-error");r&&(r.disabled=!0,r.innerHTML=` - - Fixing...`);try{let n=`The previous code had the following errors when committing to FlutterFlow: - -`;if(e&&e.size>0)for(const[c,d]of e.entries()){const h=Ed(d);n+=`File: ${c} -Error: ${h} - -`}else n+=`${t} -`;const i=fd({bundleSpec:y.step1Result,artifactBundle:JSON.stringify(y.artifactBundle||y.step2Result),bundleReview:y.step3Result,userFeedback:n});Kn(),nt(2),ze(2),ve(2,!0),y.step2Result=await zn(i,s),jn();const o=document.getElementById("step2-output"),a=ws(y.step2Result);o.textContent=a,o.dataset.raw=a,ve(2,!1),ze(3),nt(3),ve(3,!0),y.step3Result=await qn(y.step2Result,y.step1Result),Un();const l=document.getElementById("step3-output");l.textContent=y.step3Result,ve(3,!1),$t();const u=On(y.step3Result);Jn(a,u)}catch(n){console.error("Regeneration failed:",n),$t(),ue(Sa(n,"Regeneration failed"),"error")}finally{y.isRunning=!1,r&&(r.disabled=!1,r.textContent="Fix Errors & Regenerate"),Zt()}}async function Iv(){const t=document.getElementById("ff-status-dot"),e=document.getElementById("ff-status-text");if(!t||!e)return;const s=await Ee("flutterflow"),r=await Ee("flutterflow_project_id");s&&r?(t.className="w-2 h-2 rounded-full bg-green-500",e.textContent="FlutterFlow credentials configured",e.className="text-green-600"):s||r?(t.className="w-2 h-2 rounded-full bg-yellow-500",e.textContent="FlutterFlow credentials incomplete",e.className="text-yellow-600"):(t.className="w-2 h-2 rounded-full bg-red-500",e.textContent="FlutterFlow credentials not configured",e.className="text-red-600")}async function Cv(t){try{const e=await fetch(`${Je}/auth/send-magic-link`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:t})});if(!e.ok)throw new Error(`Failed to send magic link: HTTP ${e.status}`);return e.json()}catch(e){throw console.error("sendMagicLink failed:",{email:t,message:e.message,stack:e.stack}),e}}async function Fv(t){try{const s=await(await fetch(`${Je}/auth/verify-magic-link`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:t})})).json();if(s.error||!s.email||!s.sessionToken)throw new Error(s.error||"Invalid or expired link");return s}catch(e){throw console.error("verifyMagicLink failed:",{message:e.message,stack:e.stack}),e}}async function Pv(t){try{const e=await fetch(`${Je}/auth/refresh-session`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionToken:t})});if(!e.ok)return console.error("refreshSession: non-OK response",{url:`${Je}/auth/refresh-session`,status:e.status}),null;const s=await e.json();return s.error||!s.email||!s.sessionToken?(console.warn("refreshSession: validation failed",{error:s.error,hasEmail:!!s.email,hasToken:!!s.sessionToken}),null):s}catch(e){return console.error("refreshSession: fetch failed",{url:`${Je}/auth/refresh-session`,message:e.message,stack:e.stack}),null}}function bc(t,e){const s=Jd(),r=(G.email||s.email)!==t;G.email=t,G.sessionToken=e,G.isVerified=!0,fe=bs({isLoading:!0}),localStorage.setItem(_n,JSON.stringify({email:t,sessionToken:e})),r&&$a()}function ka(){G.email=null,G.sessionToken=null,G.isVerified=!1,fe=bs({isResolved:!0}),localStorage.removeItem(_n),localStorage.removeItem(wn)}function Jd(){try{const t=localStorage.getItem(_n);if(!t)return{email:null,sessionToken:null};const e=JSON.parse(t);return!e.email||!e.sessionToken?{email:null,sessionToken:null}:e}catch(t){return console.warn("getStoredSession: failed to parse auth session:",t),localStorage.removeItem(_n),{email:null,sessionToken:null}}}async function Av(){const e=new URLSearchParams(window.location.search).get("token");if(e){window.history.replaceState({},"",window.location.pathname);try{const{email:s,sessionToken:r}=await Fv(e);bc(s,r)}catch(s){ue(s.message||"Sign-in link invalid or expired.","error")}}else{const{email:s,sessionToken:r}=Jd();if(s&&r){const n=await Pv(r);n?bc(n.email,n.sessionToken):ka()}}Ca()}function Ia(){const t=document.getElementById("signin-modal");t&&t.classList.add("open")}function $v(t){if(t&&t.target!==t.currentTarget)return;const e=document.getElementById("signin-modal");e&&e.classList.remove("open")}async function Rv(){const t=document.getElementById("signin-email-input"),e=document.getElementById("signin-submit-btn"),s=document.getElementById("signin-message"),r=t?.value?.trim();if(!r||!/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(r)||r.length>254){s&&(s.textContent="Please enter a valid email address.");return}e&&(e.disabled=!0,e.textContent="Sending…"),s&&(s.textContent="");try{await Cv(r),t&&(t.value=""),s&&(s.textContent=`Check your email — we sent a link to ${r}`),e&&(e.textContent="Sent!")}catch(i){console.error("handleMagicLinkRequest: sendMagicLink failed",{email:r,err:i}),s&&(s.textContent="Something went wrong. Please try again."),e&&(e.disabled=!1,e.textContent="Send Link")}}function Tv(){ka(),$a(),Ca(),Gn()}function Ca(){const t=G.isVerified&&!!G.email,e=document.getElementById("auth-signedout"),s=document.getElementById("auth-signedin"),r=document.getElementById("auth-guest-usage");e&&e.classList.toggle("hidden",t),s&&s.classList.toggle("hidden",!t),r&&r.classList.toggle("hidden",t);const n=document.getElementById("auth-user-email");n&&(n.textContent=G.email||""),zr(),Gn()}async function Yd(){try{if(typeof FingerprintJS>"u"){console.warn("resolveIdentity: FingerprintJS not loaded, skipping");return}const e=await(await FingerprintJS.load()).get(),s=e.visitorId,r=await fetch(Sm,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({fingerprint:e.visitorId,cookie_id:s})});if(!r.ok)throw new Error(`Identity check HTTP ${r.status}`);const n=await r.json();if(Ge.userId=n.user_id,Ge.token=n.identity_token||null,Ge.status=n.status,Ge.resolved=!0,sessionStorage.setItem(bm,n.user_id),Ge.token&&sessionStorage.setItem(Em,Ge.token),n.usage_count!==void 0){const i=At(),a=(n.usage_month||i)===i?n.usage_count:0;localStorage.setItem(Gt,JSON.stringify({count:a,month:i})),Xs()}console.log(`Identity resolved: ${n.status} (${n.user_id.slice(0,8)}...) usage: ${n.usage_count??"n/a"}`)}catch(t){console.error("resolveIdentity failed:",t)}}let Pi=null;function Nv(t=5e3){return Ge.resolved?Promise.resolve():(Pi||(Pi=Yd().catch(e=>{console.warn("ensureIdentityReady: identity resolution failed",e)})),Promise.race([Pi,new Promise(e=>setTimeout(e,t))]))}function Zd(){const t=At();try{const e=localStorage.getItem(Gt);return e?JSON.parse(e):{count:0,month:t}}catch(e){return console.warn("getUsageData: failed to parse usage storage",{key:Gt,month:t,err:e}),localStorage.removeItem(Gt),{count:0,month:t}}}function At(){const t=new Date;return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}`}function Vn(){const t=Zd();return t.month!==At()?{count:0,month:At()}:t}function Mv(){const e={count:Vn().count+1,month:At()};return localStorage.setItem(Gt,JSON.stringify(e)),e}function Fa(){return!!fe.isLoading}function Jt(){return!!fe.isResolved}function Lv(t){if(!t)return null;const e=String(t).toLowerCase().replace(/[^a-z0-9]+/g,"_");return e==="pro"||e==="professional_plan"?"professional":e==="power_developer"||e==="power_plan"?"power":Object.prototype.hasOwnProperty.call(yn,e)?e:null}function Ov(t){return t&&Object.entries(Ad).find(([,e])=>e===t)?.[0]||null}function $r(...t){return t.find(e=>e!=null&&e!=="")}function Dv(...t){return t.find(e=>e&&typeof e=="object")||{}}function Bv(t){const e=t.data&&typeof t.data=="object"?t.data:t,s=Dv(e.subscription,e.stripeSubscription,e.currentSubscription,e.customer?.subscriptions?.data?.[0],e.subscriptions?.data?.[0],e.subscriptions?.[0]),r=e.metadata||s.metadata||e.customer?.metadata||{},n=$r(e.priceId,e.price_id,e.stripePriceId,e.stripe_price_id,s.priceId,s.price_id,s.plan?.id,s.price?.id,s.items?.data?.[0]?.price?.id,s.items?.[0]?.price?.id,s.lines?.data?.[0]?.price?.id),i=$r(e.status,e.subscriptionStatus,e.subscription_status,s.status,"none"),o=Lv($r(e.tier,e.plan,e.planId,e.plan_id,e.subscriptionTier,e.subscription_tier,e.product,e.productName,s.tier,s.plan,r.tier,r.plan)),a=xm.has(String(i).toLowerCase()),l=e.active===!0||e.isSubscribed===!0||e.subscribed===!0||e.hasSubscription===!0,u=o||Ov(n)||(a||l?"professional":"free");return bs({tier:u,status:i,periodEnd:$r(e.periodEnd,e.currentPeriodEnd,e.current_period_end,s.current_period_end,s.periodEnd,null),isResolved:!0})}function Pa(){return yn[fe.tier]??yn.free}async function jv(){if(G.isVerified&&(!Jt()||Fa())&&(await Xd({force:!0}),Gn()),G.isVerified&&!Jt())return ue("Could not verify your subscription. Please refresh or try Manage billing.","error"),!1;const{count:t}=Vn(),e=Pa();if(t>=e)return Aa(t,e,{openModal:!0}),!1;const s=Math.floor(e*.8);if(t>=s){const r=e-t;ue(`${r} run${r===1?"":"s"} remaining this month.`,"warning")}return!0}function Ai(){const t=document.getElementById("paywall-exhausted");t&&t.classList.add("hidden")}function Aa(t,e,s={}){const r=document.getElementById("walkthrough-modal");r&&r.classList.remove("open");const n=document.getElementById("ready-state");n&&n.classList.add("hidden");const i=document.getElementById("preview-frame-container");i&&(i.style.display="none");const o=document.getElementById("main-stage-container");o&&o.classList.add("visible");const a=document.getElementById("results-view");a&&a.classList.remove("visible"),document.body.classList.remove("results-fullscreen","results-with-sidebar");const l=document.getElementById("pipeline-progress");l&&l.classList.remove("visible");const u=document.getElementById("paywall-exhausted");if(!u){ue(`You've used all ${e} runs for this month. Upgrade to continue.`,"error"),Cn();return}const c=document.getElementById("paywall-exhausted-text");if(c){const h=fe.tier;h==="free"?c.textContent=`You've used all ${e} free generations this month. Upgrade to Pro for 50 generations/month and access to all AI models.`:c.textContent=`You've used all ${e} generations this month on your ${h} plan. Your limit resets next month.`}const d=document.getElementById("paywall-signin-btn");d&&d.classList.toggle("hidden",G.isVerified),u.classList.remove("hidden"),s.openModal&&Cn()}function $o(t){return fe.tier==="free"&&jr.includes(t)?lr:t}function Uv(){const t=document.getElementById("code-options-content"),e=document.getElementById("code-generator-model");if(!t||!e)return;const s=fe.tier,n=!(G.isVerified&&!Jt())&&s==="free";Array.from(e.options).forEach(o=>{const a=zt(o.value),l=jr.includes(o.value);o.textContent=l&&n?`${a} (PRO)`:a,o.disabled=!1}),n&&jr.includes(e.value)&&(e.value=lr),e.disabled=!1,dc.has(e)||(e.addEventListener("change",()=>{Jt()&&fe.tier==="free"&&jr.includes(e.value)&&(e.value=lr,Cn()),Po(e.value),Rd()}),dc.add(e));let i=document.getElementById("model-selector-free-notice");n?(i||(i=document.createElement("p"),i.id="model-selector-free-notice",i.className="text-xs text-gray-400 mt-1",t.appendChild(i)),i.innerHTML='Free plan — Gemini only. '):i&&i.remove(),Po(e.value)}function Xs(){const t=document.getElementById("usage-counter");if(!t)return;if(G.isVerified&&Fa()){t.textContent="Checking plan…",t.className="text-xs text-gray-500",zr(),Ai();return}if(G.isVerified&&!Jt()){t.textContent="Plan check failed",t.className="text-xs text-red-600 font-medium",zr(),Ai();return}const{count:e}=Vn(),s=Pa();t.textContent=`${e} / ${s} runs this month`;const r=s>0?e/s:0;t.className=r>=1?"text-xs text-red-600 font-medium":r>=.8?"text-xs text-yellow-600 font-medium":"text-xs text-gray-500",zr(),e>=s&&!y.isRunning?Aa(e,s):Ai()}function zr(){const t=document.getElementById("guest-usage-text");if(!t)return;const e=Zd(),s=e.month===At()?e.count??0:0,r=yn.free;t.textContent=`${s} / ${r} generations used`}async function Xd(t={}){const e=t.force===!0;if(!G.isVerified||!G.sessionToken){fe=bs({isResolved:!0});return}fe={...fe,isLoading:!0,error:null};const s=localStorage.getItem(wn);if(!e&&s)try{const{data:r,email:n,ts:i,version:o}=JSON.parse(s);if(o===hc&&n===G.email&&Date.now()-i<300*1e3){fe={...r,isLoading:!1,isResolved:r.isResolved!==!1};return}}catch(r){console.warn("Failed to parse subscription cache:",r,"| raw value:",s)}try{const n=await(await fetch(`${Je}/stripe/get-subscription`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionToken:G.sessionToken,user_id:Ge.userId})})).json();if(n.error){if(["unauthorized","invalid session","expired session"].some(o=>String(n.error).toLowerCase().includes(o))){ka(),Ca();return}fe=bs({isResolved:!1,error:n.error});return}fe=Bv(n),localStorage.setItem(wn,JSON.stringify({version:hc,data:fe,email:G.email,ts:Date.now()}))}catch(r){console.error("fetchSubscription failed:",r),fe={...fe,isLoading:!1,isResolved:!1,error:r.message}}}function $a(){localStorage.removeItem(wn)}async function Hv(t){if(!G.isVerified||!G.sessionToken){Qd(),Ia();return}if(!Ad[t]){ue("Invalid plan selected.","error");return}const e=document.getElementById(`checkout-btn-${t}`);e&&(e.disabled=!0,e.textContent="Redirecting…");try{const r=await(await fetch(`${Je}/stripe/create-checkout-session-intl`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({tierId:t,sessionToken:G.sessionToken,currency:Md()})})).json();if(r.error||!r.url)throw new Error(r.error||"Failed to create checkout session");const{url:n}=r;window.location.href=n}catch(s){console.error("startCheckout failed:",s),e&&(e.disabled=!1,e.textContent="Subscribe"),ue("Could not start checkout. Please try again.","error")}}async function Wv(){if(!G.isVerified||!G.sessionToken){Ia();return}const t=document.getElementById("manage-billing-btn");t&&(t.disabled=!0,t.textContent="Loading…");try{const s=await(await fetch(`${Je}/stripe/create-portal-session`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionToken:G.sessionToken})})).json();if(s.error||!s.url)throw new Error(s.error||"Failed to open billing portal");const{url:r}=s;window.location.href=r}catch(e){console.error("openCustomerPortal failed:",e),t&&(t.disabled=!1,t.textContent="Manage billing"),ue("Could not open billing portal. Please try again.","error")}}async function In(t,e,s,r={},n=[]){const o=new AbortController,a=setTimeout(()=>o.abort(),12e4);try{const l=await fetch(wm,{method:"POST",headers:{"Content-Type":"application/json",...Ge.token?{Authorization:`Bearer ${Ge.token}`}:{}},signal:o.signal,body:JSON.stringify({user_id:Ge.userId,step:t,model:e,prompt:s,images:n,context:r})}),u=await l.text();let c={};try{c=u?JSON.parse(u):{}}catch{c={}}if(l.status===429){c.serverCount!==void 0&&(localStorage.setItem(Gt,JSON.stringify({count:c.serverCount,month:At()})),Xs());const p=new Error(c.message||"Monthly usage limit reached. Upgrade to continue.");throw p.isUsageLimit=!0,p}const d=qf(c,t);if(d)throw d;if(console.log(`[BuildShip] ${t} response keys:`,Object.keys(c),"content type:",typeof c.content),!l.ok)throw new Error(`${c.message||c.error||"BuildShip pipeline error"} (HTTP ${l.status})`);if(t==="generator")if(c.usage_status==="success"&&Number.isFinite(c.usage_count)){const p=At();(c.usage_month||p)===p&&(localStorage.setItem(Gt,JSON.stringify({count:c.usage_count,month:p})),Xs())}else Mv(),Xs();let h=c.output||c.content;if(!h){const p=u?` (body: ${u.slice(0,120)})`:"";throw new Error(`BuildShip returned no output for step "${t}"${p}`)}return Array.isArray(h)&&(h=h.map(p=>typeof p=="string"?p:p.text||"").join("")),typeof h!="string"&&(h=JSON.stringify(h)),h}catch(l){throw l.name==="AbortError"?new Error(`BuildShip ${t} timed out after ${12e4/1e3}s`):l instanceof TypeError?new Error(`BuildShip unreachable: ${l.message}`):l}finally{clearTimeout(a)}}function zv(){const e=new URLSearchParams(window.location.search).get("checkout");e==="success"?(window.history.replaceState({},"",window.location.pathname),$a(),ue("Subscription active! Welcome aboard.","success")):e==="cancel"&&(window.history.replaceState({},"",window.location.pathname),ue("Checkout cancelled.","info"))}function Gn(){const t=G.isVerified&&!!G.email,e=fe.tier,s=t&&Fa(),r=!t||Jt(),n=document.getElementById("subscription-tier-badge");if(n){const a={free:"Free",professional:"Professional",power:"Power Developer"},l={free:"bg-gray-100 text-gray-600",professional:"bg-indigo-100 text-indigo-700",power:"bg-purple-100 text-purple-700",unresolved:"bg-red-50 text-red-600"};n.textContent=s?"Checking…":r?a[e]||"Free":"Plan unavailable",n.className=`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${r?l[e]||l.free:l.unresolved}`}const i=document.getElementById("upgrade-prompt");i&&i.classList.toggle("hidden",!t||s||!r||e!=="free");const o=document.getElementById("manage-billing-btn");o&&o.classList.toggle("hidden",!t||s||r&&e==="free"),qv(r?e:null),Uv(),Rd(),Xs()}function qv(t){const e=["bg-gray-100","text-gray-500","cursor-default"];Object.entries({professional:{btnId:"checkout-btn-professional",defaultText:"Subscribe"},power:{btnId:"checkout-btn-power",defaultText:"Subscribe"}}).forEach(([n,{btnId:i,defaultText:o}])=>{const a=document.getElementById(i);a&&(n===t?(a.disabled=!0,a.textContent="Current plan",a.classList.add(...e)):(a.disabled=!1,a.textContent=o,a.classList.remove(...e)))});const r=document.getElementById("free-tier-current");r&&r.classList.toggle("hidden",t!=="free")}function Ro(){const t=Md(),e=document.getElementById("pro-price"),s=document.getElementById("power-price"),r=document.getElementById("pro-price-note"),n=document.getElementById("power-price-note");e&&(e.textContent=fc(pc.professional,t)),s&&(s.textContent=fc(pc.power,t));const i="billed monthly";r&&(r.textContent=i),n&&(n.textContent=i)}function Cn(){Ro();const t=document.getElementById("pricing-modal");t&&t.classList.add("open"),Tm().then(()=>Ro())}function Qd(t){if(t&&t.target!==t.currentTarget)return;const e=document.getElementById("pricing-modal");e&&e.classList.remove("open")}function ue(t,e="info"){const s={success:"bg-green-600 text-white",error:"bg-red-600 text-white",warning:"bg-amber-500 text-white",info:"bg-gray-800 text-white"},r=document.createElement("div");r.className=`fixed bottom-6 left-1/2 -translate-x-1/2 px-5 py-3 rounded-lg text-sm font-medium shadow-lg z-50 transition-opacity duration-300 ${s[e]||s.info}`,r.textContent=t,document.body.appendChild(r),setTimeout(()=>{r.style.opacity="0",setTimeout(()=>r.remove(),300)},3500)}document.addEventListener("DOMContentLoaded",async()=>{hljs.configure({tabReplace:" ",classPrefix:"hljs-"}),Vv(),await Av(),zv(),await Xd(),Gn(),Ro(),await nv(),Qm();const t=document.getElementById("flutterflow-endpoint-select");if(t){const s=fr();t.value=s}Ud(),Yd();const e=document.getElementById("pipeline-input");e&&(e.addEventListener("input",()=>{Et===2&&e.value.trim().length>0&&(pa(),Dn())}),e.addEventListener("blur",()=>{const s=document.getElementById("walkthrough-modal");Et===2&&s&&s.classList.add("open")}),e.addEventListener("keydown",s=>{if(s.key==="Tab"){const r=document.getElementById("walkthrough-modal");Et===2&&r&&setTimeout(()=>{r.classList.add("open")},100)}})),window.addEventListener("commitStateChange",s=>{const{state:r}=s.detail;r===V.PREPARING||r===V.VALIDATING||r===V.PUSHING?(be.phaseId||sh(),Sc(r)):(r===V.SUCCESS||r===V.ERROR)&&(Sc(r),setTimeout(Fn,1e3))})});function Vv(){const t=document.getElementById("preview-frame-container");t&&(t.style.display="")}function Gv(){const t=document.getElementById("welcome-video-player");t&&(t.addEventListener("click",Yt),document.addEventListener("keydown",Yt))}function Yt(){const t=document.getElementById("preview-frame-container"),e=document.getElementById("main-stage-container"),s=document.getElementById("ready-state");t&&(t.style.display="none"),e&&e.classList.add("visible"),s&&s.classList.remove("hidden");const r=document.getElementById("welcome-video-player");r&&r.removeEventListener("click",Yt),document.removeEventListener("keydown",Yt),Ud()}let Qs=null;async function Kv(){const t=document.getElementById("confirm-project-select");if(!t)return;const e=++yc,s=()=>e===yc,r=await Ee("flutterflow"),n=await Ee("flutterflow_project_id");if(s()){if(!r){t.innerHTML='',t.disabled=!0;return}t.disabled=!1,t.innerHTML='';try{const o=await new gr(r,"").listProjects();if(!s())return;if(!o||o.length===0){t.innerHTML='';return}t.innerHTML='',o.forEach(a=>{const l=document.createElement("option");l.value=a.id||a.projectId||"",l.textContent=a.name||a.projectName||`Project ${a.id}`,t.appendChild(l)}),n&&(t.value=n)}catch(i){if(!s())return;console.error("Failed to load projects for deploy:",i),t.innerHTML=''}}}function Jv(){return document.getElementById("confirm-project-select")?.value?.trim()||null}function eh(t,e,s,r=null){Qs={codeInfo:t,checks:e,deps:s,bundlePlan:r},document.getElementById("confirm-file-name").textContent=t.fileName,document.getElementById("confirm-artifact-type").textContent=t.artifactType,document.getElementById("confirm-file-size").textContent=`${(t.content.length/1024).toFixed(1)} KB`,document.getElementById("confirm-line-count").textContent=r?`${r.fileEntries.length} files`:t.content.split(` -`).length,Kv();const n=document.getElementById("confirm-deps-list"),i=document.getElementById("confirm-deps-section");s&&Object.keys(s).length>0?(n.innerHTML=Object.entries(s).map(([u,c])=>{const d=c?`at least ${bt(c)}`:"version resolved from your project";return`
  • • ${bt(u)}: ${d}
  • `}).join(""),i.classList.remove("hidden")):i.classList.add("hidden");const o=document.getElementById("confirm-warnings-list"),a=document.getElementById("confirm-warnings-section");e.warnings&&e.warnings.length>0?(o.innerHTML=e.warnings.map(u=>`
  • • ${bt(u)}
  • `).join(""),a.classList.remove("hidden")):a.classList.add("hidden"),document.getElementById("confirm-code-preview").textContent=t.content,document.getElementById("code-preview-content").classList.add("hidden"),document.getElementById("code-preview-chevron").style.transform="rotate(0deg)";const l=document.getElementById("commit-confirm-modal");l&&l.classList.add("open")}function th(t){if(t&&t.target!==t.currentTarget)return;const e=document.getElementById("commit-confirm-modal");e&&e.classList.remove("open"),Qs=null}function Yv(t){if(t&&t.target!==t.currentTarget)return;const e=document.getElementById("commit-success-modal");e&&e.classList.remove("open");const s=["success-message","success-project-id","success-file-name","success-artifact-type","success-time","success-size"];for(const i of s){const o=document.getElementById(i);o&&(o.textContent="")}const r=document.getElementById("success-warnings-section");r&&r.classList.add("hidden");const n=document.getElementById("success-warnings-list");n&&(n.innerHTML="")}function To(t){const e=(g,m)=>{const _=document.getElementById(g);_&&(_.textContent=m||"")},s=t.metadata?.fileName||"",r=t.metadata?.projectId||"",n=t.metadata?.artifactType||"",i=t.elapsedTime?`${(t.elapsedTime/1e3).toFixed(1)}s`:"",o=t.metadata?.codeSize?`${(t.metadata.codeSize/1024).toFixed(1)} KB`:"";e("success-message",t.message||"Code committed successfully!"),e("success-project-id",r),e("success-file-name",s),e("success-artifact-type",n),e("success-time",i),e("success-size",o);const a=t.addedDependencies||[],l=document.getElementById("success-deps-row");l&&l.classList.toggle("hidden",a.length===0),e("success-deps",a.join(", "));const u=document.getElementById("success-open-ff-link");u&&r&&(u.href=`https://app.flutterflow.io/project/${r}`);const c=document.getElementById("success-warnings-section"),d=document.getElementById("success-warnings-list"),h=t.unverified||[],p=t.warnings||[];(p.length>0||h.length>0)&&c&&d&&(d.innerHTML=[...h.map(g=>`
  • Not verified before deploying: ${j(String(g))}
  • `),...p.map(([g,m])=>`
  • ${j(g)}: ${j(String(m))}
  • `)].join(""),c.classList.remove("hidden"));const f=document.getElementById("commit-success-modal");f&&f.classList.add("open")}function No(t){Fn(),xv(t)}function Zv(){const t=document.getElementById("code-preview-content"),e=document.getElementById("code-preview-chevron");t.classList.contains("hidden")?(t.classList.remove("hidden"),e.style.transform="rotate(90deg)"):(t.classList.add("hidden"),e.style.transform="rotate(0deg)")}const Ec={prepare:{message:"Preparing your code...",start:4,end:14},validate:{message:"Checking FlutterFlow credentials...",start:14,end:22},project:{message:"Reading your FlutterFlow project...",start:22,end:40},provision:{message:"Creating custom classes in FlutterFlow...",start:40,end:82},package:{message:"Packaging files for upload...",start:82,end:88},push:{message:"Pushing to FlutterFlow...",start:88,end:97},done:{message:"Complete!",start:100,end:100}},Xv=[{after:0,text:"Starting a FlutterFlow build runner..."},{after:12,text:"Preparing the FlutterFlow AI workspace..."},{after:35,text:"Uploading your custom classes..."},{after:60,text:"FlutterFlow is applying the changes..."},{after:100,text:"Still working — this can take a couple of minutes..."}],be={sequence:[],phaseId:null,phaseStartedAt:null,timer:null,substatus:null,liveSubstatus:!1,start({withProvisioning:t=!1}={}){this.sequence=["prepare","validate","project"],t&&this.sequence.push("provision"),this.sequence.push("package","push","done");const e=document.getElementById("commit-progress-overlay");e&&e.classList.add("open"),this.set("prepare")},set(t,e=null){if(!(!Ec[t]||t===this.phaseId)){if(!this.sequence.includes(t)){const s=this.sequence.indexOf("package");this.sequence.splice(s===-1?this.sequence.length:s,0,t)}this.phaseId=t,this.phaseStartedAt=Date.now(),this.substatus=e,this.liveSubstatus=!1,this.render(),this.timer&&clearInterval(this.timer),t!=="done"&&(this.timer=setInterval(()=>this.render(),500))}},setSubstatus(t){t&&(this.liveSubstatus=!0,this.substatus=t,this.render())},render(){const t=Ec[this.phaseId];if(!t)return;const e=(Date.now()-this.phaseStartedAt)/1e3,s=t.start+(t.end-t.start)*(1-Math.exp(-e/25));if(this.phaseId==="provision"&&!this.liveSubstatus){const o=Xv.filter(a=>e>=a.after).pop();o&&(this.substatus=o.text)}const r=this.sequence.indexOf(this.phaseId),i=[`Step ${r===-1?1:r+1} of ${this.sequence.length}`];e>=5&&i.push(Qv(e)),rh(this.phaseId==="done"?100:s,t.message,i.join(" · "),this.substatus)},stop(){this.timer&&clearInterval(this.timer),this.timer=null,this.phaseId=null;const t=document.getElementById("commit-progress-overlay");t&&t.classList.remove("open")}};function Qv(t){const e=Math.floor(t);return e<60?`${e}s elapsed`:`${Math.floor(e/60)}m ${String(e%60).padStart(2,"0")}s elapsed`}function sh(t){be.start(t)}function Fn(){be.stop()}function rh(t,e,s,r=null){const n=document.getElementById("commit-progress-bar"),i=document.getElementById("progress-message"),o=document.getElementById("progress-detail"),a=document.getElementById("progress-substatus");n&&(n.style.width=`${Math.round(t*10)/10}%`),i&&(i.textContent=e),o&&(o.textContent=s),a&&(a.textContent=r||"",a.classList.toggle("hidden",!r))}function Sc(t){const e={[V.PREPARING]:"prepare",[V.VALIDATING]:"validate",[V.PUSHING]:"project",[V.SUCCESS]:"done"};if(t===V.ERROR){be.timer&&clearInterval(be.timer),be.timer=null,rh(100,"Failed","Error occurred");return}const s=e[t];s&&be.set(s)}function e_(t){return t.bundlePlan?t.bundlePlan.fileEntries.some(e=>e.type===U.CODE_FILE):t.codeInfo?.codeType===U.CODE_FILE}async function t_(){if(!Qs){console.error("No pending commit data");return}const t=Qs;if(Qs=null,Zs=Jv(),th(),sh({withProvisioning:e_(t)}),t.bundlePlan){const o=await pv(t.bundlePlan,{pipelineResult:{step1Result:y.step1Result,selectedModel:document.getElementById("code-generator-model")?.value}});Zs=null,Fn(),o.success?To(o):No(o);return}const{codeInfo:e}=t,{artifactType:s,artifactName:r,fileName:n}=Wd(),i=await hv(e.content,{artifactType:s,artifactName:r,fileName:n,pipelineResult:{step1Result:y.step1Result,selectedModel:document.getElementById("code-generator-model")?.value}});Zs=null,Fn(),i.success?To(i):No(i)}window.runThinkingPipeline=Ao;window.toggleStep=mv;window.toggleSection=gv;window.selectWorkflowStep=ze;window.copyCode=vv;window.retryWithDifferentModel=bv;window.openApiKeysModal=ha;window.closeApiKeysModal=Bd;window.closeWalkthroughModal=Gm;window.openWalkthroughModal=Vm;window.advanceWalkthrough=pa;window.commitToFlutterFlow=dv;function s_(){const t=document.getElementById("pipeline-input");t&&t.focus()}function r_(){const t=document.getElementById("advanced-settings");t&&(t.open=!0);const e=document.getElementById("code-generator-model");e&&(e.scrollIntoView({behavior:"smooth",block:"center"}),e.focus(),e.click())}window.focusPromptInput=s_;window.openModelSelector=r_;window.handlePromptImageSelect=$m;window.removePromptImage=Rm;window.saveApiKeys=Ym;window.clearAllApiKeys=Zm;window.toggleKeyVisibility=tv;window.handleWelcomeVideoEnd=Gv;window.dismissWelcomeVideo=Yt;window.initiateCommitToFlutterFlow=Ev;window.updateFlutterFlowCredentialStatus=Iv;window.closeCommitConfirmModal=th;window.closeCommitSuccessModal=Yv;window.showCommitSuccessModal=To;window.showCommitFailureModal=No;window.toggleCodePreview=Zv;window.confirmCommitToFlutterFlow=t_;window.runRefinement=_v;window.regenerateFromPastedErrors=wv;window.clearErrorInput=yv;window.setFlutterFlowEndpoint=qm;window.getFlutterFlowEndpoint=fr;window.commitProgress=be;window.openSignInModal=Ia;window.closeSignInModal=$v;window.handleMagicLinkRequest=Rv;window.handleSignOut=Tv;window.startCheckout=Hv;window.openCustomerPortal=Wv;window.openPricingModal=Cn;window.closePricingModal=Qd;let hs=null,nh=null;const xc=120;function Kn(){const t=document.getElementById("pipeline-progress"),e=document.getElementById("results-view"),s=document.getElementById("ready-state");s&&s.classList.add("hidden"),e&&e.classList.remove("visible"),document.body.classList.remove("results-fullscreen","results-with-sidebar"),t&&t.classList.add("visible"),nh=Date.now();for(let r=1;r<=3;r++){const n=document.getElementById(`pdot-${r}`);n&&(n.className="progress-dot")}nt(1),n_()}function nt(t){const e={1:"Analyzing your prompt...",2:"Generating Dart code...",3:"Running code audit..."},s={1:"Step 1 of 3 — Prompt Architect",2:"Step 2 of 3 — Code Generator",3:"Step 3 of 3 — Code Review"},r=document.getElementById("progress-title-text"),n=document.getElementById("progress-substep-text");r&&(r.textContent=e[t]||e[1]),n&&(n.textContent=s[t]||s[1]);for(let i=1;i<=3;i++){const o=document.getElementById(`pdot-${i}`);o&&(i{const t=(Date.now()-nh)/1e3,e=document.getElementById("progress-elapsed"),s=document.getElementById("pipeline-progress-fill");e&&(e.textContent=`${Math.floor(t)}s`);const r=t/xc*100,n=Math.min(95,r*(1-Math.exp(-t/(xc*.6)))*1.2);s&&(s.style.width=`${n}%`)},250)}function $t(){hs&&(clearInterval(hs),hs=null);const t=document.getElementById("pipeline-progress-fill");t&&(t.style.width="100%");for(let e=1;e<=3;e++){const s=document.getElementById(`pdot-${e}`);s&&(s.className="progress-dot completed")}setTimeout(()=>{const e=document.getElementById("pipeline-progress");e&&e.classList.remove("visible"),t&&(t.style.width="0%")},400)}function Ss(t,e=""){const s={pass:'',warning:'',fail:'',info:''};return``}function ih(t){return{pass:"Passed review",warning:"Needs attention",fail:"Blocking issues"}[t]||"Needs attention"}function i_(){return Lg({bundle:y.artifactBundle,reviewResult:y.step3Result})}function o_(t){return` -
    - ${Ss(t.severity)} -
    -
    ${j(t.message)}
    - ${t.suggestion?`
    ${j(t.suggestion)}
    `:""} - ${j(t.source)} -
    -
    - `}function a_(t){return` -
  • -
    - ${j(t.title)} - ${t.detail&&t.detail!==t.title?`

    ${j(t.detail)}

    `:""} -
    -
  • - `}function l_(t){const e=document.getElementById("results-summary-detail"),s=document.getElementById("results-title");if(!e)return;s&&(s.textContent=t.title);const r=t.score,n=r==null?"neutral":r>=80?"pass":r>=60?"warning":"fail",i=r==null?"":r>=80?"Strong":r>=60?"Needs work":"High risk",o=t.findings.length?` -
      - ${t.findings.map(l=>` -
    • - ${Ss(l.severity)} - - ${j(l.message)} - ${l.suggestion?`${j(l.suggestion)}`:""} - -
    • - `).join("")} -
    - `:"",a=t.manualSteps.length?` -
    -

    ${Ss("info")} Complete in FlutterFlow

    -

    For your information — these don't block the deploy. Finish them by hand in the FlutterFlow editor once the code is pushed.

    -
      - ${t.manualSteps.map(l=>` -
    • - ${j(l.title)} - ${l.detail&&l.detail!==l.title?`${j(l.detail)}`:""} -
    • - `).join("")} -
    -
    - `:"";e.innerHTML=` -
    -
    -

    ${j(t.summary)}

    - ${o} - ${a} -
    -
    - -
    - Is the generated code correct? -
    - - -
    -
    -
    -
    - `}function c_(t){const e=t.artifacts.find(l=>l.id===y.selectedArtifactId)||t.artifacts[0];if(!e)return"";const s={pass:{icon:"pass",message:"No file-specific issues were found."},warning:{icon:"warning",message:"This file needs attention, but Code Review did not return a specific finding."},fail:{icon:"fail",message:"This file is blocked, but Code Review did not return a specific finding."}}[e.status],r=e.findings.length?e.findings.map(o_).join(""):`
    ${Ss(s.icon)} ${j(s.message)}
    `,n=e.dependencies?.length?e.dependencies.map(l=>` -
  • ${j(l.name)}${l.version?` ${j(l.version)}`:""}${l.reason?`

    ${j(l.reason)}

    `:""}
  • - `).join(""):'
  • No external packages
  • ',i=e.imports?.length?e.imports.map(l=>`${j(l)}`).join(""):'No imports returned',o=e.publicApi?.length?e.publicApi.map(l=>`${j(l)}`).join(""):'No public API signature returned',a=e.relationships.length?e.relationships.map(l=>` -
  • ${j(l.from||"Bundle")} ${j(l.type)} ${j(l.to||"Bundle")}${l.description?`

    ${j(l.description)}

    `:""}
  • - `).join(""):'
  • No relationships for this file
  • ';return` -
    -
    - ${Ss(e.status)} ${j(ih(e.status))} -

    ${j(e.artifactName)}

    - ${e.description?`

    ${j(e.description)}

    `:""} -
    -
    - ${j(e.artifactType)} - ${j(e.fileName)} -
    -
    -
    -

    Code Review findings

    - ${r} -
    - ${e.manualSteps.length?` -
    -

    Manual FlutterFlow steps for this file

    -
      ${e.manualSteps.map(a_).join("")}
    -
    - `:""} -
    - File details -
    -
    -

    Dependencies

    -
      ${n}
    -
    -
    -

    Deployment

    -
    -
    Status
    ${j(e.deployStatus||"pending")}
    -
    Order
    ${e.index+1} of ${t.artifacts.length}
    -
    Path hint
    ${j(e.pathHint||"Not returned")}
    -
    -
    -
    -
    -

    Public API

    -
    ${o}
    -
    -
    -

    Imports

    -
    ${i}
    -
    -
    -

    Relationships

    -
      ${a}
    -
    -
    - `}function u_(t){const e=document.getElementById("bundle-strip"),s=document.getElementById("results-summary-tab"),r=document.getElementById("artifact-tabs"),n=document.getElementById("results-file-count");if(s&&s.classList.toggle("active",y.resultsViewMode==="summary"),!t.artifacts.length){n&&(n.textContent="0 files"),e&&e.classList.remove("visible"),r&&(r.innerHTML="");return}if(n){const i=t.artifacts.length;n.textContent=`${i} ${i===1?"file":"files"}`}r&&(r.innerHTML=t.artifacts.map(i=>` - - `).join(""),r.onclick=i=>{const o=i.target.closest(".artifact-tab");o?.dataset?.artifactId&&oh(o.dataset.artifactId)}),e&&e.classList.add("visible")}function Ra(){document.body.classList.add("results-fullscreen"),document.body.classList.add("results-with-sidebar");const t=document.getElementById("results-view"),e=document.getElementById("results-code-output"),s=document.getElementById("results-audit-output"),r=document.getElementById("results-summary-detail"),n=document.getElementById("artifact-results-split"),i=i_(),o=ma();if(l_(i),u_(i),e&&(e.textContent=""),e){const a=Pd(o);e.innerHTML=a}s&&(s.innerHTML=c_(i)),r&&r.classList.toggle("hidden",y.resultsViewMode!=="summary"),n&&n.classList.toggle("hidden",y.resultsViewMode!=="file"),t&&t.classList.add("visible")}function Jn(t,e){y.selectedArtifactId||(y.selectedArtifactId=gn(y.artifactBundle).id),y.resultsViewMode="summary",document.body.classList.add("results-fullscreen");const s=document.getElementById("step3-output");s&&(s.textContent=""),Ra(),Zt();const r=document.getElementById("btn-feedback-up"),n=document.getElementById("btn-feedback-down");r&&(r.className="feedback-btn"),n&&(n.className="feedback-btn")}function oh(t){y.selectedArtifactId=t,y.resultsViewMode="file",Ra()}function d_(){y.resultsViewMode="summary",Ra()}function h_(){const t=document.getElementById("btn-copy-results"),e=ma();navigator.clipboard.writeText(e).then(()=>{if(t){t.classList.add("copied");const s=t.querySelector("span");if(s){const r=s.textContent;s.textContent="Copied!",setTimeout(()=>{t.classList.remove("copied"),s.textContent=r},2e3)}}})}function p_(t){const e=document.getElementById("btn-feedback-up"),s=document.getElementById("btn-feedback-down");t==="up"?(e.classList.toggle("active-up"),s.classList.remove("active-down")):(s.classList.toggle("active-down"),e.classList.remove("active-up")),xa(t==="up"?"thumbsUp":"thumbsDown",y.step2Result,y.step1Result)}function f_(){const t=document.getElementById("error-input-panel");if(t){t.classList.remove("hidden"),t.style.display="flex";const e=document.getElementById("ff-error-paste-input");e&&setTimeout(()=>e.focus(),100)}}function ah(){const t=document.getElementById("error-input-panel");t&&(t.classList.add("hidden"),t.style.display="none")}window.copyResultsCode=h_;window.selectArtifact=oh;window.selectResultsSummary=d_;window.submitResultsFeedback=p_;window.showErrorInputPanel=f_;window.hideErrorInputPanel=ah; diff --git a/dist/assets/index-CrZGgSTH.js b/dist/assets/index-CrZGgSTH.js new file mode 100644 index 0000000..a9ff094 --- /dev/null +++ b/dist/assets/index-CrZGgSTH.js @@ -0,0 +1,328 @@ +(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))i(r);new MutationObserver(r=>{for(const s of r)if(s.type==="childList")for(const o of s.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&i(o)}).observe(document,{childList:!0,subtree:!0});function n(r){const s={};return r.integrity&&(s.integrity=r.integrity),r.referrerPolicy&&(s.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?s.credentials="include":r.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function i(r){if(r.ep)return;r.ep=!0;const s=n(r);fetch(r.href,s)}})();var w=typeof window<"u"?window:void 0,je=typeof globalThis<"u"?globalThis:w,Ve=je?.navigator,F=je?.document,Ee=je?.location,Sl=je?.fetch,fa=je!=null&&je.XMLHttpRequest&&"withCredentials"in new je.XMLHttpRequest?je.XMLHttpRequest:void 0,jc=je?.AbortController,Eg=je?.CompressionStream,Qe=Ve?.userAgent;function Wd(){return!(!w||w.navigator.onLine===!1)}var Fi=typeof globalThis<"u"?globalThis:w;Fi&&typeof self>"u"&&(Fi.self=Fi),Fi&&typeof File>"u"&&(Fi.File=function(){});var B=w??{},oe={DEBUG:!1,LIB_VERSION:"0.5.0",LIB_NAME:"browser-common"};function Uc(t,e,n,i,r,s,o){try{var a=t[s](o),l=a.value}catch(u){return void n(u)}a.done?e(l):Promise.resolve(l).then(i,r)}function ce(t){return function(){var e=this,n=arguments;return new Promise((function(i,r){var s=t.apply(e,n);function o(l){Uc(s,i,r,o,a,"next",l)}function a(l){Uc(s,i,r,o,a,"throw",l)}o(void 0)}))}}function k(){return k=Object.assign?Object.assign.bind():function(t){for(var e=1;arguments.length>e;e++){var n=arguments[e];for(var i in n)({}).hasOwnProperty.call(n,i)&&(t[i]=n[i])}return t},k.apply(null,arguments)}function qd(t,e){if(t==null)return{};var n={};for(var i in t)if({}.hasOwnProperty.call(t,i)){if(e.indexOf(i)!==-1)continue;n[i]=t[i]}return n}var Hc=t=>{if(typeof t!="string")return t;try{return JSON.parse(t)}catch{return t}};function Wc(t){return typeof t=="string"||t}function qc(t){return typeof t=="string"?t:void 0}var Ri,Sg=["$feature_flag","$feature_flag_response","$feature_flag_has_experiment","$feature_flag_id","$feature_flag_version","$feature_flag_reason","$feature_flag_request_id","$feature_flag_evaluated_at","$feature_flag_error","locally_evaluated","$groups","$process_person_profile","$geoip_disable","$current_url","$pathname","$referring_domain","utm_source","utm_medium","utm_campaign","utm_content","utm_term","gad_source","mc_cid","gclid","gclsrc","dclid","gbraid","wbraid","fbclid","msclkid","twclid","li_fat_id","igshid","ttclid","rdt_cid","epik","qclid","sccid","irclid","_kx","$session_id","$window_id","$lib","$lib_version","$device_id","$is_server"],Zt=(function(t){return t.AnonymousId="anonymous_id",t.DistinctId="distinct_id",t.Props="props",t.EnablePersonProcessing="enable_person_processing",t.PersonMode="person_mode",t.FeatureFlagDetails="feature_flag_details",t.FeatureFlags="feature_flags",t.FeatureFlagPayloads="feature_flag_payloads",t.BootstrapFeatureFlagDetails="bootstrap_feature_flag_details",t.BootstrapFeatureFlags="bootstrap_feature_flags",t.BootstrapFeatureFlagPayloads="bootstrap_feature_flag_payloads",t.OverrideFeatureFlags="override_feature_flags",t.Queue="queue",t.AiQueue="ai_queue",t.LogsQueue="logs_queue",t.OptedOut="opted_out",t.SessionId="session_id",t.SessionStartTimestamp="session_start_timestamp",t.SessionLastTimestamp="session_timestamp",t.PersonProperties="person_properties",t.GroupProperties="group_properties",t.InstalledAppBuild="installed_app_build",t.InstalledAppVersion="installed_app_version",t.SessionReplay="session_replay",t.PushRegistered="push_registered",t.SessionReplayEventTriggerActivatedSession="session_replay_event_trigger_activated_session",t.SurveyLastSeenDate="survey_last_seen_date",t.SurveysSeen="surveys_seen",t.Surveys="surveys",t.RemoteConfig="remote_config",t.FlagsEndpointWasHit="flags_endpoint_was_hit",t.DeviceId="device_id",t})({}),zc=(function(t){return t.GZipJS="gzip-js",t.Base64="base64",t})({}),xg=["$snapshot","$pageview","$pageleave","$set","survey dismissed","survey sent","survey shown","$identify","$groupidentify","$create_alias","$$client_ingestion_warning","$web_experiment_applied","$feature_enrollment_update","$feature_flag_called"],Ig=["token"],zd="NativeGzipValidationError",ha=t=>t.length>=2&&t[0]===31&&t[1]===139,Vc=(t,e)=>t===zc.GZipJS||e===zc.GZipJS||e==="gzip",Gc=t=>!(!t||typeof t!="object")&&("name"in t?String(t.name):"")==="NotReadableError",$r=t=>{var e=new Error("Native gzip produced invalid output: "+t);throw e.name=zd,e},kg=(function(){var t=ce((function*(e,n){18>e.size&&$r("too-short");var i=new Uint8Array(yield e.slice(0,10).arrayBuffer());ha(i)&&i[2]===8||$r("invalid-header");var r=new DataView(yield e.slice(e.size-8).arrayBuffer());r.getUint32(0,!0)!==(o=>{for(var a=(()=>{if(Ri)return Ri;Ri=[];for(var c=0;256>c;c++){for(var d=c,f=0;8>f;f++)d=1&d?3988292384^d>>>1:d>>>1;Ri[c]=d>>>0}return Ri})(),l=4294967295,u=0;o.length>u;u++)l=a[255&(l^o[u])]^l>>>8;return(4294967295^l)>>>0})(n)&&$r("invalid-crc");var s=n.length>>>0;r.getUint32(4,!0)!==s&&$r("invalid-size")}));return function(e,n){return t.apply(this,arguments)}})();function pa(){return pa=ce((function*(t,e,n){e===void 0&&(e=!0);try{var i=new TextEncoder().encode(t),r=new globalThis.CompressionStream("gzip"),s=r.writable.getWriter(),o=s.write(i).then((()=>s.close())).catch((function(){var u=ce((function*(c){try{yield s.abort(c)}catch{}throw c}));return function(c){return u.apply(this,arguments)}})()),a=new Response(r.readable).blob(),l=(yield Promise.all([a,o]))[0];return yield kg(l,i),l}catch(u){if(n!=null&&n.rethrow)throw u;return e&&console.error("Failed to gzip compress data",u),null}})),pa.apply(this,arguments)}var Cg=["amazonbot","amazonproductbot","app.hypefactors.com","applebot","archive.org_bot","awariobot","backlinksextendedbot","baiduspider","bingbot","bingpreview","chrome-lighthouse","dataforseobot","deepscan","duckduckbot","facebookexternal","facebookcatalog","http://yandex.com/bots","hubspot","ia_archiver","leikibot","linkedinbot","meta-externalagent","mj12bot","msnbot","nessus","petalbot","pinterest","prerender","rogerbot","screaming frog","sebot-wa","sitebulb","slackbot","slurp","trendictionbot","turnitin","twitterbot","vercel-screenshot","vercelbot","yahoo! slurp","yandexbot","zoombot","bot.htm","bot.php","(bot;","bot/","crawler","ahrefsbot","ahrefssiteaudit","semrushbot","siteauditbot","splitsignalbot","gptbot","oai-searchbot","chatgpt-user","perplexitybot","better uptime bot","sentryuptimebot","uptimerobot","headlesschrome","cypress","google-hoteladsverifier","adsbot-google","apis-google","duplexweb-google","feedfetcher-google","google favicon","google web preview","google-read-aloud","googlebot","googleother","google-cloudvertexbot","googleweblight","mediapartners-google","storebot-google","google-inspectiontool","bytespider"],Kc=function(t,e){if(e===void 0&&(e=[]),!t)return!1;var n=t.toLowerCase();return Cg.concat(e).some((i=>{var r=i.toLowerCase();return n.indexOf(r)!==-1}))};function j(t,e){return t.indexOf(e)!==-1}var Ks=function(t){return t.trim()},ga=function(t){return t.replace(/^\$/,"")};function Vd(t){var e,n=[];return(e=JSON.stringify(t,(function(i,r){if(typeof r=="bigint")return r.toString();if(typeof r!="function"&&typeof r!="symbol"){if(r instanceof Error)return{name:r.name,message:r.message,stack:r.stack};if(r&&typeof r=="object"){for(;n.length>0&&n[n.length-1]!==this;)n.pop();if(n.includes(r))return"[Circular]";n.push(r)}return r}})))!==null&&e!==void 0?e:"null"}var Gd=Object.prototype,Kd=Gd.hasOwnProperty,Ys=Gd.toString,U=Array.isArray||function(t){return Ys.call(t)==="[object Array]"},qe=t=>typeof t=="function",ye=t=>t===Object(t)&&!U(t),an=t=>{if(ye(t)){for(var e in t)if(Kd.call(t,e))return!1;return!0}return!1},A=t=>t===void 0,X=t=>Ys.call(t)=="[object String]",ma=t=>X(t)&&t.trim().length===0,it=t=>t===null,q=t=>A(t)||it(t),Fe=t=>Ys.call(t)=="[object Number]"&&t==t,Yt=t=>Fe(t)&&t>0,kt=t=>Ys.call(t)==="[object Boolean]",Ag=t=>t instanceof FormData,Pg=t=>j(xg,t),Fg=t=>j(Ig,t);function Yd(t){return t===null||typeof t!="object"}function cs(t,e){return{}.toString.call(t)==="[object "+e+"]"}function xl(t){return typeof Event<"u"&&Jd(t,Event)}function Jd(t,e){try{return t instanceof e}catch{return!1}}var Rg=[!0,"true",1,"1","yes"],To=t=>j(Rg,t),Tg=[!1,"false",0,"0","no"];function Nt(t,e,n,i,r){return e>n&&(i.warn("min cannot be greater than max."),e=n),Fe(t)?t>n?(i.warn(" cannot be greater than max: "+n+". Using max value instead."),n):e>t?(i.warn(" cannot be less than min: "+e+". Using min value instead."),e):t:(i.warn(" must be a number. using max or fallback. max: "+n+", fallback: "+r),Nt(r||n,e,n,i))}class Mg{constructor(e){this.tt={},this.et=e.et,this.it=Nt(e.bucketSize,0,100,e.rt),this.nt=Nt(e.refillRate,0,this.it,e.rt),this.st=Nt(e.refillInterval,0,864e5,e.rt)}ot(e,n){var i=Math.floor((n-e.lastAccess)/this.st);i>0&&(e.tokens=Math.min(e.tokens+i*this.nt,this.it),e.lastAccess=e.lastAccess+i*this.st)}consumeRateLimit(e){var n,i=Date.now(),r=String(e),s=this.tt[r];return s?this.ot(s,i):this.tt[r]=s={tokens:this.it,lastAccess:i},s.tokens===0||(s.tokens--,s.tokens===0&&((n=this.et)==null||n.call(this,e)),s.tokens===0)}stop(){this.tt={}}}var ft="Mobile",us="iOS",ln="Android",hi="Tablet",Zd=ln+" "+hi,Xd="iPad",Qd="Apple",ef=Qd+" Watch",Zi="Safari",pi="BlackBerry",tf="Samsung",nf=tf+"Browser",rf=tf+" Internet",Hn="Chrome",$g=Hn+" OS",sf=Hn+" "+us,Il="Internet Explorer",of=Il+" "+ft,kl="Opera",Lg=kl+" Mini",Cl="Edge",af="Microsoft "+Cl,li="Firefox",lf=li+" "+us,or="Nintendo",ar="PlayStation",ci="Xbox",cf=ln+" "+ft,uf=ft+" "+Zi,Hi="Windows",va=Hi+" Phone",Yc="Nokia",ya="Ouya",df="Generic",Ng=df+" "+ft.toLowerCase(),ff=df+" "+hi.toLowerCase(),_a="Konqueror",hf="Oculus Browser",ds="Vivaldi",pf="Yandex",fs="Whale",wa="DuckDuckGo",gf="Pale Moon",hs="Waterfox",Xi="Brave",mf="Google Search App",ke="(\\d+(\\.\\d+)?)",Mo=new RegExp("Version/"+ke),Og=new RegExp(ci,"i"),Bg=new RegExp(ar+" \\w+","i"),Dg=new RegExp(or+" \\w+","i"),Al=new RegExp(pi+"|PlayBook|BB10","i"),jg={"NT3.51":"NT 3.11","NT4.0":"NT 4.0","5.0":"2000",5.1:"XP",5.2:"XP","6.0":"Vista",6.1:"7",6.2:"8",6.3:"8.1",6.4:"10","10.0":"10"},vf=function(t,e,n,i){e=e||"";var r=(function(s){return s!=null&&s.brave?Xi:null})(n);return r||(i!=null&&i.detectGoogleSearchApp&&j(t,"GSA/")?mf:j(t," OPR/")&&j(t,"Mini")?Lg:j(t," OPR/")?kl:Al.test(t)?pi:j(t,"IE"+ft)||j(t,"WPDesktop")?of:j(t,"OculusBrowser")?hf:j(t,nf)?rf:j(t,Cl)||j(t,"Edg/")?af:j(t,ds+"/")?ds:j(t,"YaBrowser/")?pf:j(t,fs+"/")?fs:j(t,wa+"/")||j(t,"Ddg/")?wa:j(t,"FBIOS")?"Facebook "+ft:j(t,"UCWEB")||j(t,"UCBrowser")?"UC Browser":j(t,"CriOS")?sf:j(t,"CrMo")||j(t,Hn)?Hn:j(t,ln)&&j(t,Zi)?cf:j(t,"FxiOS")?lf:j(t.toLowerCase(),_a.toLowerCase())?_a:j(t,Xi+"/")?Xi:((s,o)=>o&&j(o,Qd)||(function(a){return j(a,Zi)&&!j(a,Hn)&&!j(a,ln)})(s))(t,e)?j(t,ft)?uf:Zi:j(t,"PaleMoon/")?gf:j(t,hs+"/")?hs:j(t,li)?li:j(t,"MSIE")||j(t,"Trident/")?Il:j(t,"Gecko")?li:"")},Ug={[of]:[new RegExp("rv:"+ke)],[af]:[new RegExp(Cl+"?\\/"+ke)],[Hn]:[new RegExp("("+Hn+"|CrMo)\\/"+ke)],[sf]:[new RegExp("CriOS\\/"+ke)],"UC Browser":[new RegExp("(UCBrowser|UCWEB)\\/"+ke)],[Zi]:[Mo],[uf]:[Mo],[kl]:[new RegExp("(Opera|OPR)\\/"+ke)],[li]:[new RegExp(li+"\\/"+ke)],[lf]:[new RegExp("FxiOS\\/"+ke)],[_a]:[new RegExp("Konqueror[:/]?"+ke,"i")],[pi]:[new RegExp(pi+" "+ke),Mo],[cf]:[new RegExp("android\\s"+ke,"i")],[rf]:[new RegExp(nf+"\\/"+ke)],[hf]:[new RegExp("OculusBrowser\\/"+ke)],[ds]:[new RegExp(ds+"\\/"+ke)],[pf]:[new RegExp("YaBrowser\\/"+ke)],[fs]:[new RegExp(fs+"\\/"+ke)],[Xi]:[new RegExp(Xi+"\\/"+ke)],[wa]:[new RegExp("(DuckDuckGo|Ddg)\\/"+ke)],[gf]:[new RegExp("PaleMoon\\/"+ke)],[hs]:[new RegExp(hs+"\\/"+ke)],[mf]:[new RegExp("GSA\\/"+ke)],[Il]:[new RegExp("(rv:|MSIE )"+ke)],Mozilla:[new RegExp("rv:"+ke)]},Hg=function(t,e,n,i){var r=vf(t,e,n,i),s=Ug[r];if(A(s))return null;for(var o=0;s.length>o;o++){var a=t.match(s[o]);if(a)return parseFloat(a[a.length-2])}return null},Jc=[[new RegExp(ci+"; "+ci+" (.*?)[);]","i"),t=>[ci,t&&t[1]||""]],[new RegExp(or,"i"),[or,""]],[new RegExp(ar,"i"),[ar,""]],[Al,[pi,""]],[new RegExp(Hi,"i"),(t,e)=>{if(/Phone/.test(e)||/WPDesktop/.test(e))return[va,""];if(new RegExp(ft).test(e)&&!/IEMobile\b/.test(e))return[Hi+" "+ft,""];var n=/Windows NT ([0-9.]+)/i.exec(e);if(n&&n[1]){var i=jg[n[1]]||"";return/arm/i.test(e)&&(i="RT"),[Hi,i]}return[Hi,""]}],[/((iPhone|iPad|iPod).*?OS (\d+)_(\d+)_?(\d+)?|iPhone)/,t=>t&&t[3]?[us,[t[3],t[4],t[5]||"0"].join(".")]:[us,""]],[/(watch.*\/(\d+\.\d+\.\d+)|watch os,(\d+\.\d+),)/i,t=>{var e="";return t&&t.length>=3&&(e=A(t[2])?t[3]:t[2]),["watchOS",e]}],[new RegExp("("+ln+" (\\d+)\\.(\\d+)\\.?(\\d+)?|"+ln+")","i"),t=>t&&t[2]?[ln,[t[2],t[3],t[4]||"0"].join(".")]:[ln,""]],[/Mac OS X (\d+)[_.](\d+)[_.]?(\d+)?/i,t=>{var e=["Mac OS X",""];return t&&t[1]&&(e[1]=[t[1],t[2],t[3]||"0"].join(".")),e}],[/Mac/i,["Mac OS X",""]],[/CrOS/,[$g,""]],[/Linux|debian/i,["Linux",""]]],Zc=function(t){return Dg.test(t)?or:Bg.test(t)?ar:Og.test(t)?ci:new RegExp(ya,"i").test(t)?ya:new RegExp("("+va+"|WPDesktop)","i").test(t)?va:/iPad/.test(t)?Xd:/iPod/.test(t)?"iPod Touch":/iPhone/.test(t)?"iPhone":/(watch)(?: ?os[,/]|\d,\d\/)[\d.]+/i.test(t)?ef:Al.test(t)?pi:/(kobo)\s(ereader|touch)/i.test(t)?"Kobo":new RegExp(Yc,"i").test(t)?Yc:/(kf[a-z]{2}wi|aeo[c-r]{2})( bui|\))/i.test(t)||/(kf[a-z]+)( bui|\)).+silk\//i.test(t)?"Kindle Fire":/(Android|ZTE)/i.test(t)?new RegExp(ft).test(t)&&!/(9138B|TB782B|Nexus [97]|pixel c|HUAWEISHT|BTV|noble nook|smart ultra 6)/i.test(t)||/pixel[\daxl ]{1,6}/i.test(t)&&!/pixel c/i.test(t)||/(huaweimed-al00|tah-|APA|SM-G92|i980|zte|U304AA)/i.test(t)||/lmy47v/i.test(t)&&!/QTAQZ3/i.test(t)?ln:Zd:new RegExp("(pda|"+ft+")","i").test(t)?Ng:new RegExp(hi,"i").test(t)&&!new RegExp(hi+" pc","i").test(t)?ff:""},Wg=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function Xc(t,e){return typeof(n=t)=="string"&&Wg.test(n)?t:e();var n}function Sn(t){return t&&t.split("#")[0]}function Pl(t,e){var n=setTimeout(t,e);return n?.unref&&n?.unref(),n}function Qc(t,e,n){return yf.apply(this,arguments)}function yf(){return(yf=ce((function*(t,e,n){var i;try{return yield Promise.race([t,new Promise(((r,s)=>{i=Pl((()=>{try{n?.(),r()}catch(o){s(o)}}),e)}))])}finally{clearTimeout(i)}}))).apply(this,arguments)}var qg=t=>t instanceof Error,_f={trace:{text:"TRACE",number:1},debug:{text:"DEBUG",number:5},info:{text:"INFO",number:9},warn:{text:"WARN",number:13},error:{text:"ERROR",number:17},fatal:{text:"FATAL",number:21}},zg=_f.info;function wf(t){if(kt(t))return{boolValue:t};if(typeof t=="number")return Number.isFinite(t)?Number.isInteger(t)?{intValue:t}:{doubleValue:t}:{stringValue:String(t)};if(typeof t=="string")return{stringValue:t};if(U(t))return{arrayValue:{values:t.map((e=>wf(e)))}};try{return{stringValue:JSON.stringify(t)}}catch{return{stringValue:String(t)}}}function ps(t){var e=[];for(var n in t){var i=t[n];it(i)||A(i)||e.push({key:n,value:wf(i)})}return e}function Vg(t,e){var n=_f[t.level||"info"]||zg,i=n.text,r=n.number,s=String(Date.now())+"000000",o={};e.distinctId&&(o.posthogDistinctId=e.distinctId),e.sessionId&&(o.sessionId=e.sessionId),e.windowId&&(o["window.id"]=e.windowId),q(e.sessionStartTimestamp)||(o.sessionStartTimestamp=String(e.sessionStartTimestamp)),q(e.lastActivityTimestamp)||(o.lastActivityTimestamp=String(e.lastActivityTimestamp)),e.currentUrl&&(o["url.full"]=e.currentUrl),e.screenName&&(o["screen.name"]=e.screenName),e.appState&&(o["app.state"]=e.appState),e.activeFeatureFlags&&e.activeFeatureFlags.length>0&&(o.feature_flags=e.activeFeatureFlags);var a=k({},o,t.attributes||{}),l={timeUnixNano:s,observedTimeUnixNano:s,severityNumber:r,severityText:i,body:{stringValue:t.body},attributes:ps(a)};return t.trace_id&&(l.traceId=t.trace_id),t.span_id&&(l.spanId=t.span_id),A(t.trace_flags)||(l.flags=t.trace_flags),l}function bf(t,e,n){return k({},t.resourceAttributes,{"service.name":t.serviceName||"unknown_service"},t.environment&&{"deployment.environment":t.environment},t.serviceVersion&&{"service.version":t.serviceVersion},{"telemetry.sdk.name":e,"telemetry.sdk.version":n})}function Ef(t,e,n,i){return{resourceLogs:[{resource:{attributes:ps(e)},scopeLogs:[{scope:{name:n,version:i},logRecords:t}]}]}}let Gg=class{constructor(t,e,n,i,r,s,o){var a;s===void 0&&(s=()=>Promise.resolve()),this._instance=t,this.Ne=e,this.rt=n,this.ut=i,this.ht=r,this.dt=s,this.vt=o,this.ct=null,this.ft=0,this.yt=0,this.bt=0,this._t=0,this.wt=!1,this.kt=e.maxBufferSize,this.xt=Math.max((a=e.maxQueueSize)!==null&&a!==void 0?a:e.maxBufferSize,e.maxBufferSize),this.St=e.flushIntervalMs,this.Ct=e.maxBatchRecordsPerPost,this.Mt=e.rateCapWindowMs,this.Tt=e.maxLogsPerInterval}reset(){this.Et(),this.ct=null,this.bt=0,this._t=0,this.wt=!1,this.ft=0,this.yt=0,this.Ct=this.Ne.maxBatchRecordsPerPost}onReconnect(){this.yt=0,this.It()}captureLog(t){if(!this._instance.isDisabled&&!this._instance.optedOut&&t!=null&&t.body){var e=this.Pt(t);if(e!==null)if(e.body){if(this.Rt()){var n={record:Vg(e,this.ut())};this.ht((()=>this.At(n)))}}else this.rt.info("Log was rejected in beforeSend function")}}Pt(t){var e=this.Ne.beforeSend;if(!e)return t;var n=U(e)?e:[e],i=t;for(var r of n)try{var s=r(i);if(!s)return this.rt.info("Log was rejected in beforeSend function"),null;i=s}catch(o){return this.rt.error("Error in beforeSend function for log:",o),null}return i}Rt(){if(this.Tt===void 0)return!0;var t=Date.now(),e=t-this.bt;return this.Mt>e&&e>=0||(this.bt=t,this._t=0,this.wt=!1),this.Tt>this._t?(this._t++,!0):(this.wt||(this.rt.warn("captureLog dropping logs: exceeded "+this.Tt+" logs per "+this.Mt+"ms"),this.wt=!0),!1)}flush(){var t=this;return ce((function*(){if(!t._instance.isDisabled)return t.ct||(t.ct=t.Ft().finally((()=>{t.ct=null}))),t.ct}))()}Ft(){var t=this;return ce((function*(){var e;t.Et();var n=(e=t._instance.getPersistedProperty(Zt.LogsQueue))!==null&&e!==void 0?e:[];if(n.length!==0)for(var i=n.length,r=0;n.length>0&&i>r;){var s,o;t.ft=0;var a=Math.min(n.length,t.Ct),l=n.slice(0,a),u=Ef(l.map((d=>d.record)),t.Lt(),(s=t.vt)!==null&&s!==void 0?s:t._instance.getLibraryId(),t._instance.getLibraryVersion()),c=yield t._instance.Ot(u);if(c.kind==="too-large"&&l.length>1)t.Ct=Math.max(1,Math.floor(l.length/2)),t.rt.warn("Received 413 when sending logs batch of size "+l.length+", reducing batch size to "+t.Ct);else if(c.kind==="retry-later"||(c.kind==="too-large"?t.rt.warn("Dropping a single log record after 413 with batch size 1 — the record is larger than the server cap and cannot be split further."):c.kind==="ok"&&t.Ne.maxBatchRecordsPerPost>t.Ct&&(t.Ct=Math.min(t.Ne.maxBatchRecordsPerPost,t.Ct+1)),yield t.Dt(l.length),n=(o=t._instance.getPersistedProperty(Zt.LogsQueue))!==null&&o!==void 0?o:[],r+=l.length,c.kind==="fatal"))throw c.error}}))()}Dt(t){var e=this;return ce((function*(){var n,i=Math.max(0,t-e.ft),r=(n=e._instance.getPersistedProperty(Zt.LogsQueue))!==null&&n!==void 0?n:[];e._instance.setPersistedProperty(Zt.LogsQueue,r.slice(i)),yield e.dt()}))()}Lt(){return bf(this.Ne,this._instance.getLibraryId(),this._instance.getLibraryVersion())}At(t){var e;if(!this._instance.optedOut){var n=(e=this._instance.getPersistedProperty(Zt.LogsQueue))!==null&&e!==void 0?e:[];this.xt>n.length||(n.shift(),this.ft++,this.rt.info("Logs queue is full, dropping oldest record.")),n.push(t),this._instance.setPersistedProperty(Zt.LogsQueue,n),this.kt>n.length?this.$t():this.It()}}$t(t){t===void 0&&(t=this.St),this.Nt||(this.Nt=Pl((()=>{this.Nt=void 0,this.It()}),t))}qt(){var t=Math.min(Math.max(0,this.yt-1),6);return this.St*Math.pow(2,t)}jt(){var t=this._instance.getPersistedProperty(Zt.LogsQueue);return!!t&&t.length>0}shutdown(t){var e=this;return ce((function*(){e.Et();var n=e.flush().catch((()=>{}));t!==void 0?yield Qc(n,t):yield n}))()}flushWithTimeout(t){var e=this;return ce((function*(){var n=e.flush();yield Qc(n,t,(()=>{n.catch((()=>{}))}))}))()}It(){this.flush().then((()=>{this.yt=0}),(t=>{this.yt++,this.rt.error("PostHog logs flush failed:",t)})).finally((()=>{!this._instance.isDisabled&&this.jt()&&this.$t(this.qt())}))}Et(){this.Nt&&(clearTimeout(this.Nt),this.Nt=void 0)}};var $o=[0,5,10,25,50,75,100,250,500,750,1e3,2500,5e3,7500,1e4];function eu(t){return String(t)+"000000"}function tu(t,e,n,i){var r="";return i&&(r=Object.keys(i).sort().map((s=>JSON.stringify(s)+":"+JSON.stringify(i[s]))).join(",")),t+"\0"+e+"\0"+(n??"")+"\0"+r}let Kg=class{constructor(t,e,n){this._instance=t,this.Ne=e,this.rt=n,this.Bt=new Map,this.ct=null,this.Ht=!1,this.Ut=new Map,this.zt=new Set,this.Wt=0}count(t,e,n){e===void 0&&(e=1),this.Vt({name:t,type:"count",value:e,unit:n?.unit,attributes:n?.attributes})}gauge(t,e,n){this.Vt({name:t,type:"gauge",value:e,unit:n?.unit,attributes:n?.attributes})}histogram(t,e,n){this.Vt({name:t,type:"histogram",value:e,unit:n?.unit,attributes:n?.attributes})}flush(){var t=this,e=this.ct,n=(function(){var r=ce((function*(){e&&(yield e.catch((()=>{}))),yield t.Zt()}));return function(){return r.apply(this,arguments)}})(),i=n().finally((()=>{this.ct===i&&(this.ct=null)}));return this.ct=i,i}drainWindow(){if(this.Bt.size===0)return null;var t=this.Bt;return this.Bt=new Map,this.Ht=!1,this.Ut=new Map,this.zt=new Set,this.Gt(t)}reset(){this.Wt++,this.Et(),this.Bt=new Map,this.ct=null,this.Ht=!1,this.Ut=new Map,this.zt=new Set}Vt(t){if(!this._instance.isDisabled&&!this._instance.optedOut){var e=this.Pt(t);if(e!==null)if(e.name&&typeof e.name=="string")if(typeof e.value=="number"&&Number.isFinite(e.value))if(e.type==="count"&&0>e.value)this.rt.warn("Dropping count '"+e.name+"': counters are monotonic, value must be >= 0");else{var n,i;try{n=e.attributes?k({},e.attributes):void 0,i=tu(e.type,e.name,e.unit,n)}catch(o){return void this.rt.warn("Dropping metric '"+e.name+"': attributes could not be serialized",o)}var r=this.Bt.get(i);if(!r){if(!this.Qt())return;r={name:e.name,type:e.type,unit:e.unit,attributes:n,windowStartMs:Date.now()},this.Bt.set(i,r)}var s=this.Ut.get(e.name);s===void 0?this.Ut.set(e.name,e.type):s===e.type||this.zt.has(e.name)||(this.zt.add(e.name),this.rt.warn("Metric name '"+e.name+"' is already used as a "+s+"; recording it as a "+e.type+" too will blend both series in charts. Use a distinct name.")),this.Kt(r,e.value),this.$t()}else this.rt.warn("Dropping metric '"+e.name+"': value must be a finite number");else this.rt.warn("Dropping metric with empty name")}}Qt(){return this.Ne.maxSeriesPerFlush>this.Bt.size||(this.Ht||(this.Ht=!0,this.rt.warn("Metric series cap reached ("+this.Ne.maxSeriesPerFlush+" per flush window); dropping new series until the next flush. Reduce attribute cardinality.")),!1)}Kt(t,e){var n;switch(t.type){case"count":t.total=((n=t.total)!==null&&n!==void 0?n:0)+e;break;case"gauge":t.last=e;break;case"histogram":t.hist||(t.hist={count:0,sum:0,min:e,max:e,bucketCounts:new Array($o.length+1).fill(0)});var i=t.hist;i.count+=1,i.sum+=e,i.min=Math.min(i.min,e),i.max=Math.max(i.max,e),i.bucketCounts[(function(r,s){for(var o=0;s.length>o;o++)if(s[o]>=r)return o;return s.length})(e,$o)]+=1}}Pt(t){var e=this.Ne.beforeSend;if(!e)return t;var n=U(e)?e:[e],i=t;for(var r of n)try{var s=r(i);if(!s)return this.rt.info("Metric was rejected in beforeSend function"),null;i=s}catch(o){return this.rt.error("Error in beforeSend function for metric:",o),null}return i}$t(){this.Nt||(this.Nt=Pl((()=>{this.Nt=void 0,this.flush().catch((t=>{this.rt.error("Metrics flush failed:",t)}))}),this.Ne.flushIntervalMs))}Et(){this.Nt&&(clearTimeout(this.Nt),this.Nt=void 0)}Zt(){var t=this;return ce((function*(){if(t.Bt.size!==0){var e=t.Bt;t.Bt=new Map,t.Ht=!1,t.Ut=new Map,t.zt=new Set;var n=t.Wt,i=yield t._instance.Jt(t.Gt(e));if(n===t.Wt)switch(i.kind){case"ok":return;case"retry-later":return t.Yt(e),void t.$t();case"too-large":return void t.rt.warn("Metrics batch exceeded the server size limit and was dropped");case"fatal":return void t.rt.error("Failed to send metrics batch:",i.error)}}}))()}Gt(t){return e=this.Xt(t),n=(function(s,o,a){return k({},s.resourceAttributes,{"service.name":s.serviceName||"unknown_service"},s.environment&&{"deployment.environment":s.environment},s.serviceVersion&&{"service.version":s.serviceVersion},{"telemetry.sdk.name":o,"telemetry.sdk.version":a})})(this.Ne,this._instance.getLibraryId(),this._instance.getLibraryVersion()),i=this._instance.getLibraryId(),r=this._instance.getLibraryVersion(),{resourceMetrics:[{resource:{attributes:ps(n)},scopeMetrics:[{scope:{name:i,version:r},metrics:e}]}]};var e,n,i,r}Xt(t){var e=eu(Date.now()),n=new Map;for(var i of t.values()){var r,s=tu(i.type,i.name,i.unit,void 0),o=n.get(s);o||(o=k({name:i.name},i.unit&&{unit:i.unit}),i.type==="count"?o.sum={aggregationTemporality:1,isMonotonic:!0,dataPoints:[]}:i.type==="gauge"?o.gauge={dataPoints:[]}:o.histogram={aggregationTemporality:1,dataPoints:[]},n.set(s,o));var a=ps((r=i.attributes)!==null&&r!==void 0?r:{}),l=eu(i.windowStartMs);if(i.type==="count"){var u,c={attributes:a,startTimeUnixNano:l,timeUnixNano:e,asDouble:(u=i.total)!==null&&u!==void 0?u:0};o.sum.dataPoints.push(c)}else if(i.type==="gauge"){var d,f={attributes:a,timeUnixNano:e,asDouble:(d=i.last)!==null&&d!==void 0?d:0};o.gauge.dataPoints.push(f)}else i.hist&&o.histogram.dataPoints.push({attributes:a,startTimeUnixNano:l,timeUnixNano:e,count:i.hist.count,sum:i.hist.sum,min:i.hist.min,max:i.hist.max,bucketCounts:i.hist.bucketCounts,explicitBounds:$o})}return Array.from(n.values())}Yt(t){var e,n;for(var i of t){var r=i[0],s=i[1],o=this.Bt.get(r);if(o)switch(o.windowStartMs=Math.min(o.windowStartMs,s.windowStartMs),o.type){case"count":o.total=((e=o.total)!==null&&e!==void 0?e:0)+((n=s.total)!==null&&n!==void 0?n:0);break;case"gauge":break;case"histogram":if(s.hist)if(o.hist){o.hist.count+=s.hist.count,o.hist.sum+=s.hist.sum,o.hist.min=Math.min(o.hist.min,s.hist.min),o.hist.max=Math.max(o.hist.max,s.hist.max);for(var a=0;o.hist.bucketCounts.length>a;a++)o.hist.bucketCounts[a]+=s.hist.bucketCounts[a]}else o.hist=s.hist}else this.Qt()&&this.Bt.set(r,s)}}};var Lr,nu,Lo;function Yg(t){var e=globalThis._posthogChunkIds;if(e){var n=Object.keys(e);return Lo&&n.length===nu||(nu=n.length,Lo=n.reduce(((i,r)=>{Lr||(Lr={});var s=Lr[r];if(s)i[s[0]]=s[1];else for(var o=t(r),a=o.length-1;a>=0;a--){var l=o[a],u=l?.filename,c=e[r];if(u&&c){i[u]=c,Lr[r]=[u,c];break}}return i}),{})),Lo}}class Jg{constructor(e,n,i){i===void 0&&(i=[]),this.coercers=e,this.stackParser=n,this.modifiers=i}buildFromUnknown(e,n){n===void 0&&(n={});var i=n&&n.mechanism||{handled:!0,type:"generic"},r=this.buildCoercingContext(i,n,0).apply(e),s=this.buildParsingContext(n),o=this.parseStacktrace(r,s);return{$exception_list:this.convertToExceptionList(o,i),$exception_level:"error"}}modifyFrames(e){var n=this;return ce((function*(){for(var i of e)i.stacktrace&&i.stacktrace.frames&&U(i.stacktrace.frames)&&(i.stacktrace.frames=yield n.applyModifiers(i.stacktrace.frames));return e}))()}coerceFallback(e){var n;return{type:"Error",value:"Unknown error",stack:(n=e.syntheticException)==null?void 0:n.stack,synthetic:!0}}parseStacktrace(e,n){var i,r;return e.cause!=null&&(i=this.parseStacktrace(e.cause,n)),e.stack!=""&&e.stack!=null&&(r=this.applyChunkIds(this.stackParser(e.stack,e.synthetic?n.skipFirstLines:0),n.chunkIdMap)),k({},e,{cause:i,stack:r})}applyChunkIds(e,n){return e.map((i=>(i.filename&&n&&(i.chunk_id=n[i.filename]),i)))}applyCoercers(e,n){for(var i of this.coercers)if(i.match(e))return i.coerce(e,n);return this.coerceFallback(n)}applyModifiers(e){var n=this;return ce((function*(){var i=e;for(var r of n.modifiers)i=yield r(i);return i}))()}convertToExceptionList(e,n){var i,r,s,o={type:e.type,value:e.value,mechanism:{type:(i=n.type)!==null&&i!==void 0?i:"generic",handled:(r=n.handled)===null||r===void 0||r,synthetic:(s=e.synthetic)!==null&&s!==void 0&&s}};e.stack&&(o.stacktrace={type:"raw",frames:e.stack});var a=[o];return e.cause!=null&&a.push(...this.convertToExceptionList(e.cause,k({},n,{handled:!0}))),a}buildParsingContext(e){var n;return{chunkIdMap:Yg(this.stackParser),skipFirstLines:(n=e.skipFirstLines)!==null&&n!==void 0?n:1}}buildCoercingContext(e,n,i){i===void 0&&(i=0);var r=(s,o)=>{if(4>=o){var a=this.buildCoercingContext(e,n,o);return this.applyCoercers(s,a)}};return k({},n,{syntheticException:i==0?n.syntheticException:void 0,mechanism:e,apply:s=>r(s,i),next:s=>r(s,i+1)})}}var gi="?";function ba(t,e,n,i,r){var s={platform:t,filename:e,function:n===""?gi:n,in_app:!0};return A(i)||(s.lineno=i),A(r)||(s.colno=r),s}var Sf=(t,e)=>{var n=t.indexOf("safari-extension")!==-1,i=t.indexOf("safari-web-extension")!==-1;return n||i?[t.indexOf("@")!==-1?t.split("@")[0]:gi,n?"safari-extension:"+e:"safari-web-extension:"+e]:[t,e]},Zg=/^\s*at (\S+?)(?::(\d+))(?::(\d+))\s*$/i,Xg=/^\s*at (?:(.+?\)(?: \[.+\])?|.*?) ?\((?:address at )?)?(?:async )?((?:|[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,Qg=/\((\S*)(?::(\d+))(?::(\d+))\)/,em=(t,e)=>{var n=Zg.exec(t);if(n)return ba(e,n[1],gi,+n[2],+n[3]);var i=Xg.exec(t);if(i){if(i[2]&&i[2].indexOf("eval")===0){var r=Qg.exec(i[2]);r&&(i[2]=r[1],i[3]=r[2],i[4]=r[3])}var s=Sf(i[1]||gi,i[2]);return ba(e,s[1],s[0],i[3]?+i[3]:void 0,i[4]?+i[4]:void 0)}},tm=/^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:[-a-z]+)?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js)|\/[\w\-. /=]+)(?::(\d+))?(?::(\d+))?\s*$/i,nm=/(\S+) line (\d+)(?: > eval line \d+)* > eval/i,im=(t,e)=>{var n=tm.exec(t);if(n){if(n[3]&&n[3].indexOf(" > eval")>-1){var i=nm.exec(n[3]);i&&(n[1]=n[1]||"eval",n[3]=i[1],n[4]=i[2],n[5]="")}var r=n[3],s=n[1]||gi,o=Sf(s,r);return ba(e,r=o[1],s=o[0],n[4]?+n[4]:void 0,n[5]?+n[5]:void 0)}},iu=/\(error: (.*)\)/;class rm{match(e){return this.isDOMException(e)||this.isDOMError(e)}coerce(e,n){var i=X(e.stack);return{type:this.getType(e),value:this.getValue(e),stack:i?e.stack:void 0,cause:e.cause?n.next(e.cause):void 0,synthetic:!1}}getType(e){return this.isDOMError(e)?"DOMError":"DOMException"}getValue(e){var n=e.name||(this.isDOMError(e)?"DOMError":"DOMException");return e.message?n+": "+e.message:n}isDOMException(e){return cs(e,"DOMException")}isDOMError(e){return cs(e,"DOMError")}}class sm{match(e){return(function(n){switch({}.toString.call(n)){case"[object Error]":case"[object Exception]":case"[object DOMException]":case"[object DOMError]":case"[object WebAssembly.Exception]":return!0;default:return Jd(n,Error)}})(e)}coerce(e,n){return{type:this.getType(e),value:this.getMessage(e,n),stack:this.getStack(e),cause:e.cause?n.next(e.cause):void 0,synthetic:!1}}getType(e){return e.name||e.constructor.name}getMessage(e,n){var i=e.message;return String(i.error&&typeof i.error.message=="string"?i.error.message:i)}getStack(e){return e.stacktrace||e.stack||void 0}}class om{constructor(){}match(e){return!!cs(e,"ErrorEvent")&&(e.error!=null||this.fe(e))}coerce(e,n){var i;if(e.error!=null)return n.apply(e.error);var r=n.apply(e.message);return k({},r,{stack:(i=this.pe(e))!==null&&i!==void 0?i:r.stack,synthetic:!0})}fe(e){return X(e.message)&&e.message.length>0}pe(e){var n=e;if(X(n.filename)&&n.filename.length>0){var i,r,s=(i=n.lineno)!==null&&i!==void 0?i:0,o=(r=n.colno)!==null&&r!==void 0?r:0;return`Error + at `+n.filename+":"+s+":"+o}}}var am=/^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/i;class lm{match(e){return typeof e=="string"}coerce(e,n){var i,r=this.getInfos(e),s=r[0],o=r[1];return{type:s??"Error",value:o??e,stack:(i=n.syntheticException)==null?void 0:i.stack,synthetic:!0}}getInfos(e){var n="Error",i=e,r=e.match(am);return r&&(n=r[1],i=r[2]),[n,i]}}var cm=["fatal","error","warning","log","info","debug"];function xf(t,e){e===void 0&&(e=40);var n=Object.keys(t);if(n.sort(),!n.length)return"[object has no keys]";for(var i=n.length;i>0;i--){var r=n.slice(0,i).join(", ");if(e>=r.length)return i===n.length?r:r.length>e?r.slice(0,e)+"...":r}return""}class um{match(e){return typeof e=="object"&&e!==null}coerce(e,n){var i,r,s=this.getErrorPropertyFromObject(e);return s?n.apply(s):{type:this.getType(e),value:this.getValue(e),stack:(i=this.getStack(e))!==null&&i!==void 0?i:(r=n.syntheticException)==null?void 0:r.stack,level:this.isSeverityLevel(e.level)?e.level:"error",synthetic:!0}}getType(e){return xl(e)?e.constructor.name:"Error"}getValue(e){if("name"in e&&typeof e.name=="string"){var n="'"+e.name+"' captured as exception";return"message"in e&&typeof e.message=="string"&&(n+=" with message: '"+e.message+"'"),n}if("message"in e&&typeof e.message=="string")return e.message;var i=this.getObjectClassName(e);return(i&&i!=="Object"?"'"+i+"'":"Object")+" captured as exception with keys: "+xf(e)}isSeverityLevel(e){return X(e)&&!ma(e)&&cm.indexOf(e)>=0}getStack(e){try{return X(e.stacktrace)&&e.stacktrace.length>0?e.stacktrace:X(e.stack)&&e.stack.length>0?e.stack:void 0}catch{return}}getErrorPropertyFromObject(e){for(var n in e)if({}.hasOwnProperty.call(e,n)){var i=e[n];if(qg(i))return i}}getObjectClassName(e){try{var n=Object.getPrototypeOf(e);return n?n.constructor.name:void 0}catch{return}}}class dm{match(e){return xl(e)}coerce(e,n){var i,r=e.constructor.name;return{type:r,value:r+" captured as exception with keys: "+xf(e),stack:(i=n.syntheticException)==null?void 0:i.stack,synthetic:!0}}}class fm{match(e){return Yd(e)}coerce(e,n){var i;return{type:"Error",value:"Primitive value captured as exception: "+String(e),stack:(i=n.syntheticException)==null?void 0:i.stack,synthetic:!0}}}class hm{match(e){return cs(e,"PromiseRejectionEvent")||this.isCustomEventWrappingRejection(e)}isCustomEventWrappingRejection(e){if(!xl(e))return!1;try{var n=e.detail;return n!=null&&typeof n=="object"&&"reason"in n}catch{return!1}}coerce(e,n){var i,r=this.getUnhandledRejectionReason(e);return Yd(r)?{type:"UnhandledRejection",value:"Non-Error promise rejection captured with value: "+String(r),stack:(i=n.syntheticException)==null?void 0:i.stack,synthetic:!0}:n.apply(r)}getUnhandledRejectionReason(e){try{if("reason"in e)return e.reason;if("detail"in e&&e.detail!=null&&typeof e.detail=="object"&&"reason"in e.detail)return e.detail.reason}catch{}return e}}var gs="$message",ms="$timestamp",pm=new Set([gs,ms]),No={enabled:!0,max_bytes:32768};function vs(t){var e;return t?{enabled:(e=t.enabled)!==null&&e!==void 0?e:No.enabled,max_bytes:mm(t.max_bytes,No.max_bytes)}:k({},No)}class gm{constructor(e){this.Ke=[],this.Je=0,this.Ne=vs(e)}setConfig(e){this.Ne=vs(e),this.Xe()}add(e){var n=(function(r){var s;try{s=Vd(r)}catch{return}try{var o=JSON.parse(s);if(!ye(o))return;var a=o,l=a[gs],u=a[ms];return!X(l)||l.trim().length===0||!X(u)&&!Fe(u)?void 0:{step:a,json:s}}catch{return}})(e);if(n){var i=(function(r){if(typeof TextEncoder<"u")return new TextEncoder().encode(r).length;for(var s=encodeURIComponent(r),o=0,a=0;s.length>a;a++)s[a]==="%"?(o+=1,a+=2):o+=1;return o})(n.json);i>this.Ne.max_bytes||(this.Ke.push({step:n.step,bytes:i}),this.Je+=i,this.Xe())}}getAttachable(){return this.Ke.map((e=>e.step))}clear(){this.Ke=[],this.Je=0}size(){return this.Ke.length}Xe(){for(;this.Je>this.Ne.max_bytes&&this.Ke.length>0;){var e=this.Ke.shift();e&&(this.Je-=e.bytes)}}}function mm(t,e){if(!Fe(t)||t===1/0||t===-1/0)return e;var n=Math.floor(t);return 0>n?e:n}var If=function(t,e){var n=(e===void 0?{}:e).debugEnabled,i={k(r){if(w&&(oe.DEBUG||w.POSTHOG_DEBUG||n)&&!A(w.console)&&w.console){for(var s=("__rrweb_original__"in w.console[r])?w.console[r].__rrweb_original__:w.console[r],o=arguments.length,a=new Array(o>1?o-1:0),l=1;o>l;l++)a[l-1]=arguments[l];s(t,...a)}},debug(){for(var r=arguments.length,s=new Array(r),o=0;r>o;o++)s[o]=arguments[o];i.k("debug",...s)},info(){for(var r=arguments.length,s=new Array(r),o=0;r>o;o++)s[o]=arguments[o];i.k("log",...s)},warn(){for(var r=arguments.length,s=new Array(r),o=0;r>o;o++)s[o]=arguments[o];i.k("warn",...s)},error(){for(var r=arguments.length,s=new Array(r),o=0;r>o;o++)s[o]=arguments[o];i.k("error",...s)},critical(){for(var r=arguments.length,s=new Array(r),o=0;r>o;o++)s[o]=arguments[o];console.error(t,...s)},uninitializedWarning(r){i.error("You must initialize PostHog before calling "+r)},createLogger:(r,s)=>If(t+" "+r,s)};return i},P=If("[PostHog.js]"),_e=P.createLogger,vm=_e("[ExternalScriptsLoader]"),Oo=(t,e,n)=>{if(t.config.disable_external_dependency_loading)return vm.warn(e+" was requested but loading of external scripts is disabled."),n("Loading of external scripts is disabled");var i=F?.querySelectorAll("script");if(i){for(var r,s=function(){if(i[o].src===e){var l=i[o];return l.__posthog_loading_callback_fired?{v:n()}:(l.addEventListener("load",(u=>{l.__posthog_loading_callback_fired=!0,n(void 0,u)})),l.onerror=u=>n(u),{v:void 0})}},o=0;i.length>o;o++)if(r=s())return r.v}var a=()=>{if(!F)return n("document not found");var l=F.createElement("script");if(l.type="text/javascript",l.crossOrigin="anonymous",l.src=e,l.onload=d=>{l.__posthog_loading_callback_fired=!0,n(void 0,d)},l.onerror=d=>n(d),t.config.prepare_external_dependency_script&&(l=t.config.prepare_external_dependency_script(l)),!l)return n("prepare_external_dependency_script returned null");if(t.config.external_scripts_inject_target==="head")F.head.appendChild(l);else{var u,c=F.querySelectorAll("body > script");c.length>0?(u=c[0].parentNode)==null||u.insertBefore(l,c[0]):F.body.appendChild(l)}};F!=null&&F.body?a():F?.addEventListener("DOMContentLoaded",a)};B.__PosthogExtensions__=B.__PosthogExtensions__||{},B.__PosthogExtensions__.loadExternalDependency=(t,e,n)=>{if(e!=="remote-config"){var i;if(t.config.strict_script_versioning)i=t.requestRouter.endpointFor("assets","/static/"+t.version+"/"+e+".js");else{var r="/static/"+e+".js?v="+t.version;if(e==="toolbar"){var s=3e5;r=r+"&t="+Math.floor(Date.now()/s)*s}i=t.requestRouter.endpointFor("assets",r)}Oo(t,i,n)}else{var o=t.requestRouter.endpointFor("assets","/array/"+t.config.token+"/config.js");Oo(t,o,n)}},B.__PosthogExtensions__.loadSiteApp=(t,e,n)=>{var i=t.requestRouter.endpointFor("api",e);Oo(t,i,n)};oe.DEBUG=!1,oe.LIB_VERSION="1.415.7",oe.LIB_NAME="web";var kf="$people_distinct_id",lr="$device_id",Bo="$device_model",Wi="__alias",qi="__timers",Ea="$autocapture_disabled_server_side",Sa="$heatmaps_enabled_server_side",xa="$exception_capture_enabled_server_side",Ia="$error_tracking_suppression_rules",ka="$error_tracking_capture_extension_exceptions",Ca="$web_vitals_enabled_server_side",Fl="$dead_clicks_enabled_server_side",Rl="$product_tours_enabled_server_side",Aa="$web_vitals_allowed_metrics",jn="$session_recording_remote_config",Cf="$replay_sample_rate",Af="$replay_override_sampling",Pf="$replay_override_linked_flag",Ff="$replay_override_url_trigger",Rf="$replay_override_event_trigger",si="$sesid",Tl="$session_is_sampled",Ln="$enabled_feature_flags",zi="$active_feature_flags",Kr="$early_access_features",Pa="$feature_flag_details",Vi="$feature_flag_payloads",Yr="$feature_flag_request_id",ys="$minimal_flag_called_events",Mt="$override_feature_flags",Nn="$override_feature_flag_payloads",Jt="$stored_person_properties",On="$stored_group_properties",Fa="$surveys",_s="$surveys_loaded_at",Ra="$surveys_activated",Jr="$surveys_activated_session",Zr="$surveys_activated_timestamps",Gi="ph_product_tours",Dn="$flag_call_reported",Ki="$flag_call_reported_session_id",Xr="$feature_flag_errors",Qi="$feature_flag_evaluated_at",yt="$user_state",Ta="$client_session_props",Ma="$capture_rate_limit",$a="$initial_campaign_params",La="$initial_referrer_info",ws="$initial_person_info",bs="$epp",Nr="$posthog_cookieless",Tf="$cookieless_mode",Mf="$sdk_debug_extensions_init_method",$f="$sdk_debug_extensions_init_time_ms",Lf="$sdk_debug_recording_script_not_loaded",Ml="PostHog loadExternalDependency extension not found.",Bn="on_reject",tn="always",Xn="anonymous",Pn="identified",Na="identified_only",Es="visibilitychange",Ss="beforeunload",ii="$pageview",Do="$pageleave",jo="$identify",ru="$groupidentify";function Or(t,e){U(t)&&t.forEach(e)}function ae(t,e){if(!q(t))if(U(t))t.forEach(e);else if(Ag(t))t.forEach(((i,r)=>e(i,r)));else for(var n in t)Kd.call(t,n)&&e(t[n],n)}var ve=function(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),i=1;e>i;i++)n[i-1]=arguments[i];for(var r of n)for(var s in r)r[s]!==void 0&&(t[s]=r[s]);return t};function Qr(t){for(var e=Object.keys(t),n=e.length,i=new Array(n);n--;)i[n]=[e[n],t[e[n]]];return i}var su=function(t){try{return t()}catch{return}},ym=function(t){return function(){try{for(var e=arguments.length,n=new Array(e),i=0;e>i;i++)n[i]=arguments[i];return t.apply(this,n)}catch(r){P.critical("Implementation error. Please turn on debug mode and open a ticket on https://app.posthog.com/home#panel=support%3Asupport%3A."),P.critical(r)}}},$l=function(t){var e={};return ae(t,(function(n,i){(X(n)&&n.length>0||Fe(n))&&(e[i]=n)})),e},_m=["herokuapp.com","vercel.app","netlify.app"];function wm(t){var e=t?.hostname;if(!X(e))return!1;var n=e.split(".").slice(-2).join(".");for(var i of _m)if(n===i)return!1;return!0}function Se(t,e,n,i){var r=i??{},s=r.capture,o=r.passive;t?.addEventListener(e,n,{capture:s!==void 0&&s,passive:o===void 0||o})}function Oa(t){return t.name==="ph_toolbar_internal"}var Nf=t=>{if(F){try{for(var e=t+"=",n=F.cookie.split(";").filter((s=>s.length)),i=0;n.length>i;i++){for(var r=n[i];r.charAt(0)==" ";)r=r.substring(1,r.length);if(r.indexOf(e)===0)return decodeURIComponent(r.substring(e.length,r.length))}}catch{}return null}};Math.trunc||(Math.trunc=function(t){return 0>t?Math.ceil(t):Math.floor(t)}),Number.isInteger||(Number.isInteger=function(t){return Fe(t)&&isFinite(t)&&Math.floor(t)===t});class xs{constructor(e){if(this.bytes=e,e.length!==16)throw new TypeError("not 128-bit length")}static fromFieldsV7(e,n,i,r){if(!Number.isInteger(e)||!Number.isInteger(n)||!Number.isInteger(i)||!Number.isInteger(r)||0>e||0>n||0>i||0>r||e>0xffffffffffff||n>4095||i>1073741823||r>4294967295)throw new RangeError("invalid field value");var s=new Uint8Array(16);return s[0]=e/Math.pow(2,40),s[1]=e/Math.pow(2,32),s[2]=e/Math.pow(2,24),s[3]=e/Math.pow(2,16),s[4]=e/256,s[5]=e,s[6]=112|n>>>8,s[7]=n,s[8]=128|i>>>24,s[9]=i>>>16,s[10]=i>>>8,s[11]=i,s[12]=r>>>24,s[13]=r>>>16,s[14]=r>>>8,s[15]=r,new xs(s)}toString(){for(var e="",n=0;this.bytes.length>n;n++)e=e+(this.bytes[n]>>>4).toString(16)+(15&this.bytes[n]).toString(16),n!==3&&n!==5&&n!==7&&n!==9||(e+="-");if(e.length!==36)throw new Error("Invalid UUIDv7 was generated");return e}clone(){return new xs(this.bytes.slice(0))}equals(e){return this.compareTo(e)===0}compareTo(e){for(var n=0;16>n;n++){var i=this.bytes[n]-e.bytes[n];if(i!==0)return Math.sign(i)}return 0}}class bm{generate(){var e=this.generateOrAbort();if(!A(e))return e;this.S=0;var n=this.generateOrAbort();if(A(n))throw new Error("Could not generate UUID after timestamp reset");return n}generateOrAbort(){var e=Date.now();if(e>this.S)this.S=e,this.C();else{if(this.S>=e+1e4)return;this.I++,this.I>4398046511103&&(this.S++,this.C())}return xs.fromFieldsV7(this.S,Math.trunc(this.I/Math.pow(2,30)),this.I&Math.pow(2,30)-1,this.A.nextUint32())}C(){this.I=1024*this.A.nextUint32()+(1023&this.A.nextUint32())}constructor(){this.S=0,this.I=0,this.A=new Em}}var ou,Of=t=>{if(typeof UUIDV7_DENY_WEAK_RNG<"u"&&UUIDV7_DENY_WEAK_RNG)throw new Error("no cryptographically strong RNG available");for(var e=0;t.length>e;e++)t[e]=65536*Math.trunc(65536*Math.random())+Math.trunc(65536*Math.random());return t};w&&!A(w.crypto)&&crypto.getRandomValues&&(Of=t=>crypto.getRandomValues(t));class Em{nextUint32(){return this.R.length>this.O||(Of(this.R),this.O=0),this.R[this.O++]}constructor(){this.R=new Uint32Array(8),this.O=1/0}}var Xt=()=>Sm().toString(),Sm=()=>(ou||(ou=new bm)).generate(),Ti="",xm=/[a-z0-9][a-z0-9-]+\.[a-z]{2,}$/i,nn={N:()=>!!F,j(t){P.error("cookieStore error: "+t)},P:Nf,H(t){var e;try{e=JSON.parse(nn.P(t))||{}}catch{}return e},F(t,e,n,i,r){if(!F)return!1;try{var s="",o="",a=(function(c,d){if(d){var f=(function(h,g){if(g===void 0&&(g=F),Ti)return Ti;if(!g||["localhost","127.0.0.1"].includes(h))return"";for(var m=h.split("."),v=Math.min(m.length,8),x="dmn_chk_"+Xt();!Ti&&v--;){var E=m.slice(v).join("."),y=x+"=1;domain=."+E+";path=/";g.cookie=y+";max-age=3",g.cookie.includes(x)&&(g.cookie=y+";max-age=0",Ti=E)}return Ti})(c);if(!f){var p=(h=>{var g=h.match(xm);return g?g[0]:""})(c);p!==f&&P.info("Warning: cookie subdomain discovery mismatch",p,f),f=p}return f?"; domain=."+f:""}return""})(F.location.hostname,i);if(n){var l=new Date;l.setTime(l.getTime()+864e5*n),s="; expires="+l.toUTCString()}r&&(o="; secure");var u=t+"="+encodeURIComponent(JSON.stringify(e))+s+"; SameSite=Lax; path=/"+a+o;return u.length>3686.4&&P.warn("cookieStore warning: large cookie, len="+u.length),F.cookie=u,!0}catch{return!1}},q(t,e){if(F!=null&&F.cookie)try{nn.F(t,"",-1,e)}catch{return}}},Uo=null,fe={N(){if(!it(Uo))return Uo;var t=!0;if(A(w))t=!1;else try{var e="__mplssupport__";fe.F(e,"xyz"),fe.P(e)!=='"xyz"'&&(t=!1),fe.q(e)}catch{t=!1}return t||P.error("localStorage unsupported; falling back to cookie store"),Uo=t,t},j(t){P.error("localStorage error: "+t)},P(t){try{return w?.localStorage.getItem(t)}catch(e){fe.j(e)}return null},H(t){try{return JSON.parse(fe.P(t))||{}}catch{}return null},F(t,e){try{return w?.localStorage.setItem(t,JSON.stringify(e)),!0}catch(n){fe.j(n)}return!1},q(t){try{w?.localStorage.removeItem(t)}catch(e){fe.j(e)}}},Im=[lr,"distinct_id",si,Tl,bs,ws,yt],Br={},km={N:()=>!0,j(t){P.error("memoryStorage error: "+t)},P:t=>Br[t]||null,H:t=>Br[t]||null,F:(t,e)=>(Br[t]=e,!0),q(t){delete Br[t]}},Fn=null,Ce={N(){if(!it(Fn))return Fn;if(Fn=!0,A(w))Fn=!1;else try{var t="__support__";Ce.F(t,"xyz"),Ce.P(t)!=='"xyz"'&&(Fn=!1),Ce.q(t)}catch{Fn=!1}return Fn},j(t){P.error("sessionStorage error: ",t)},P(t){try{return w?.sessionStorage.getItem(t)}catch(e){Ce.j(e)}return null},H(t){try{return JSON.parse(Ce.P(t))||null}catch{}return null},F(t,e){try{return w?.sessionStorage.setItem(t,JSON.stringify(e)),!0}catch(n){Ce.j(n)}return!1},q(t){try{w?.sessionStorage.removeItem(t)}catch(e){Ce.j(e)}}};class Cm{constructor(e){this._instance=e}get Ne(){return this._instance.config}get consent(){return this.ti()?0:this.ei}isOptedOut(){return this.Ne.cookieless_mode===tn||this.isRejected()||this.consent===-1&&this.Ne.cookieless_mode===Bn}isOptedIn(){return!this.isOptedOut()}isExplicitlyOptedOut(){return this.consent===0}isRejected(){return this.consent===0||this.consent===-1&&this.Ne.opt_out_capturing_by_default}optInOut(e){this.ii.F(this.ri,e?1:0,this.Ne.cookie_expiration,this.Ne.cross_subdomain_cookie,this.Ne.secure_cookie)}reset(){this.ii.q(this.ri,this.Ne.cross_subdomain_cookie)}get ri(){var e=this._instance.config,n=e.token,i=e.opt_out_capturing_cookie_prefix;return e.consent_persistence_name||(i?i+n:"__ph_opt_in_out_"+n)}get ei(){var e=this.ii.P(this.ri);return To(e)?1:j(Tg,e)?0:-1}get ii(){var e=this.Ne.opt_out_capturing_persistence_type,n=e==="localStorage"?fe:nn;if(!this.ni||this.ni!==n){this.ni=n;var i=e==="localStorage"?nn:fe;i.P(this.ri)&&(this.ni.P(this.ri)||this.optInOut(To(i.P(this.ri))),i.q(this.ri,this.Ne.cross_subdomain_cookie))}return this.ni}ti(){return!!this.Ne.respect_dnt&&[Ve?.doNotTrack,Ve?.msDoNotTrack,B.doNotTrack].some((e=>To(e)))}}function Bf(t,e){var n,i=t==null||(n=t.config)==null?void 0:n.get_current_url;if(!qe(i))return e;try{var r=i(e);return X(r)&&r?r:e}catch(s){return P.error("Error in get_current_url, falling back to window.location.href",s),e}}var Df="__POSTHOG_TOOLBAR__",Am=1,Pm=3,Fm=11;function au(t){return t instanceof Element&&(t.id===Df||!(t.closest==null||!t.closest(".toolbar-global-fade-container")))}function xn(t){return!!t&&t.nodeType===Am}function lt(t,e){return!!t&&!!t.tagName&&t.tagName.toLowerCase()===e.toLowerCase()}function jf(t){return!!t&&t.nodeType===Pm}function Uf(t){return!!t&&t.nodeType===Fm&&xn(t.host)}var Hf=1e3;function Ll(t){return t?Ks(t).split(/\s+/):[]}function lu(t,e){var n=(function(i){var r,s=w==null||(r=w.location)==null?void 0:r.href;return A(s)?void 0:Bf(i,s)})(e);return!!(n&&t&&t.some((i=>n.match(i))))}function Is(t){var e="";switch(typeof t.className){case"string":e=t.className;break;case"object":e=(t.className&&"baseVal"in t.className?t.className.baseVal:null)||t.getAttribute("class")||"";break;default:e=""}return Ll(e)}function Wf(t){return q(t)?null:Ks(t).split(/(\s+)/).filter((e=>er(e))).join("").replace(/[\r\n]/g," ").replace(/[ ]+/g," ").substring(0,255)}function cr(t){var e="";return Da(t)&&!Gf(t)&&t.childNodes&&t.childNodes.length&&ae(t.childNodes,(function(n){var i;jf(n)&&n.textContent&&(e+=(i=Wf(n.textContent))!==null&&i!==void 0?i:"")})),Ks(e)}function Ho(t){var e;return A(t.target)?t.srcElement||null:(e=t.target)!=null&&e.shadowRoot?t.composedPath()[0]||null:t.target||null}var Nl=["a","button","form","input","select","textarea","label"];function Ba(t,e){if(A(e))return!0;var n,i=function(s){if(e.some((o=>(function(a,l){var u=a.matches||a.matchesSelector||a.msMatchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.oMatchesSelector;try{return!!u&&u.call(a,l)}catch{return!1}})(s,o))))return{v:!0}};for(var r of t)if(n=i(r))return n.v;return!1}function qf(t){var e=t.parentNode;return!(!e||!xn(e))&&e}var Rm=[".ph-no-autocapture","[data-ph-no-autocapture]"],zf=["next","previous","prev",">","<"],Tm=[...zf,"+","-","−","–"],cu=(t,e)=>/[a-z0-9]/i.test(e)?t.includes(e):t===e,uu=[".ph-no-rageclick",".ph-no-capture"],Mm=["","text","search","email","password","url","tel","number"];function du(t,e){if(!w||Ol(t))return!1;var n,i,r,s,o;if(kt(e)?(n=!!e&&uu,i=void 0,r=!1):(n=(s=e?.css_selector_ignorelist)!==null&&s!==void 0?s:uu,i=e?.content_ignorelist,r=(o=e?.ignore_text_selection)!==null&&o!==void 0&&o),n===!1||r&&(function(l){return!(!l||!xn(l))&&(!!lt(l,"textarea")||(lt(l,"input")?j(Mm,(l.getAttribute("type")||"").toLowerCase()):(function(u){if(u.isContentEditable)return!0;var c=u.getAttribute==null?void 0:u.getAttribute("contenteditable");return c==="true"||c===""})(l)))})(t))return!1;var a=Vf(t,!1).targetElementList;return!(function(l,u){if(l===!1||A(l))return!1;var c;if(l===!0)c=zf;else{if(!U(l))return!1;if(l.length>10)return P.error("[PostHog] content_ignorelist array cannot exceed 10 items. Use css_selector_ignorelist for more complex matching."),!1;c=l.map((d=>d.toLowerCase()))}return u.some((d=>{var f=d.safeText,p=d.ariaLabel;return c.some((h=>cu(f,h)||cu(p,h)))}))})(i,a.map((l=>{var u;return{safeText:cr(l).toLowerCase(),ariaLabel:((u=l.getAttribute("aria-label"))==null?void 0:u.toLowerCase().trim())||""}})))&&!Ba(a,n)}var Ol=t=>!t||lt(t,"html")||!xn(t),Vf=(t,e)=>{if(!w||Ol(t))return{parentIsUsefulElement:!1,targetElementList:[]};for(var n=!1,i=[t],r=t;r.parentNode&&!lt(r,"body");)if(Uf(r.parentNode))i.push(r.parentNode.host),r=r.parentNode.host;else{var s=qf(r);if(!s)break;if(e||Nl.indexOf(s.tagName.toLowerCase())>-1)n=!0;else try{var o=w.getComputedStyle(s);o&&o.getPropertyValue("cursor")==="pointer"&&(n=!0)}catch{}i.push(s),r=s}return{parentIsUsefulElement:n,targetElementList:i}};function Da(t){for(var e=new Set,n=0,i=t;i.parentNode&&!lt(i,"body");i=i.parentNode){if(n++>=Hf||e.has(i))return!1;e.add(i);var r=Is(i);if(j(r,"ph-sensitive")||j(r,"ph-no-capture"))return!1}if(j(Is(t),"ph-include"))return!0;var s=t.type||"";if(X(s))switch(s.toLowerCase()){case"hidden":case"password":return!1}var o=t.name||t.id||"";return!X(o)||!/^cc|cardnum|ccnum|creditcard|csc|cvc|cvv|exp|pass|pwd|routing|seccode|securitycode|securitynum|socialsec|socsec|ssn/i.test(o.replace(/[^a-zA-Z0-9]/g,""))}function Gf(t){return!!(lt(t,"input")&&!["button","checkbox","submit","reset"].includes(t.type)||lt(t,"select")||lt(t,"textarea")||t.getAttribute("contenteditable")==="true")}var fu=new RegExp("^(?:(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11}))$"),hu=/(^|[^0-9A-Za-z_])([0-9][0-9 -]*[0-9])(?=$|[^0-9A-Za-z_])/g,$m=[16,15,14,13],Lm=new RegExp("^(\\d{3}-?\\d{2}-?\\d{4})$"),pu=new RegExp("(^|[^0-9])((?!000|666)[0-9]{3}-?(?!00)[0-9]{2}-?(?!0000)[0-9]{4})(?=$|([^0-9]))","g"),gu=/[0-9A-Za-z_]/;function Nm(t){for(var e=0,n=!1,i=t.length-1;i>=0;i--){var r=t.charCodeAt(i)-48;n&&(r*=2)>9&&(r-=9),e+=r,n=!n}return e%10==0}function er(t,e){if(e===void 0&&(e=!0),q(t))return!1;if(X(t)){t=Ks(t);var n=e?fu.test((t||"").replace(/[- ]/g,"")):(function(r){var s;for(hu.lastIndex=0;s=hu.exec(r);){var o=s[2];if(o)for(var a=o.replace(/[- ]/g,""),l=0;a.length>l;l++)for(var u of $m){var c=l+u;if(a.length>=c){var d=a.slice(l,c);if(fu.test(d)&&Nm(d))return!0}}}return!1})(t);if(n)return!1;var i=e?Lm.test(t):(function(r){var s;for(pu.lastIndex=0;s=pu.exec(r);){var o=s[1],a=s[3];if(!(o&&a&&gu.test(o)&&gu.test(a)))return!0}return!1})(t);if(i)return!1}return!0}function mu(t){var e=cr(t);return er(e=(e+" "+Kf(t)).trim())?e:""}function Kf(t){var e="";return t&&t.childNodes&&t.childNodes.length&&ae(t.childNodes,(function(n){var i;if(n&&((i=n.tagName)==null?void 0:i.toLowerCase())==="span")try{var r=cr(n);e=(e+" "+r).trim(),n.childNodes&&n.childNodes.length&&(e=(e+" "+Kf(n)).trim())}catch(s){P.error("[AutoCapture]",s)}})),e}function vu(t){return t.replace(/"|\\"/g,'\\"')}function Om(t){var e=t.attr__class;if(e)return U(e)?e:Ll(e)}var Dr=_e("[Dead Clicks]"),Bm=()=>!0,Dm=t=>{var e,n=!((e=t.instance.persistence)==null||!e.get_property(Fl)),i=t.instance.config.capture_dead_clicks;return kt(i)?i:!!ye(i)||n};class yu{get lazyLoadedDeadClicksAutocapture(){return this.si}constructor(e,n,i){this.instance=e,this.isEnabled=n,this.onCapture=i,this.startIfEnabledOrStop()}onRemoteConfig(e){if(e.ok){var n=e.config;"captureDeadClicks"in n&&(this.instance.persistence&&this.instance.persistence.register({[Fl]:n.captureDeadClicks}),this.startIfEnabledOrStop())}}startIfEnabledOrStop(){this.isEnabled(this)?this.ai((()=>{this.oi()})):this.stop()}ai(e){var n,i;(n=B.__PosthogExtensions__)!=null&&n.initDeadClicksAutocapture?e():(i=B.__PosthogExtensions__)==null||i.loadExternalDependency==null||i.loadExternalDependency(this.instance,"dead-clicks-autocapture",(r=>{r?Dr.error("failed to load script",r):e()}))}oi(){var e;if(F){if(!this.si&&(e=B.__PosthogExtensions__)!=null&&e.initDeadClicksAutocapture){var n=ye(this.instance.config.capture_dead_clicks)?k({},this.instance.config.capture_dead_clicks):{};n.__onCapture=this.onCapture,this.onCapture&&(n.capture_dead_swipes=!1),this.si=B.__PosthogExtensions__.initDeadClicksAutocapture(this.instance,n),this.si.start(F),Dr.info("starting...")}}else Dr.error("`document` not found. Cannot start.")}stop(){this.si&&(this.si.stop(),this.si=void 0,Dr.info("stopping..."))}}var Wo=_e("[SegmentIntegration]"),Yf="posthog-js";function Jf(t,e){var n=e===void 0?{}:e,i=n.organization,r=n.projectId,s=n.prefix,o=n.severityAllowList,a=o===void 0?["error"]:o,l=n.sendExceptionsToPostHog,u=l===void 0||l;return c=>{var d,f,p,h,g;if(a!=="*"&&!a.includes(c.level)||!t.__loaded)return c;c.tags||(c.tags={});var m=t.requestRouter.endpointFor("ui","/project/"+t.config.token+"/person/"+t.get_distinct_id());c.tags["PostHog Person URL"]=m,t.sessionRecordingStarted()&&(c.tags["PostHog Recording URL"]=t.get_session_replay_url({withTimestamp:!0}));var v,x=((d=c.exception)==null?void 0:d.values)||[],E=x.map((b=>k({},b,{stacktrace:b.stacktrace?k({},b.stacktrace,{type:"raw",frames:(b.stacktrace.frames||[]).map((I=>k({},I,{platform:"web:javascript"})))}):void 0}))),y={$exception_message:((f=x[0])==null?void 0:f.value)||c.message,$exception_type:(p=x[0])==null?void 0:p.type,$exception_level:c.level,$exception_list:E,$sentry_event_id:c.event_id,$sentry_exception:c.exception,$sentry_exception_message:((h=x[0])==null?void 0:h.value)||c.message,$sentry_exception_type:(g=x[0])==null?void 0:g.type,$sentry_tags:c.tags};return i&&r&&(y.$sentry_url=(s||"https://sentry.io/organizations/")+i+"/issues/?project="+r+"&query="+c.event_id),u&&((v=t.exceptions)==null||v.sendExceptionEvent(y)),c}}class jm{constructor(e,n,i,r,s,o){this.name=Yf,this.setupOnce=function(a){a(Jf(e,{organization:n,projectId:i,prefix:r,severityAllowList:s,sendExceptionsToPostHog:o==null||o}))}}}class _u{constructor(e){this.li=(n,i,r)=>{r&&(r.noSessionId||r.activityTimeout||r.sessionPastMaximumLength||r.crossTabAdoption)&&(P.info("[PageViewManager] Session rotated, clearing pageview state",{sessionId:n,changeReason:r}),this.ui=void 0,this._instance.scrollManager.resetContext())},this._instance=e,this.hi()}hi(){var e;this.di=(e=this._instance.sessionManager)==null?void 0:e.onSessionId(this.li)}destroy(){var e;(e=this.di)==null||e.call(this),this.di=void 0}doPageView(e,n){var i,r=this.vi(e,n);return this.ui={pathname:(i=w?.location.pathname)!==null&&i!==void 0?i:"",pageViewId:n,timestamp:e},this._instance.scrollManager.resetContext(),r}doPageLeave(e){var n;return this.vi(e,(n=this.ui)==null?void 0:n.pageViewId)}doEvent(){var e;return{$pageview_id:(e=this.ui)==null?void 0:e.pageViewId}}vi(e,n){var i=this.ui;if(!i)return{$pageview_id:n};var r={$pageview_id:n,$prev_pageview_id:i.pageViewId},s=this._instance.scrollManager.getContext();if(s&&!this._instance.config.disable_scroll_properties){var o=s.maxScrollHeight,a=s.lastScrollY,l=s.maxScrollY,u=s.maxContentHeight,c=s.lastContentY,d=s.maxContentY;if(!(A(o)||A(a)||A(l)||A(u)||A(c)||A(d))){o=Math.ceil(o),a=Math.ceil(a),l=Math.ceil(l),u=Math.ceil(u),c=Math.ceil(c),d=Math.ceil(d);var f=o>1?Nt(a/o,0,1,P):1,p=o>1?Nt(l/o,0,1,P):1,h=u>1?Nt(c/u,0,1,P):1,g=u>1?Nt(d/u,0,1,P):1;r=ve(r,{$prev_pageview_last_scroll:a,$prev_pageview_last_scroll_percentage:f,$prev_pageview_max_scroll:l,$prev_pageview_max_scroll_percentage:p,$prev_pageview_last_content:c,$prev_pageview_last_content_percentage:h,$prev_pageview_max_content:d,$prev_pageview_max_content_percentage:g})}}return i.pathname&&(r.$prev_pageview_pathname=i.pathname),i.timestamp&&(r.$prev_pageview_duration=(e.getTime()-i.timestamp.getTime())/1e3),r}}var qo=["flags","surveys"],Um={[kf]:{exposure:"hidden"},[Wi]:{exposure:"hidden"},__cmpns:{exposure:"hidden"},[qi]:{exposure:"hidden"},[Ea]:{exposure:"event"},[Sa]:{exposure:"hidden"},[xa]:{exposure:"event"},[Ia]:{exposure:"hidden"},[ka]:{exposure:"event"},[Ca]:{exposure:"event"},[Fl]:{exposure:"event"},[Rl]:{exposure:"hidden"},[Aa]:{exposure:"event"},[jn]:{exposure:"hidden"},$session_recording_enabled_server_side:{exposure:"hidden"},[si]:{exposure:"hidden"},[Tl]:{exposure:"event"},[Cf]:{exposure:"event",shouldSkipFromEventProperties:t=>it(t)},$session_past_minimum_duration:{exposure:"event"},$session_recording_url_trigger_activated_session:{exposure:"event"},$session_recording_event_trigger_activated_session:{exposure:"event"},$debug_first_full_snapshot_timestamp:{exposure:"event"},$sess_rec_flush_size:{exposure:"hidden"},[Ln]:{exposure:"hidden",storageGroup:"flags"},[zi]:{exposure:"hidden",storageGroup:"flags"},[Kr]:{exposure:"hidden"},[Pa]:{exposure:"hidden",storageGroup:"flags"},[Vi]:{exposure:"hidden",storageGroup:"flags"},[Yr]:{exposure:"hidden",storageGroup:"flags",volatile:!0},[ys]:{exposure:"hidden",storageGroup:"flags"},[Mt]:{exposure:"hidden"},[Nn]:{exposure:"hidden"},[Jt]:{exposure:"hidden"},[On]:{exposure:"hidden"},[Fa]:{exposure:"hidden",storageGroup:"surveys"},[_s]:{exposure:"hidden",storageGroup:"surveys",volatile:!0},[Ra]:{exposure:"event"},[Jr]:{exposure:"hidden"},[Zr]:{exposure:"hidden"},[Gi]:{exposure:"hidden"},$product_tours_activated:{exposure:"hidden"},$product_tours_activated_session:{exposure:"hidden"},$conversations_widget_session_id:{exposure:"event"},$conversations_ticket_id:{exposure:"event"},$conversations_widget_state:{exposure:"event"},$conversations_user_traits:{exposure:"event"},[Dn]:{exposure:"hidden"},[Ki]:{exposure:"hidden"},[Xr]:{exposure:"hidden"},[Qi]:{exposure:"hidden",storageGroup:"flags",volatile:!0},[yt]:{exposure:"hidden"},[Ta]:{exposure:"hidden"},[Ma]:{exposure:"hidden"},[$a]:{exposure:"hidden"},[La]:{exposure:"hidden"},[ws]:{exposure:"hidden"},[bs]:{exposure:"hidden"},[Af]:{exposure:"event"},[Pf]:{exposure:"event"},[Ff]:{exposure:"event"},[Rf]:{exposure:"event"},[Mf]:{exposure:"event"},[$f]:{exposure:"event"},[Lf]:{exposure:"event"},$sdk_debug_replay_event_trigger_status:{exposure:"event"},$sdk_debug_replay_linked_flag_trigger_status:{exposure:"event"},$sdk_debug_replay_matched_recording_trigger_groups:{exposure:"event"},$sdk_debug_replay_remote_trigger_matching_config:{exposure:"event"},$sdk_debug_replay_trigger_groups_count:{exposure:"event"},$sdk_debug_replay_url_trigger_status:{exposure:"event"},$session_recording_start_reason:{exposure:"event"}},Hm=[["$posthog_sr_group_event_trigger_",{exposure:"hidden"}],["$posthog_sr_group_url_trigger_",{exposure:"hidden"}],["$posthog_sr_group_sampling_",{exposure:"hidden"}]],Rn=t=>{var e=Um[t];if(e)return e;for(var n of Hm){var i=n[1];if(t.indexOf(n[0])===0)return i}},oi=(t,e)=>{try{return JSON.stringify(t,((n,i)=>typeof i=="bigint"?i.toString():i),e)}catch{return Vd(t)}},ks=t=>{var e=F?.createElement("a");return A(e)?null:(e.href=t,e)},mi=function(t,e){for(var n,i=((t.split("#")[0]||"").split(/\?(.*)/)[1]||"").replace(/^\?+/g,"").split("&"),r=0;i.length>r;r++){var s=i[r].split("=");if(s[0]===e){n=s;break}}if(!U(n)||2>n.length)return"";var o=n[1];try{o=decodeURIComponent(o)}catch{P.error("Skipping decoding for malformed query param: "+o)}return o.replace(/\+/g," ")},ur=function(t,e,n){if(!t||!e||!e.length)return t;for(var i=t.split("#"),r=i[1],s=(i[0]||"").split("?"),o=s[1],a=s[0],l=(o||"").split("&"),u=[],c=0;l.length>c;c++){var d=l[c].split("=");U(d)&&(e.includes(d[0])?u.push(d[0]+"="+n):u.push(l[c]))}var f=a;return o!=null&&(f+="?"+u.join("&")),r!=null&&(f+="#"+r),f},Cs=function(t,e){var n=t.match(new RegExp(e+"=([^&]*)"));return n?n[1]:null},Zf=(t,e)=>t>=e&&Wd(),Xf=(t,e,n,i)=>{if(t===0){if(Wd()){var r=e+1;return r===n&&i(),r}return e}return 0},jr="https?://(.*)",vi=["gclid","gclsrc","dclid","gbraid","wbraid","fbclid","msclkid","twclid","li_fat_id","igshid","ttclid","rdt_cid","epik","qclid","sccid","irclid","_kx"],Wm=["utm_source","utm_medium","utm_campaign","utm_content","utm_term","gad_source","mc_cid",...vi],dr="",qm=["li_fat_id"];function Qf(t,e,n){if(!F)return{};var i,r=e?[...vi,...n||[]]:[],s=eh(ur(F.URL,r,dr),t),o=(i={},ae(qm,(function(a){var l=Nf(a);i[a]=l||null})),i);return ve(o,s)}function eh(t,e){var n=Wm.concat(e||[]),i={};return ae(n,(function(r){var s=mi(t,r);i[r]=s||null})),i}function th(t){var e=(function(s){return s?s.search(jr+"google.([^/?]*)")===0?"google":s.search(jr+"bing.com")===0?"bing":s.search(jr+"yahoo.com")===0?"yahoo":s.search(jr+"duckduckgo.com")===0?"duckduckgo":null:null})(t),n=e!="yahoo"?"q":"p",i={};if(!it(e)){i.$search_engine=e;var r=F?mi(F.referrer,n):"";r.length&&(i.ph_keyword=r)}return i}function wu(){return navigator.language||navigator.userLanguage}var As="$direct";function nh(){return F?.referrer||As}function ih(t,e,n){n===void 0&&(n=!1);var i=t?[...vi,...e||[]]:[],r=n?Sn(Ee?.href):Ee?.href,s=r?.substring(0,1e3);return{r:nh().substring(0,1e3),u:s?ur(s,i,dr):void 0}}function rh(t,e){var n;e===void 0&&(e=!1);var i=t.r,r=t.u,s=e?Sn(r):r,o={$referrer:i,$referring_domain:i==null?void 0:i==As?As:(n=ks(i))==null?void 0:n.host};if(s){o.$current_url=s;var a=ks(s);o.$host=a?.host,o.$pathname=a?.pathname;var l=eh(s);ve(o,l)}if(i){var u=th(i);ve(o,u)}return o}function sh(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone}catch{return}}function zm(){try{return new Date().getTimezoneOffset()}catch{return}}var Vm={flags:Qi,surveys:_s},Gm=["cookie","localstorage","localstorage+cookie","sessionstorage","memory"],Qn="main";class zo{constructor(e,n,i){if(i===void 0&&(i=!0),this.ci={},this.fi=!1,this.pi=!1,this.Ne=e,this.gi=i,this.props={},this.mi=void 0,this.yi=(s=>{var o="";return s.token&&(o=s.token.replace(/\+/g,"PL").replace(/\//g,"SL").replace(/=/g,"EQ")),s.persistence_name?"ph_"+s.persistence_name:"ph_"+o+"_posthog"})(e),this.ii=this.bi(e),this.pi=this.wi(e),this.load(),e.debug&&P.info("Persistence loaded",e.persistence,k({},this.props)),this.update_config(e,e,n),this.save(),w){var r=()=>this.flush();Se(w,"beforeunload",r,{capture:!1}),Se(w,"pagehide",r,{capture:!1})}}ki(){var e,n=(e=this.Ne)==null?void 0:e.persistence_save_debounce_ms;return Fe(n)&&n>0?n:0}isDisabled(){return!!this.xi}bi(e){Gm.indexOf(e.persistence.toLowerCase())===-1&&(P.critical("Unknown persistence type "+e.persistence+"; falling back to localStorage+cookie"),e.persistence="localStorage+cookie");var n,i=(function(o,a){o===void 0&&(o=[]),a===void 0&&(a=!1);var l=[...Im,...o];return k({},fe,{H(u){try{var c={};try{c=nn.H(u)||{}}catch{}var d,f=JSON.parse(fe.P(u)||"{}");if(a){var p={};for(var h in c){var g=c[h];it(g)||g===""||(p[h]=g)}d=ve(f,p)}else d=ve(c,f);return fe.F(u,d),d}catch{}return null},F(u,c,d,f,p,h){var g=fe.F(u,c,void 0,void 0,h);try{var m={};l.forEach((v=>{c[v]&&(m[v]=c[v])})),Object.keys(m).length&&nn.F(u,m,d,f,p,h)}catch(v){fe.j(v)}return g},q(u,c){try{w?.localStorage.removeItem(u),nn.q(u,c)}catch(d){fe.j(d)}}})})(e.cookie_persisted_properties||[],e.__preview_cookie_wins_on_conflict||!1),r=!1,s=e.persistence.toLowerCase();return s==="localstorage"&&fe.N()?(n=fe,r=!0):s==="localstorage+cookie"&&i.N()?(n=i,r=!0):s==="sessionstorage"&&Ce.N()?n=Ce:s==="memory"?n=km:s==="cookie"?n=nn:i.N()?(n=i,r=!0):n=nn,this.fi=r,n}Si(e){return this.yi+"__"+e}wi(e){return this.fi&&!!e.split_storage}properties(){var e={};return ae(this.props,((n,i)=>{var r=Rn(i);if(!r||r.exposure==="event"){if(r!=null&&r.shouldSkipFromEventProperties!=null&&r.shouldSkipFromEventProperties(n))return;e[i]=n}})),e}load(){if(!this.xi){var e=this.ii.H(this.yi);e&&(this.props=ve({},e)),this.pi&&this.Ci()}}Ci(){for(var e of qo){var n=fe.H(this.Si(e));if(n&&!an(n)){var i=this.Mi(e);i.persisted=!0,this.Ti(e)||(i.fingerprint=this.Ei(n,e)),this.Ii(e,n)||ve(this.props,n)}}}Ti(e){return Object.keys(this.props).some((n=>{var i;return((i=Rn(n))==null?void 0:i.storageGroup)===e}))}Ii(e,n){var i=Vm[e];if(!i)return!1;var r=n[i],s=this.props[i];return Fe(r)&&Fe(s)&&s>r}refreshKey(e){var n;if(!this.xi){var i=this.pi?(n=Rn(e))==null?void 0:n.storageGroup:void 0,r=i?fe.H(this.Si(i)):this.ii.H(this.yi);if(r&&e in r)this.Pi(e,r[e]);else{if(i){var s=this.ii.H(this.yi);if(s&&e in s)return void this.Pi(e,s[e])}this.Ri(e)}}}save(){if(!this.xi){var e=this.ki();e>0?A(this.Ai)&&(this.Ai=setTimeout((()=>{this.Ai=void 0,this.Fi()}),e)):this.Fi()}}flush(){A(this.Ai)||(clearTimeout(this.Ai),this.Ai=void 0,this.Fi())}Fi(){this.xi||(this.pi?this.Li():this.Oi(this.ii,this.yi,this.props,Qn))}Li(){var e=this.Di(),n=e.main,i=e.groups;for(var r of(this.Oi(this.ii,this.yi,n,Qn),qo)){var s,o=i[r];(!an(o)||(s=this.ci[r])!=null&&s.persisted)&&this.Oi(fe,this.Si(r),o,r)}}Di(){var e={},n={flags:{},surveys:{}};return ae(this.props,((i,r)=>{var s,o=(s=Rn(r))==null?void 0:s.storageGroup;o?n[o][r]=i:e[r]=i})),{main:e,groups:n}}Ei(e,n){if(n===Qn)return JSON.stringify(e)+"|"+this.$i+"|"+this.Ni+"|"+this.qi;var i={};return ae(e,((r,s)=>{var o;i[s]=(o=Rn(s))!=null&&o.volatile?"__volatile__":r})),JSON.stringify(i)}Oi(e,n,i,r){var s=this.Mi(r);if(r===Qn||s.dirty||A(s.fingerprint)){var o;try{if((o=this.Ei(i,r))===s.fingerprint)return void(s.dirty=!1)}catch{o=void 0}e.F(n,i,this.$i,this.Ni,this.qi,this.Ne.debug)?(s.dirty=!1,r!==Qn&&(s.persisted=!0),A(o)||(s.fingerprint=o)):this.Ne.debug&&P.warn('failed to persist storage entry "'+n+'"; will retry on next save')}}remove(e){var n=(e===void 0?{}:e).keepGroupEntries,i=n!==void 0&&n;if(A(this.Ai)||(clearTimeout(this.Ai),this.Ai=void 0),this.ii.q(this.yi,!1),this.ii.q(this.yi,!0),!i&&this.gi)for(var r of qo)fe.q(this.Si(r));i?delete this.ci[Qn]:this.ci={}}clear(){this.remove(),this.props={}}register_once(e,n,i){if(ye(e)){A(n)&&(n="None"),this.$i=A(i)?this.ji:i;var r=!1;if(ae(e,((s,o)=>{this.props.hasOwnProperty(o)&&this.props[o]!==n||(this.Pi(o,s),r=!0)})),r)return this.save(),!0}return!1}register(e,n){if(ye(e)){this.$i=A(n)?this.ji:n;var i=!1;if(ae(e,((r,s)=>{e.hasOwnProperty(s)&&(this.props[s]!==r||ye(r)||U(r))&&(this.Pi(s,r),i=!0)})),i)return this.save(),!0}return!1}unregister(e){var n=typeof e=="string"?[e]:e,i=!1;for(var r of n)r in this.props&&(this.Ri(r),i=!0);i&&this.save()}update_campaign_params(){var e=F?.URL;if(e!==this.mi){var n=Qf(this.Ne.custom_campaign_params,this.Ne.mask_personal_data_properties,this.Ne.custom_personal_data_properties);an($l(n))||this.register(n),this.mi=e}}update_search_keyword(){var e;this.register((e=F?.referrer)?th(e):{})}update_referrer_info(){var e;this.register_once({$referrer:nh(),$referring_domain:F!=null&&F.referrer&&((e=ks(F.referrer))==null?void 0:e.host)||As},void 0)}set_initial_person_info(){this.props[$a]||this.props[La]||this.register_once({[ws]:ih(this.Ne.mask_personal_data_properties,this.Ne.custom_personal_data_properties,this.Ne.disable_capture_url_hashes)},void 0)}get_initial_props(){var e={};ae([La,$a],(r=>{var s=this.props[r];s&&ae(s,(function(o,a){e["$initial_"+ga(a)]=o}))}));var n=this.props[ws];if(n){var i=(function(r,s){s===void 0&&(s=!1);var o=rh(r,s),a={};return ae(o,(function(l,u){a["$initial_"+ga(u)]=l})),a})(n,this.Ne.disable_capture_url_hashes);ve(e,i)}return e}safe_merge(e){return ae(this.props,(function(n,i){i in e||(e[i]=n)})),e}update_config(e,n,i){this.ji=this.$i=e.cookie_expiration,this.set_disabled(e.disable_persistence||!!i),this.set_cross_subdomain(e.cross_subdomain_cookie),this.set_secure(e.secure_cookie);var r=e.persistence!==n.persistence||!((l,u)=>{if(l.length!==u.length)return!1;var c=[...l].sort(),d=[...u].sort();return c.every(((f,p)=>f===d[p]))})(e.cookie_persisted_properties||[],n.cookie_persisted_properties||[]),s=r?this.bi(e):this.ii,o=this.wi(e);if(r||o!==this.pi){var a=this.props;this.clear(),this.ii=s,this.pi=o,this.props=a,this.save()}}set_disabled(e){this.xi=e,this.xi?this.remove():this.save()}set_cross_subdomain(e){e!==this.Ni&&(this.Ni=e,this.remove({keepGroupEntries:!0}),this.save())}set_secure(e){e!==this.qi&&(this.qi=e,this.remove({keepGroupEntries:!0}),this.save())}set_event_timer(e,n){var i=this.props[qi]||{};i[e]=n,this.Pi(qi,i),this.save()}remove_event_timer(e){var n=this.props[qi]||{},i=n[e];return A(i)||(delete n[e],this.Pi(qi,n),this.save()),i}get_property(e){return this.props[e]}set_property(e,n){this.Pi(e,n),this.save()}Pi(e,n){var i;this.props[e]=n,(i=Rn(e))!=null&&i.volatile||this.Bi(e)}Ri(e){delete this.props[e],this.Bi(e)}Bi(e){var n,i=(n=Rn(e))==null?void 0:n.storageGroup;i&&(this.Mi(i).dirty=!0)}Mi(e){return this.ci[e]||(this.ci[e]={})}}function Ur(t){var e=!0;return{dispose(){if(e){e=!1;var n=t();n&&qe(n.then)&&n.then(void 0,(()=>{}))}}}}var ze={GZipJS:"gzip-js",Base64:"base64"},Mi={Activation:"events",Cancellation:"cancelEvents"},Vo={Popover:"popover",API:"api",Widget:"widget"},rn={SHOWN:"survey shown",DISMISSED:"survey dismissed",SENT:"survey sent"},Go={SURVEY_ID:"$survey_id",SURVEY_ITERATION:"$survey_iteration",SURVEY_LAST_SEEN_DATE:"$survey_last_seen_date"},ja={Popover:"popover",Inline:"inline"},Km={SHOWN:"product tour shown"},bu={TOUR_LAST_SEEN_DATE:"$product_tour_last_seen_date",TOUR_TYPE:"$product_tour_type"},Eu=_e("[RateLimiter]");class Ym{constructor(e){this.serverLimits={},this.lastEventRateLimited=!1,this.checkForLimiting=n=>{var i=n.text;if(i&&i.length)try{(JSON.parse(i).quota_limited||[]).forEach((r=>{Eu.info((r||"events")+" is quota limited."),this.serverLimits[r]=new Date().getTime()+6e4}))}catch(r){return void Eu.warn('could not rate limit - continuing. Error: "'+r?.message+'"',{text:i})}},this.instance=e,this.lastEventRateLimited=this.clientRateLimitContext(!0).isRateLimited}get captureEventsPerSecond(){var e;return((e=this.instance.config.rate_limiting)==null?void 0:e.events_per_second)||10}get captureEventsBurstLimit(){var e;return Math.max(((e=this.instance.config.rate_limiting)==null?void 0:e.events_burst_limit)||10*this.captureEventsPerSecond,this.captureEventsPerSecond)}clientRateLimitContext(e){var n,i,r;e===void 0&&(e=!1);var s=this.captureEventsBurstLimit,o=this.captureEventsPerSecond,a=new Date().getTime(),l=(n=(i=this.instance.persistence)==null?void 0:i.get_property(Ma))!==null&&n!==void 0?n:{tokens:s,last:a};l.tokens+=(a-l.last)/1e3*o,l.last=a,l.tokens>s&&(l.tokens=s);var u=1>l.tokens;if(u||e||(l.tokens=Math.max(0,l.tokens-1)),u&&!e){var c=(Fe(l.dropped)?l.dropped:0)+1;l.dropped=c,!this.lastEventRateLimited&&this.Hi(c)&&(l.dropped=0)}return this.lastEventRateLimited=u,(r=this.instance.persistence)==null||r.set_property(Ma,l),{isRateLimited:u,remainingTokens:l.tokens}}Ui(e){var n=this.instance.config.property_denylist;return!U(n)||!n.includes(e)}zi(){var e;if(this.Ui("$current_url")&&this.Ui("$pathname")&&Ee!=null&&Ee.pathname)return""+((e=Ee.origin)!==null&&e!==void 0?e:"")+Ee.pathname}Hi(e){var n,i,r=this.captureEventsBurstLimit,s=this.captureEventsPerSecond,o=this.zi(),a=this.Ui("$session_id")?(n=(i=this.instance).get_session_id)==null?void 0:n.call(i):void 0,l=[e+" event(s) dropped since the last warning",o?"triggered on "+o:void 0,a?"session "+a:void 0].filter(Boolean).join(", ");return!!this.instance.capture("$$client_ingestion_warning",{$$client_ingestion_warning_message:"posthog-js client rate limited: "+l+". Config is set to "+s+" events per second and "+r+" events burst limit."},{skip_client_rate_limiting:!0})}isServerRateLimited(e){var n=this.serverLimits[e||"events"]||!1;return n!==!1&&new Date().getTime()e(this.remoteConfig))):e()}Vi(e){this._instance._send_request({method:"GET",url:this._instance.requestRouter.endpointFor("assets","/array/"+this._instance.config.token+"/config"),callback:e})}load(){try{if(this.remoteConfig)return _n.info("Using preloaded remote config",this.remoteConfig),this.Zi(this.remoteConfig),void this.Gi();if(this._instance.Qi())return void _n.warn("Remote config is disabled. Falling back to local config.");this.Wi((e=>{if(!e)return _n.info("No config found after loading remote JS config. Falling back to JSON."),void this.Vi((n=>{this.Zi(n.json,n),this.Gi()}));this.Zi(e),this.Gi()}))}catch(e){_n.error("Error loading remote config",e),this.Zi()}}stop(){this.Ki&&(clearInterval(this.Ki),this.Ki=void 0)}refresh(){!this._instance.Qi()&&F&&F.visibilityState!=="hidden"&&this._instance.reloadFeatureFlags()}Gi(){var e;if(!this.Ki){var n=(e=this._instance.config.remote_config_refresh_interval_ms)!==null&&e!==void 0?e:3e5;n!==0&&(this.Ki=setInterval((()=>{this.refresh()}),n))}}Zi(e,n){!e&&n&&(n.statusCode===0?n.error||_n.warn("Failed to fetch remote config from PostHog."):_n.error("Failed to fetch remote config from PostHog."));try{this._instance.Zi(e?{ok:!0,config:e}:{ok:!1})}catch(r){_n.error("Error applying remote config",r)}if(e?.hasFeatureFlags!==!1&&!this._instance.config.advanced_disable_feature_flags_on_first_load)try{var i;(i=this._instance.featureFlags)==null||i.ensureFlagsLoaded()}catch(r){_n.error("Error loading feature flags",r)}}}var wt=Uint8Array,nt=Uint16Array,yi=Uint32Array,Bl=new wt([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),Dl=new wt([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),Su=new wt([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),ah=function(t,e){for(var n=new nt(31),i=0;31>i;++i)n[i]=e+=1<i;++i)for(var s=n[i];n[i+1]>s;++s)r[s]=s-n[i]<<5|i;return[n,r]},lh=ah(Bl,2),Ua=lh[1];lh[0][28]=258,Ua[258]=28;for(var xu=ah(Dl,0)[1],ch=new nt(32768),xe=0;32768>xe;++xe){var ei=(43690&xe)>>>1|(21845&xe)<<1;ch[xe]=((65280&(ei=(61680&(ei=(52428&ei)>>>2|(13107&ei)<<2))>>>4|(3855&ei)<<4))>>>8|(255&ei)<<8)>>>1}var tr=function(t,e,n){for(var i=t.length,r=0,s=new nt(e);i>r;++r)++s[t[r]-1];var o,a=new nt(e);for(r=0;e>r;++r)a[r]=a[r-1]+s[r-1]<<1;for(o=new nt(i),r=0;i>r;++r)o[r]=ch[a[t[r]-1]++]>>>15-t[r];return o},Vn=new wt(288);for(xe=0;144>xe;++xe)Vn[xe]=8;for(xe=144;256>xe;++xe)Vn[xe]=9;for(xe=256;280>xe;++xe)Vn[xe]=7;for(xe=280;288>xe;++xe)Vn[xe]=8;var Ps=new wt(32);for(xe=0;32>xe;++xe)Ps[xe]=5;var Jm=tr(Vn,9),Zm=tr(Ps,5),uh=function(t){return(t/8>>0)+(7&t&&1)},dh=function(t,e,n){(n==null||n>t.length)&&(n=t.length);var i=new(t instanceof nt?nt:t instanceof yi?yi:wt)(n-e);return i.set(t.subarray(e,n)),i},Gt=function(t,e,n){var i=e/8>>0;t[i]|=n<<=7&e,t[i+1]|=n>>>8},$i=function(t,e,n){var i=e/8>>0;t[i]|=n<<=7&e,t[i+1]|=n>>>8,t[i+2]|=n>>>16},Ko=function(t,e){for(var n=[],i=0;t.length>i;++i)t[i]&&n.push({s:i,f:t[i]});var r=n.length,s=n.slice();if(!r)return[new wt(0),0];if(r==1){var o=new wt(n[0].s+1);return o[n[0].s]=1,[o,1]}n.sort((function(b,I){return b.f-I.f})),n.push({s:-1,f:25001});var a=n[0],l=n[1],u=0,c=1,d=2;for(n[0]={s:-1,f:a.f+l.f,l:a,r:l};c!=r-1;)a=n[n[d].f>n[u].f?u++:d++],l=n[u!=c&&n[d].f>n[u].f?u++:d++],n[c++]={s:-1,f:a.f+l.f,l:a,r:l};var f=s[0].s;for(i=1;r>i;++i)s[i].s>f&&(f=s[i].s);var p=new nt(f+1),h=Ha(n[c-1],p,0);if(h>e){i=0;var g=0,m=h-e,v=1<i;++i){var x=s[i].s;if(e>=p[x])break;g+=v-(1<>>=m;g>0;){var E=s[i].s;e>p[E]?g-=1<=0&&g;--i){var y=s[i].s;p[y]==e&&(--p[y],++g)}h=e}return[new wt(p),h]},Ha=function(t,e,n){return t.s==-1?Math.max(Ha(t.l,e,n+1),Ha(t.r,e,n+1)):e[t.s]=n},Iu=function(t){for(var e=t.length;e&&!t[--e];);for(var n=new nt(++e),i=0,r=t[0],s=1,o=function(l){n[i++]=l},a=1;e>=a;++a)if(t[a]==r&&a!=e)++s;else{if(!r&&s>2){for(;s>138;s-=138)o(32754);s>2&&(o(s>10?s-11<<5|28690:s-3<<5|12305),s=0)}else if(s>3){for(o(r),--s;s>6;s-=6)o(8304);s>2&&(o(s-3<<5|8208),s=0)}for(;s--;)o(r);s=1,r=t[a]}return[n.subarray(0,i),e]},Li=function(t,e){for(var n=0,i=0;e.length>i;++i)n+=t[i]*e[i];return n},Wa=function(t,e,n){var i=n.length,r=uh(e+2);t[r]=255&i,t[r+1]=i>>>8,t[r+2]=255^t[r],t[r+3]=255^t[r+1];for(var s=0;i>s;++s)t[r+s+4]=n[s];return 8*(r+4+i)},ku=function(t,e,n,i,r,s,o,a,l,u,c){Gt(e,c++,n),++r[256];for(var d=Ko(r,15),f=d[0],p=d[1],h=Ko(s,15),g=h[0],m=h[1],v=Iu(f),x=v[0],E=v[1],y=Iu(g),b=y[0],I=y[1],T=new nt(19),S=0;x.length>S;++S)T[31&x[S]]++;for(S=0;b.length>S;++S)T[31&b[S]]++;for(var C=Ko(T,7),R=C[0],O=C[1],L=19;L>4&&!R[Su[L-1]];--L);var N,J,G,M,K=u+5<<3,ie=Li(r,Vn)+Li(s,Ps)+o,ue=Li(r,f)+Li(s,g)+o+14+3*L+Li(T,R)+(2*T[16]+3*T[17]+7*T[18]);if(ie>=K&&ue>=K)return Wa(e,c,t.subarray(l,l+u));if(Gt(e,c,1+(ie>ue)),c+=2,ie>ue){N=tr(f,p),J=f,G=tr(g,m),M=g;var we=tr(R,O);for(Gt(e,c,E-257),Gt(e,c+5,I-1),Gt(e,c+10,L-4),c+=14,S=0;L>S;++S)Gt(e,c+3*S,R[Su[S]]);c+=3*L;for(var be=[x,b],Re=0;2>Re;++Re){var Q=be[Re];for(S=0;Q.length>S;++S)Gt(e,c,we[de=31&Q[S]]),c+=R[de],de>15&&(Gt(e,c,Q[S]>>>5&127),c+=Q[S]>>>12)}}else N=Jm,J=Vn,G=Zm,M=Ps;for(S=0;a>S;++S)if(i[S]>255){var de;$i(e,c,N[257+(de=i[S]>>>18&31)]),c+=J[de+257],de>7&&(Gt(e,c,i[S]>>>23&31),c+=Bl[de]);var pe=31&i[S];$i(e,c,G[pe]),c+=M[pe],pe>3&&($i(e,c,i[S]>>>5&8191),c+=Dl[pe])}else $i(e,c,N[i[S]]),c+=J[i[S]];return $i(e,c,N[256]),c+J[256]},Xm=new yi([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),Qm=(function(){for(var t=new yi(256),e=0;256>e;++e){for(var n=e,i=9;--i;)n=(1&n&&3988292384)^n>>>1;t[e]=n}return t})(),Yo=function(t,e,n){for(;n;++e)t[e]=n,n>>>=8};function ev(t,e){e===void 0&&(e={});var n=(function(){var d=4294967295;return{p(f){for(var p=d,h=0;f.length>h;++h)p=Qm[255&p^f[h]]^p>>>8;d=p},d(){return 4294967295^d}}})(),i=t.length;n.p(t);var r,s,o,a,l,u=(a=10+((r=e).filename&&r.filename.length+1||0),l=8,(function(d,f,p,h,g,m){var v=d.length,x=new wt(h+v+5*(1+Math.floor(v/7e3))+g),E=x.subarray(h,x.length-g),y=0;if(!f||8>v)for(var b=0;v>=b;b+=65535){var I=b+65535;v>I?y=Wa(E,y,d.subarray(b,I)):(E[b]=!0,y=Wa(E,y,d.subarray(b,v)))}else{for(var T=Xm[f-1],S=T>>>13,C=8191&T,R=(1<b;++b){var de=G(b),pe=32767&b,Ne=L[de];if(O[pe]=Ne,L[de]=pe,b>=Re){var pt=v-b;if((ue>7e3||be>24576)&&pt>423){y=ku(d,E,0,M,K,ie,we,be,Q,b-Q,y),be=ue=we=0,Q=b;for(var re=0;286>re;++re)K[re]=0;for(re=0;30>re;++re)ie[re]=0}var We=2,Je=0,Pt=C,$=pe-Ne&32767;if(pt>2&&de==G(b-$))for(var ee=Math.min(S,pt)-1,Be=Math.min(32767,b),Ze=Math.min(258,pt);Be>=$&&--Pt&&pe!=Ne;){if(d[b+We]==d[b+We-$]){for(var Te=0;Ze>Te&&d[b+Te]==d[b+Te-$];++Te);if(Te>We){if(We=Te,Je=$,Te>ee)break;var qt=Math.min($,Te-2),gt=0;for(re=0;qt>re;++re){var rt=b-$+re+32768&32767,mt=rt-O[rt]+32768&32767;mt>gt&&(gt=mt,Ne=rt)}}}$+=(pe=Ne)-(Ne=O[pe])+32768&32767}if(Je){M[be++]=268435456|Ua[We]<<18|xu[Je];var zt=31&Ua[We],Ai=31&xu[Je];we+=Bl[zt]+Dl[Ai],++K[257+zt],++ie[Ai],Re=b+We,++ue}else M[be++]=d[b],++K[d[b]]}}y=ku(d,E,!0,M,K,ie,we,be,Q,b-Q,y)}return dh(x,0,h+uh(y)+g)})(s=t,(o=e).level==null?6:o.level,o.mem==null?Math.ceil(1.5*Math.max(8,Math.min(13,Math.log(s.length)))):12+o.mem,a,l)),c=u.length;return(function(d,f){var p=f.filename;if(d[0]=31,d[1]=139,d[2]=8,d[8]=2>f.level?4:f.level==9?2:0,d[9]=3,f.mtime!=0&&Yo(d,4,Math.floor(new Date(f.mtime||Date.now())/1e3)),p){d[3]=8;for(var h=0;p.length>=h;++h)d[h+10]=p.charCodeAt(h)}})(u,e),Yo(u,c-8,n.d()),Yo(u,c-4,i),u}var tv=!!fa||!!Sl,fh="text/plain",es=!1,hh=(t,e)=>{var n=t.split("#"),i=n[1],r=n[0].split("?"),s=r[0],o=r[1];if(!o)return t;var a=o.split("&").filter((l=>l.split("=")[0]!==e)).join("&");return s+(a?"?"+a:"")+(i?"#"+i:"")},Js=function(t,e,n){var i;n===void 0&&(n=!0);var r=t.split("?"),s=r[0],o=r[1],a=k({},e),l=(i=o?.split("&").map((c=>{var d,f=c.split("="),p=f[0],h=n&&(d=a[p])!==null&&d!==void 0?d:f[1];return delete a[p],p+"="+h})))!==null&&i!==void 0?i:[],u=(function(c,d){var f,p;d===void 0&&(d="&");var h=[];return ae(c,(function(g,m){A(g)||A(m)||m==="undefined"||(f=encodeURIComponent((v=>v instanceof File)(g)?g.name:g.toString()),p=encodeURIComponent(m),h[h.length]=p+"="+f)})),h.join(d)})(a);return u&&l.push(u),l.length>0?s+"?"+l.join("&"):s},Jo=t=>{if(t.Ji)return t.Ji;var e=t.data,n=t.compression;if(e){if(n===ze.GZipJS){var i=ev((function(a,l){var u=a.length;if(typeof TextEncoder<"u")return new TextEncoder().encode(a);for(var c=new wt(a.length+(a.length>>>1)),d=0,f=function(m){c[d++]=m},p=0;u>p;++p){if(d+5>c.length){var h=new wt(d+8+(u-p<<1));h.set(c),c=h}var g=a.charCodeAt(p);128>g?f(g):2048>g?(f(192|g>>>6),f(128|63&g)):g>55295&&57344>g?(f(240|(g=65536+(1047552&g)|1023&a.charCodeAt(++p))>>>18),f(128|g>>>12&63),f(128|g>>>6&63),f(128|63&g)):(f(224|g>>>12),f(128|g>>>6&63),f(128|63&g))}return dh(c,0,d)})(oi(e)),{mtime:0});return{contentType:fh,body:i.buffer.slice(i.byteOffset,i.byteOffset+i.byteLength),estimatedSize:i.byteLength}}if(n===ze.Base64){var r=(function(a){return a&&btoa(encodeURIComponent(a).replace(/%([0-9A-F]{2})/g,((l,u)=>String.fromCharCode(parseInt(u,16)))))})(oi(e)),s=(a=>"data="+encodeURIComponent(typeof a=="string"?a:oi(a)))(r);return{contentType:"application/x-www-form-urlencoded",body:s,estimatedSize:new Blob([s]).size}}var o=oi(e);return{contentType:"application/json",body:o,estimatedSize:new Blob([o]).size}}},ph=t=>{var e,n,i=()=>t.transport==="sendBeacon"?{url:Js(t.url,{compression:ze.Base64}),encodedBody:Jo(k({},t,{compression:ze.Base64,Ji:void 0}))}:{url:hh(t.url,"compression"),encodedBody:Jo(k({},t,{compression:void 0,Ji:void 0}))};try{e=Jo(t)}catch(r){if(Vc(t.compression,mi(t.url,"compression")))return P.error("Failed to gzip request body, sending uncompressed payload",r),i();throw r}return e&&Vc(t.compression,mi(t.url,"compression"))&&!((n=e.body)instanceof ArrayBuffer?ha(new Uint8Array(n)):ArrayBuffer.isView(n)&&ha(new Uint8Array(n.buffer,n.byteOffset,n.byteLength)))?(es=!0,i()):{url:t.url,encodedBody:e}},gh=t=>{try{return ph(t)}catch(e){return P.error(e),void(t.callback==null||t.callback({statusCode:0,error:e}))}},nv=(function(){var t=ce((function*(e){var n=oi(e.data),i=yield(function(s,o,a){return pa.apply(this,arguments)})(n,oe.DEBUG,{rethrow:!0});if(!i)return e;var r=yield i.arrayBuffer();return k({},e,{Ji:{contentType:fh,body:r,estimatedSize:r.byteLength}})}));return function(e){return t.apply(this,arguments)}})(),iv=/Failed to fetch|NetworkError|Load failed/i,mh=t=>t?.name==="TypeError"&&iv.test(t?.message||""),vh=t=>{var e=gh(t);if(e){var n=e.url,i=e.encodedBody,r=i??{},s=r.contentType,o=r.body,a=r.estimatedSize,l=new Headers;ae(t.headers,(function(h,g){l.append(g,h)})),s&&l.append("Content-Type",s);var u=null,c=!1;if(jc){var d=new jc;u={signal:d.signal,timeout:setTimeout((()=>{var h,g;c=!0,d.abort((h=t.timeout,(g=new Error("PostHog request timed out"+(h?" after "+h+"ms":""))).name="AbortError",g))}),t.timeout)}}var f=h=>{c&&h?.name==="AbortError"||mh(h)?P.warn(h):P.error(h),t.callback==null||t.callback({statusCode:0,error:h})};try{var p;Sl(n,k({method:t?.method||"GET",headers:l,keepalive:t.method==="POST"&&!t.Yi&&52428.8>(a||0),body:o,signal:(p=u)==null?void 0:p.signal},t.fetchOptions)).then((h=>h.text().then((g=>{var m={statusCode:h.status,text:g};if(h.status===200)try{m.json=JSON.parse(g)}catch(v){P.error(v)}t.callback==null||t.callback(m)})))).catch(f).finally((()=>u?clearTimeout(u.timeout):null))}catch(h){u&&clearTimeout(u.timeout),f(h)}}},qa=t=>{try{var e,n=ph(t),i=n.url,r=n.encodedBody,s=r??{},o=s.body,a=s.estimatedSize;if(!o)return;var l=o instanceof Blob?o:new Blob([o],{type:s.contentType});if(Ve.sendBeacon(i,l))return;var u=U(t.data)?t.data:(e=t.data)==null?void 0:e.batch;if(U(u)&&u.length>1&&(a??0)>16384){var c=Math.ceil(u.length/2),d=f=>U(t.data)?f:k({},t.data,{batch:f});return qa(k({},t,{data:d(u.slice(0,c))})),void qa(k({},t,{data:d(u.slice(c))}))}P.warn("Beacon of ~"+(a??0)+" bytes was rejected by the browser, falling back to fetch"),vh(k({},t,{Yi:!0}))}catch(f){P.warn("Beacon send failed",f)}},Cu=(t,e,n,i)=>{var r=i==="query"?e==="POST"?"sent_at":"_":void 0;return Js(n===ze.GZipJS?hh(t,"compression"):t,k({},r?{[r]:Date.now().toString()}:{},n===ze.GZipJS?{}:{compression:n}))},ts=[];Sl&&ts.push({transport:"fetch",method:vh}),fa&&ts.push({transport:"XHR",method(t){var e=gh(t);if(e){var n=new fa,i=e.encodedBody;n.open(t.method||"GET",e.url,!0);var r=i??{},s=r.contentType,o=r.body;ae(t.headers,(function(a,l){n.setRequestHeader(l,a)})),s&&n.setRequestHeader("Content-Type",s),t.timeout&&(n.timeout=t.timeout),n.onreadystatechange=()=>{if(n.readyState===4){var a={statusCode:n.status,text:n.responseText};if(n.status===200)try{a.json=JSON.parse(n.responseText)}catch{}t.callback==null||t.callback(a)}},n.send(o)}}}),Ve!=null&&Ve.sendBeacon&&ts.push({transport:"sendBeacon",method:qa});var za=3e3;class rv{constructor(e,n){this.Xi=!0,this.tr=[],this.er=Nt(n?.flush_interval_ms||za,250,5e3,P.createLogger("flush interval"),za),this.ir=e}enqueue(e){this.tr.push(e),this.rr||this.nr()}unload(){this.sr();var e=this.tr.length>0?this.ar():{},n=Object.values(e);[...n.filter((i=>i.url.indexOf("/e")===0)),...n.filter((i=>i.url.indexOf("/e")!==0))].map((i=>{this.lr(k({},i,{transport:"sendBeacon"}))}))}enable(){this.Xi=!1,this.nr()}nr(){var e=this;this.Xi||(this.rr=setTimeout((()=>{if(this.sr(),this.tr.length>0){var n=this.ar(),i=function(){var s=n[r],o=new Date().getTime();s.data&&U(s.data)&&ae(s.data,(a=>{a.offset=Math.abs(a.timestamp-o),delete a.timestamp})),e.lr(s)};for(var r in n)i()}}),this.er))}lr(e){try{this.ir(e)}catch(n){P.error(n)}}sr(){clearTimeout(this.rr),this.rr=void 0}ar(){var e={};return ae(this.tr,(n=>{var i,r=n,s=(r?r.batchKey:null)||r.url;A(e[s])&&(e[s]=k({},r,{data:[]})),(i=e[s].data)==null||i.push(r.data)})),this.tr=[],e}}var sv=["retriesPerformedSoFar"];class ov{constructor(e){this.ur=!1,this.hr=3e3,this.tr=[],this._instance=e,this.tr=[],this.dr=!0,!A(w)&&"onLine"in w.navigator&&(this.dr=w.navigator.onLine,this.vr=()=>{this.dr=!0,this.cr()},this.pr=()=>{this.dr=!1},Se(w,"online",this.vr),Se(w,"offline",this.pr))}get length(){return this.tr.length}retriableRequest(e){var n=e.retriesPerformedSoFar,i=qd(e,sv);Yt(n)&&(i.url=Js(i.url,{retry_count:n})),this._instance._send_request(k({},i,{callback:r=>{if(r.statusCode!==200&&(400>r.statusCode||r.statusCode>=500)){if((r.statusCode===0?3:10)>(n??0))return void this.At(k({retriesPerformedSoFar:n},i));r.statusCode===0&&P.warn("Request failed before receiving an HTTP response; this can happen due to network issues, CORS, browser blocking, or ad blockers. Stopped retrying after "+(n??0)+" retries.")}i.callback==null||i.callback(r)}}))}At(e){var n=e.retriesPerformedSoFar||0;e.retriesPerformedSoFar=n+1;var i=(function(o){var a=3e3*Math.pow(2,o),l=a/2,u=Math.min(18e5,a),c=Math.random()-.5;return Math.ceil(u+c*(u-l))})(n),r=Date.now()+i;this.tr.push({retryAt:r,requestOptions:e});var s="Enqueued failed request for retry in "+i;navigator.onLine||(s+=" (Browser is offline)"),P.warn(s),this.ur||(this.ur=!0,this.gr())}gr(){if(this.mr&&clearTimeout(this.mr),this.tr.length===0)return this.ur=!1,void(this.mr=void 0);this.mr=setTimeout((()=>{this.dr&&this.tr.length>0&&this.cr(),this.gr()}),this.hr)}cr(){var e=Date.now(),n=[],i=this.tr.filter((s=>e>s.retryAt||(n.push(s),!1)));if(this.tr=n,i.length>0)for(var r of i)this.retriableRequest(r.requestOptions)}unload(){for(var e of(this.mr&&(clearTimeout(this.mr),this.mr=void 0),this.ur=!1,A(w)||(this.vr&&(w.removeEventListener("online",this.vr),this.vr=void 0),this.pr&&(w.removeEventListener("offline",this.pr),this.pr=void 0)),this.tr)){var n=e.requestOptions;try{this._instance._send_request(k({},n,{transport:"sendBeacon"}))}catch(i){P.error(i)}}this.tr=[]}}class av{constructor(e){this.yr=()=>{var n,i,r,s;this.br||(this.br={});var o=this.scrollElement(),a=this.scrollY(),l=o?Math.max(0,o.scrollHeight-o.clientHeight):0,u=a+(o?.clientHeight||0),c=o?.scrollHeight||0;this.br.lastScrollY=Math.ceil(a),this.br.maxScrollY=Math.max(a,(n=this.br.maxScrollY)!==null&&n!==void 0?n:0),this.br.maxScrollHeight=Math.max(l,(i=this.br.maxScrollHeight)!==null&&i!==void 0?i:0),this.br.lastContentY=u,this.br.maxContentY=Math.max(u,(r=this.br.maxContentY)!==null&&r!==void 0?r:0),this.br.maxContentHeight=Math.max(c,(s=this.br.maxContentHeight)!==null&&s!==void 0?s:0)},this._instance=e}get _r(){return this._instance.config.scroll_root_selector}getContext(){return this.br}resetContext(){var e=this.br;return setTimeout(this.yr,0),e}startMeasuringScrollPosition(){Se(w,"scroll",this.yr,{capture:!0}),Se(w,"scrollend",this.yr,{capture:!0}),Se(w,"resize",this.yr)}scrollElement(){if(!this._r)return w?.document.documentElement;var e=U(this._r)?this._r:[this._r];for(var n of e){var i=w?.document.querySelector(n);if(i)return i}}wr(e){var n=e==="y"?"scrollTop":"scrollLeft";if(this._r){var i=this.scrollElement();return i&&i[n]||0}return w?e==="y"?w.scrollY||w.pageYOffset||w.document.documentElement.scrollTop||0:w.scrollX||w.pageXOffset||w.document.documentElement.scrollLeft||0:0}scrollY(){return this.wr("y")}scrollX(){return this.wr("x")}}var lv=t=>ih(t?.config.mask_personal_data_properties,t?.config.custom_personal_data_properties,t?.config.disable_capture_url_hashes);class Au{constructor(e,n,i,r){this.kr=s=>{var o=this.Sr();if(!o||o.sessionId!==s){var a={sessionId:s,props:this.Cr(this._instance)};this.Mr.register({[Ta]:a})}},this._instance=e,this.Tr=n,this.Mr=i,this.Cr=r||lv,this.Tr.onSessionId(this.kr)}Sr(){return this.Mr.props[Ta]}getSetOnceProps(){var e,n=(e=this.Sr())==null?void 0:e.props;return n?"r"in n?rh(n,this._instance.config.disable_capture_url_hashes):{$referring_domain:n.referringDomain,$pathname:n.initialPathName,utm_source:n.utm_source,utm_campaign:n.utm_campaign,utm_medium:n.utm_medium,utm_content:n.utm_content,utm_term:n.utm_term}:{}}getSessionProps(){var e={};return ae($l(this.getSetOnceProps()),((n,i)=>{i==="$current_url"&&(i="url"),e["$session_entry_"+ga(i)]=n})),e}}class jl{on(e,n){return this.Er[e]||(this.Er[e]=[]),this.Er[e].push(n),()=>{this.Er[e]=this.Er[e].filter((i=>i!==n))}}emit(e,n){for(var i of this.Er[e]||[])i(n);for(var r of this.Er["*"]||[])r(e,n)}constructor(){this.Er={}}}var Ni=_e("[SessionId]");class Pu{on(e,n){return this.Ir.on(e,n)}constructor(e,n,i){var r;if(this.Pr=null,this.Rr=[],this.Ar=void 0,this.Fr=!1,this.Ir=new jl,this.Lr=(u,c)=>!(!Yt(u)||!Yt(c))&&Math.abs(u-c)>this.sessionTimeoutMs,!e.persistence)throw new Error("SessionIdManager requires a PostHogPersistence instance");if(e.config.cookieless_mode===tn)throw new Error('SessionIdManager cannot be used with cookieless_mode="always"');this.Ne=e.config,this.Mr=e.persistence,this.Or=void 0,this.Dr=void 0,this._sessionStartTimestamp=null,this._sessionActivityTimestamp=null,this.$r=n||Xt,this.Nr=i||Xt;var s=this.Ne.persistence_name||this.Ne.token;if(this._sessionTimeoutMs=1e3*Nt(this.Ne.session_idle_timeout_seconds||1800,60,36e3,Ni.createLogger("session_idle_timeout_seconds"),1800),e.register({$configured_session_timeout_ms:this._sessionTimeoutMs}),this.qr(),this.jr="ph_"+s+"_window_id",this.Br="ph_"+s+"_primary_window_exists",this.Hr()){var o=Ce.H(this.jr),a=Ce.H(this.Br);o&&!a?this.Or=o:Ce.q(this.jr),Ce.F(this.Br,!0)}if((r=this.Ne.bootstrap)!=null&&r.sessionID)try{var l=(u=>{var c=this.Ne.bootstrap.sessionID.replace(/-/g,"");if(c.length!==32)throw new Error("Not a valid UUID");if(c[12]!=="7")throw new Error("Not a UUIDv7");return parseInt(c.substring(0,12),16)})();this.Ur(this.Ne.bootstrap.sessionID,new Date().getTime(),l)}catch(u){Ni.error("Invalid sessionID in bootstrap",u)}this.zr()}get sessionTimeoutMs(){return this._sessionTimeoutMs}onSessionId(e){return A(this.Rr)&&(this.Rr=[]),this.Rr.push(e),this.Dr&&e(this.Dr,this.Or),()=>{this.Rr=this.Rr.filter((n=>n!==e))}}Hr(){return this.Ne.persistence!=="memory"&&!this.Mr.xi&&Ce.N()}Wr(e){e!==this.Or&&(this.Or=e,this.Hr()&&Ce.F(this.jr,e))}Vr(){return this.Or?this.Or:this.Hr()?Ce.H(this.jr):null}Zr(e){var n=this.Pr;return!it(n)&&!it(e)&&5e3>Math.abs(e-n)}Ur(e,n,i){var r=n!==this._sessionActivityTimestamp,s=!(e!==this.Dr||i!==this._sessionStartTimestamp);this._sessionStartTimestamp=i,this._sessionActivityTimestamp=n,this.Dr=e,s&&!r||s&&this.Zr(n)||(this.Pr=n,this.Mr.register({[si]:[n,e,i]}))}Gr(){var e,n=(e=this.Ne)==null?void 0:e.persistence_save_debounce_ms;return Yt(n)&&n>0}Qr(){this.Gr()?this.Mr.refreshKey(si):(this.Mr.flush(),this.Mr.load())}Kr(){var e;if(!it(this._sessionActivityTimestamp)&&this._sessionActivityTimestamp!==this.Pr){this.Qr();var n=this.Jr();n[1]===this.Dr&&n[2]===this._sessionStartTimestamp&&(this.Pr=this._sessionActivityTimestamp,this.Mr.register({[si]:[this._sessionActivityTimestamp,(e=this.Dr)!==null&&e!==void 0?e:null,this._sessionStartTimestamp]}),this.Mr.flush())}}Yr(){var e=this.Jr()[0],n=Yt(e)?e:0,i=Yt(this._sessionActivityTimestamp)?this._sessionActivityTimestamp:0;return Math.max(n,i)}Xr(e){return this.Qr(),this.Lr(e,this.Yr())}Jr(){var e=this.Mr.props[si];return U(e)&&e.length===2&&e.push(e[0]),e||[0,null,0]}resetSessionId(){this.Pr=null,clearTimeout(this.tn),this.tn=void 0,this.Ur(null,null,null)}destroy(){this.Fr=!0,this.Kr(),clearTimeout(this.tn),this.tn=void 0,this.Ar&&w&&(w.removeEventListener(Ss,this.Ar,{capture:!1}),this.Ar=void 0),this.Rr=[]}zr(){this.Ar=()=>{this.Kr(),this.Hr()&&Ce.q(this.Br)},Se(w,Ss,this.Ar,{capture:!1})}checkAndGetSessionAndWindowId(e,n){if(e===void 0&&(e=!1),n===void 0&&(n=null),this.Ne.cookieless_mode===tn)throw new Error('checkAndGetSessionAndWindowId should not be called with cookieless_mode="always"');var i=n||new Date().getTime(),r=this.Jr(),s=r[1],o=r[2],a=this.Yr(),l=this.Vr(),u=Yt(o)&&Math.abs(i-o)>864e5,c=!1,d=!1,f=!s,p=s,h=!f&&!e&&this.Lr(i,a);if(h){(h=this.Xr(i))||Ni.info("cross-tab refresh kept the session alive",{sessionId:s});var g=this.Jr();s=g[1],o=g[2]}f||h||u?(s=this.$r(),l=this.Nr(),Ni.info("new session ID generated",{sessionId:s,windowId:l,changeReason:{noSessionId:f,activityTimeout:h,sessionPastMaximumLength:u}}),o=i,c=!0):(l||(l=this.Nr(),c=!0),(d=s!==p)&&(Ni.info("adopted cross-tab session id",{sessionId:s,windowId:l}),c=!0));var m=Yt(a)&&e&&!u?a:i,v=Yt(o)?o:new Date().getTime();this.Wr(l),this.Ur(s,m,v),e||this.qr();var x={noSessionId:f,activityTimeout:h,sessionPastMaximumLength:u,crossTabAdoption:d};return c&&this.Rr.forEach((E=>E(s,l,x))),{sessionId:s,windowId:l,sessionStartTimestamp:v,changeReason:c?x:void 0,lastActivityTimestamp:a}}qr(){this.Fr||(clearTimeout(this.tn),this.tn=setTimeout((()=>{if(!this.Fr)if(this.Xr(new Date().getTime())){var e=this.Dr;this.resetSessionId(),this.Ir.emit("forcedIdleReset",{idleSessionId:e})}else this.qr()}),1.1*this.sessionTimeoutMs))}}var yh=function(t,e){if(!t)return!1;var n=t.userAgent;if(n&&Kc(n,e))return!0;try{var i=t?.userAgentData;if(i!=null&&i.brands&&i.brands.some((r=>Kc(r?.brand,e))))return!0}catch{}return!!t.webdriver};function _h(){return(_h=ce((function*(){var t=Ve?.userAgentData;if(t!=null&&t.getHighEntropyValues)try{var e=yield t.getHighEntropyValues(["model"]),n=e?.model;return X(n)&&n.length>0?n:void 0}catch(i){return void P.info("Unable to resolve $device_model from userAgentData.getHighEntropyValues",i)}}))).apply(this,arguments)}var Fs=function(t,e){if(!(function(n){try{new RegExp(n)}catch{return!1}return!0})(e))return!1;try{return new RegExp(e).test(t)}catch{return!1}};function Zo(t,e,n){return oi({distinct_id:t,userPropertiesToSet:e,userPropertiesToSetOnce:n})}var wh={exact:(t,e)=>e.some((n=>t.some((i=>n===i)))),is_not:(t,e)=>e.every((n=>t.every((i=>n!==i)))),regex:(t,e)=>e.some((n=>t.some((i=>Fs(n,i))))),not_regex:(t,e)=>e.every((n=>t.every((i=>!Fs(n,i))))),icontains:(t,e)=>e.map(Hr).some((n=>t.map(Hr).some((i=>n.includes(i))))),not_icontains:(t,e)=>e.map(Hr).every((n=>t.map(Hr).every((i=>!n.includes(i))))),gt:(t,e)=>e.some((n=>{var i=parseFloat(n);return!isNaN(i)&&t.some((r=>i>parseFloat(r)))})),lt:(t,e)=>e.some((n=>{var i=parseFloat(n);return!isNaN(i)&&t.some((r=>it.toLowerCase();function bh(t,e){return!t||Object.entries(t).every((n=>{var i=n[1],r=e?.[n[0]];if(A(r)||it(r))return!1;var s=[String(r)],o=wh[i.operator];return!!o&&o(i.values,s)}))}var Va="custom",Fu="i.posthog.com",cv=/^\/static\//;class uv{constructor(e){this.en={},this.instance=e}get apiHost(){var e=this.instance.config.api_host.trim().replace(/\/$/,"");return e==="https://app.posthog.com"?"https://us.i.posthog.com":e}get flagsApiHost(){var e=this.instance.config.flags_api_host;return e?e.trim().replace(/\/$/,""):this.apiHost}get uiHost(){var e,n=(e=this.instance.config.ui_host)==null?void 0:e.replace(/\/$/,"");return n||(n=this.apiHost.replace("."+Fu,".posthog.com")),n==="https://app.posthog.com"?"https://us.posthog.com":n}get region(){return this.en[this.apiHost]||(this.en[this.apiHost]=/https:\/\/(app|us|us-assets)(\.i)?\.posthog\.com/i.test(this.apiHost)?"us":/https:\/\/(eu|eu-assets)(\.i)?\.posthog\.com/i.test(this.apiHost)?"eu":Va),this.en[this.apiHost]}rn(e){if(cv.test(e)){var n=this.instance.config.asset_host;if(typeof n=="string")return n.trim().replace(/\/$/,"")||void 0}}endpointFor(e,n){if(n===void 0&&(n=""),n&&(n=n[0]==="/"?n:"/"+n),e==="ui")return this.uiHost+n;if(e==="flags")return this.flagsApiHost+n;if(e==="assets"){var i=this.rn(n);if(i)return""+i+n}if(this.region===Va)return this.apiHost+n;var r=Fu+n;switch(e){case"assets":return"https://"+this.region+"-assets."+r;case"api":return"https://"+this.region+"."+r}}}function Eh(t){var e;return!((e=t.conditions)==null||(e=e.events)==null||(e=e.values)==null||!e.length)}var te=_e("[Surveys]"),Sh="seenSurvey_",xh=t=>{try{var e=(n=>((i,r)=>""+Sh+(function(s){return s.current_iteration&&s.current_iteration>0?s.id+"_"+s.current_iteration:s.id})(r))(0,n))(t);if(localStorage.getItem(e))return;localStorage.setItem(e,"true")}catch(n){te.error("Failed to persist survey seen state",n)}},dv=[Vo.Popover,Vo.Widget,Vo.API],fv={ignoreConditions:!1,ignoreDelay:!1,displayType:ja.Popover},hv=_e("[PostHog ExternalIntegrations]"),pv={intercom:"intercom-integration",crispChat:"crisp-chat-integration"};class gv{constructor(e){this._instance=e}ai(e,n){var i;(i=B.__PosthogExtensions__)==null||i.loadExternalDependency==null||i.loadExternalDependency(this._instance,e,(r=>{if(r)return hv.error("failed to load script",r);n()}))}startIfEnabledOrStop(){var e=this,n=function(){var s,o,a,l=i[0],u=i[1];!u||(s=B.__PosthogExtensions__)!=null&&(s=s.integrations)!=null&&s[l]||e.ai(pv[l],(()=>{var c;(c=B.__PosthogExtensions__)==null||(c=c.integrations)==null||(c=c[l])==null||c.start(e._instance)})),!u&&(o=B.__PosthogExtensions__)!=null&&(o=o.integrations)!=null&&o[l]&&((a=B.__PosthogExtensions__)==null||(a=a.integrations)==null||(a=a[l])==null||a.stop())};for(var i of Object.entries((r=this._instance.config.integrations)!==null&&r!==void 0?r:{})){var r;n()}}}class mv{constructor(e,n){this.rt=e,this.nn=n,this.sn=new Map,this.an=!1}add(e){var n=this;return ce((function*(){if(n.an)throw new Error("Cannot add an extension to a disposed ExtensionRuntime");if(n.sn.has(e.name))throw new Error('Browser extension "'+e.name+'" is already registered');n.sn.set(e.name,e);try{var i=e.setup(n.nn);i&&(yield i)}catch(s){var r=n.sn.get(e.name)===e;r&&n.sn.delete(e.name),n.rt.error('Failed to set up browser extension "'+e.name+'"',s),r&&n.ln(e)}}))()}dispose(){if(!this.an){this.an=!0;var e=Array.from(this.sn.values()).reverse();for(var n of(this.sn.clear(),e))this.ln(n)}}ln(e){try{var n=e.dispose==null?void 0:e.dispose();n&&qe(n.then)&&n.then(void 0,(i=>{this.rt.error('Failed to dispose browser extension "'+e.name+'"',i)}))}catch(i){this.rt.error('Failed to dispose browser extension "'+e.name+'"',i)}}}class vv{constructor(e){this._instance=e}initialize(){}get(e){var n=this._instance.persistence;if(typeof e=="string")return n?.get_property(e);var i={};for(var r of e){var s=n?.get_property(r);A(s)||(i[r]=s)}return i}set(e,n){var i;(i=this._instance.persistence)==null||i.register(typeof e=="string"?{[e]:n}:e)}remove(e){var n;(n=this._instance.persistence)==null||n.unregister(e)}}var Ru="extensionsRemoteConfig";class yv{constructor(e){this.an=!1,this.instance=e,this.rt=P,this.un=e.hn,this.kv=new vv(e),this.onEvent=n=>Ur(this.instance.on("eventCaptured",(i=>{try{n({event:i.event,properties:i.properties})}catch(r){this.rt.error("Browser extension event listener failed",r)}}))),this.onRemoteConfig=n=>{if(this.an)return Ur((()=>{}));var i=s=>{try{n(s)}catch(o){this.rt.error("Browser extension remote config listener failed",o)}},r=this.instance.dn.on(Ru,i);return this.un&&i(this.un),Ur(r)},this.vn=new mv(P.createLogger("[BrowserExtensions]"),this)}get logger(){return this.rt}get distinctId(){return this.instance.get_distinct_id()}get anonymousId(){var e;return(e=this.instance.get_property(lr))!==null&&e!==void 0?e:this.distinctId}get deviceId(){var e=this.instance.get_property(lr);return typeof e=="string"?e:void 0}get library(){return{name:oe.LIB_NAME,version:oe.LIB_VERSION}}get initialPersonProperties(){var e,n;return(e=(n=this.instance.persistence)==null?void 0:n.get_initial_props())!==null&&e!==void 0?e:{}}get groups(){return this.instance.getGroups()}get session(){try{var e,n,i,r,s=(e=this.instance.sessionManager)==null?void 0:e.checkAndGetSessionAndWindowId(!0);return{sessionId:(n=s?.sessionId)!==null&&n!==void 0?n:"",windowId:(i=s?.windowId)!==null&&i!==void 0?i:"",sessionStartTimestamp:(r=s?.sessionStartTimestamp)!==null&&r!==void 0?r:0}}catch{return{sessionId:"",windowId:"",sessionStartTimestamp:0}}}get projectToken(){return this.instance.config.token}add(e){return this.vn.add(e)}capture(e,n,i){var r=this;return ce((function*(){i?r.instance.capture(e,n,{timestamp:i.timestamp,uuid:i.uuid,$set:i.set,$set_once:i.setOnce}):r.instance.capture(e,n)}))()}registerDynamicEventProperties(e){return Ur(this.instance.cn(e))}handleRemoteConfig(e){this.an||(this.un=e,this.instance.dn.emit(Ru,e))}sendRequest(e,n){var i=this;return ce((function*(){var r;n===void 0&&(n={});var s=i.instance.requestRouter.endpointFor((r=n.target)!==null&&r!==void 0?r:"api",e),o={method:n.method,url:n.query?Js(s,n.query):s,data:n.body,headers:n.headers,timeout:n.timeoutMs,fireCallbackOnDrop:!0,transport:n.transport,compression:n.compression,timestampMode:n.sentAt};return n.transport==="sendBeacon"?(i.instance._send_request(o),{statusCode:202}):new Promise((a=>{o.callback=a,i.instance._send_request(o)}))}))()}dispose(){this.an||(this.an=!0,this.vn.dispose())}}var nr={},Xo=0,Rs=()=>{},Tu='Consent opt in/out is not valid with cookieless_mode="always" and will be ignored',Oi="Surveys module not available",Mu="sanitize_properties is deprecated. Use before_send instead",Ih="Invalid value for property_denylist config: ",_v=["token","distinct_id",Tf],ri="posthog",kh=!tv&&Qe?.indexOf("MSIE")===-1&&Qe?.indexOf("Mozilla")===-1,Qo=t=>{var e;return k({api_host:"https://us.i.posthog.com",flags_api_host:null,ui_host:null,asset_host:null,token:"",autocapture:!0,cross_subdomain_cookie:wm(F?.location),persistence:"localStorage+cookie",persistence_name:"",cookie_persisted_properties:[],loaded:Rs,save_campaign_params:!0,custom_campaign_params:[],custom_blocked_useragents:[],save_referrer:!0,capture_pageleave:"if_capture_pageview",defaults:t??"unset",__preview_deferred_init_extensions:!1,__preview_external_dependency_versioned_paths:!1,__preview_cookie_wins_on_conflict:!1,debug:Ee&&X(Ee?.search)&&Ee.search.indexOf("__posthog_debug=true")!==-1||!1,cookie_expiration:365,upgrade:!1,disable_session_recording:!1,disable_persistence:!1,disable_web_experiments:!0,disable_surveys:!1,disable_surveys_automatic_display:!1,disable_conversations:!1,disable_product_tours:!1,disableDeviceModel:!1,disable_external_dependency_loading:!1,strict_script_versioning:!1,enable_recording_console_log:void 0,secure_cookie:(w==null||(e=w.location)==null?void 0:e.protocol)==="https:",ip:!1,opt_out_capturing_by_default:!1,opt_out_persistence_by_default:!1,opt_out_useragent_filter:!1,opt_out_capturing_persistence_type:"localStorage",consent_persistence_name:null,opt_out_capturing_cookie_prefix:null,opt_in_site_apps:!1,property_denylist:[],respect_dnt:!1,sanitize_properties:null,request_headers:{},request_batching:!0,properties_string_max_length:65535,mask_all_element_attributes:!1,mask_all_text:!1,mask_personal_data_properties:!1,custom_personal_data_properties:[],advanced_disable_flags:!1,advanced_disable_decide:!1,advanced_disable_feature_flags:!1,advanced_disable_feature_flags_on_first_load:!1,advanced_only_evaluate_survey_feature_flags:!1,advanced_feature_flags_dedup_per_session:!1,advanced_enable_surveys:!1,advanced_disable_toolbar_metrics:!1,feature_flag_request_timeout_ms:3e3,surveys_request_timeout_ms:1e4,on_request_error(n){P.error("Bad HTTP status: "+n.statusCode+" "+n.text)},get_device_id:n=>n,capture_performance:void 0,name:"posthog",bootstrap:{},disable_compression:!1,session_idle_timeout_seconds:1800,person_profiles:Na,before_send:void 0,get_current_url:void 0,request_queue_config:{flush_interval_ms:za},error_tracking:{},_onCapture:Rs},(n=>({rageclick:n&&n>="2026-05-30"?{content_ignorelist:Tm,ignore_text_selection:!0}:!n||"2025-11-30">n||{content_ignorelist:!0},capture_pageview:!n||"2025-05-24">n||"history_change",session_recording:n&&n>="2026-06-25"?{strictMinimumDuration:!0,canvasCapture:{resolutionScale:.6},streamNetworkBody:!0}:n&&n>="2026-05-30"?{strictMinimumDuration:!0,canvasCapture:{resolutionScale:.6}}:n&&n>="2025-11-30"?{strictMinimumDuration:!0}:{},external_scripts_inject_target:n&&n>="2026-01-30"?"head":"body",internal_or_test_user_hostname:n&&n>="2026-01-30"?/^(localhost|127\.0\.0\.1)$/:void 0,persistence_save_debounce_ms:n&&n>="2026-05-30"?250:0,split_storage:!(!n||"2026-05-30">n),detect_google_search_app:!(!n||"2026-05-30">n),disable_capture_url_hashes:!(!n||"2026-06-25">n)}))(t))},wv=[["process_person","person_profiles"],["xhr_headers","request_headers"],["cookie_name","persistence_name"],["disable_cookie","disable_persistence"],["__preview_disable_beacon","disable_beacon"],["store_google","save_campaign_params"],["verbose","debug"]],$u=t=>{var e={};for(var n of wv){var i=n[0],r=n[1];A(t[i])||(e[r]=t[i])}var s=ve({},e,t),o=t.__preview_external_dependency_versioned_paths;return A(o)||(A(t.strict_script_versioning)&&(s.strict_script_versioning=!!o),X(o)&&A(t.asset_host)&&(s.asset_host=o)),U(t.property_blacklist)&&(A(t.property_denylist)?s.property_denylist=t.property_blacklist:U(t.property_denylist)?s.property_denylist=[...t.property_blacklist,...t.property_denylist]:P.error(Ih+t.property_denylist)),s};class bv{constructor(){this.__forceAllowLocalhost=!1}get fn(){return this.__forceAllowLocalhost}set fn(e){P.error("WebPerformanceObserver is deprecated and has no impact on network capture. Use `_forceAllowLocalhostNetworkCapture` on `posthog.sessionRecording`"),this.__forceAllowLocalhost=e}}class st{pn(e,n){if(e){var i=this.sn.indexOf(e);i!==-1&&this.sn.splice(i,1)}return this.sn.push(n),n.initialize==null||n.initialize(),n}gn(){return this.config.cookieless_mode===tn||this.config.cookieless_mode===Bn&&this.consent.isRejected()}get decideEndpointWasHit(){var e,n;return(e=(n=this.featureFlags)==null?void 0:n.hasLoadedFlags)!==null&&e!==void 0&&e}get flagsEndpointWasHit(){var e,n;return(e=(n=this.featureFlags)==null?void 0:n.hasLoadedFlags)!==null&&e!==void 0&&e}constructor(){var e;this.webPerformance=new bv,this.mn=!1,this.version=oe.LIB_VERSION,this.yn=new Set,this.bn="",this.dn=new jl,this.sn=[],this._n=[],this._calculate_event_properties=this.calculateEventProperties.bind(this),this.config=Qo(),this.SentryIntegration=jm,this.sentryIntegration=i=>(function(r,s){var o=Jf(r,s);return{name:Yf,processEvent:a=>o(a)}})(this,i),this.__request_queue=[],this.__loaded=!1,this.analyticsDefaultEndpoint="/e/",this.wn=!1,this.kn=null,this.xn=null,this.Sn=null,this.scrollManager=new av(this),this.pageViewManager=new _u(this),this.rateLimiter=new Ym(this),this.requestRouter=new uv(this),this.consent=new Cm(this),this.externalIntegrations=new gv(this);var n=(e=st.__defaultExtensionClasses)!==null&&e!==void 0?e:{};this.featureFlags=n.featureFlags&&new n.featureFlags(this),this.toolbar=n.toolbar&&new n.toolbar(this),this.surveys=n.surveys&&new n.surveys(this),this.conversations=n.conversations&&new n.conversations(this),this.logs=n.logs&&new n.logs(this),this.metrics=n.metrics&&new n.metrics(this),this.experiments=n.experiments&&new n.experiments(this),this.exceptions=n.exceptions&&new n.exceptions(this),this.people={set:(i,r,s)=>{var o=X(i)?{[i]:r}:i;this.setPersonProperties(o),s?.({})},set_once:(i,r,s)=>{var o=X(i)?{[i]:r}:i;this.setPersonProperties(void 0,o),s?.({})}},this.on("eventCaptured",(i=>P.info('send "'+i?.event+'"',i)))}init(e,n,i){if(i&&i!==ri){var r,s=(r=nr[i])!==null&&r!==void 0?r:new st;return s._init(e,n,i),nr[i]=s,nr[ri][i]=s,s}return this._init(e,n,i)}_init(e,n,i){var r,s;n===void 0&&(n={});var o,a=X(e)?e.trim():"";if(!a)return P.critical("PostHog was initialized without a token. This likely indicates a misconfiguration. Please check the first argument passed to posthog.init()"),this;if(this.__loaded)return a!==((o=this.config)==null?void 0:o.token)?console.warn("[PostHog.js]","You have already initialized PostHog with a different project token! Re-initializing is a no-op, so events will keep going to the project this instance was initialized with. To capture into a second project, load PostHog once, then initialize a named instance after the SDK has loaded, e.g. posthog.init('"+a+"', { ... }, 'project2')"):console.warn("[PostHog.js]","You have already initialized PostHog! Re-initializing is a no-op"),this;this.__loaded=!0,this.config=Qo(n.defaults),n.debug=this.Cn(n.debug),this.Mn=n,this.Tn=[],n.person_profiles?this.xn=n.person_profiles:n.process_person&&(this.xn=n.process_person);var l=Qo(n.defaults),u=$u(n),c=ve({},l,u,{name:i,token:a});ye(l.rageclick)&&ye(u.rageclick)&&(c.rageclick=ve({},l.rageclick,u.rageclick)),ye(l.session_recording)&&ye(u.session_recording)&&(c.session_recording=ve({},l.session_recording,u.session_recording)),this.set_config(c),this.config.on_xhr_error&&P.error("on_xhr_error is deprecated. Use on_request_error instead"),this.compression=n.disable_compression?void 0:ze.GZipJS;var d=this.En();if(this.persistence=new zo(this.config,d),this.sessionPersistence=this.config.persistence==="sessionStorage"||this.config.persistence==="memory"?this.persistence:new zo(k({},this.config,{persistence:"sessionStorage"}),d,!1),this.bn="ph_"+(this.config.persistence_name||this.config.token)+"_session_registered_properties",this.config.persistence!=="memory"&&!d&&Ce.N()){var f=Ce.H(this.bn);U(f)&&f.forEach((I=>{X(I)&&this.yn.add(I)}))}else Ce.q(this.bn);var p=k({},this.persistence.props),h=k({},this.sessionPersistence.props);this.register({$initialization_time:new Date().toISOString()}),this.In=new rv((I=>this.Pn(I)),this.config.request_queue_config),this.Rn=new ov(this),this.__request_queue=[];var g=this.gn();if(g||(this.sessionManager=new Pu(this),this.sessionPropsManager=new Au(this,this.sessionManager,this.persistence),this.sessionManager.onSessionId(((I,T,S)=>{(S!=null&&S.activityTimeout||S!=null&&S.sessionPastMaximumLength||S!=null&&S.crossTabAdoption)&&this.An()}))),this.Fn(),this.config.__preview_deferred_init_extensions?(P.info("Deferring extension initialization to improve startup performance"),setTimeout((()=>{this.Ln(g)}),0)):(P.info("Initializing extensions synchronously"),this.Ln(g)),oe.DEBUG=oe.DEBUG||this.config.debug,oe.DEBUG&&P.info("Starting in debug mode",{this:this,config:n,thisC:k({},this.config),p,s:h}),!this.config.identity_distinct_id||(r=n.bootstrap)!=null&&r.distinctID||(n.bootstrap=k({},n.bootstrap,{distinctID:this.config.identity_distinct_id,isIdentifiedID:!0})),((s=n.bootstrap)==null?void 0:s.distinctID)!==void 0){var m=n.bootstrap.distinctID,v=this.get_distinct_id(),x=this.persistence.get_property(yt);if(n.bootstrap.isIdentifiedID&&v!=null&&v!==m&&x===Xn)this.identify(m);else if(n.bootstrap.isIdentifiedID&&v!=null&&v!==m&&x===Pn)P.warn("Bootstrap distinctID differs from an already-identified user. The existing identity is preserved. Call reset() before reinitializing if you intend to switch users.");else{var E=this.config.get_device_id(Xt()),y=n.bootstrap.isIdentifiedID?E:m;this.persistence.set_property(yt,n.bootstrap.isIdentifiedID?Pn:Xn),this.register({distinct_id:m,$device_id:y})}}if(g)this.register_once({distinct_id:Nr,$device_id:null},"");else if(!this.get_distinct_id()){var b=this.config.get_device_id(Xt());this.register_once({distinct_id:b,$device_id:b},""),this.persistence.set_property(yt,Xn)}return Se(w,"onpagehide"in self?"pagehide":"unload",this._handle_unload.bind(this),{passive:!1}),n.segment?(function(I,T){var S=I.config.segment;if(!S)return T();(function(C,R){var O=C.config.segment;if(!O)return R();var L=J=>{var G=()=>J.anonymousId()||Xt();C.config.get_device_id=G,J.id()&&(C.register({distinct_id:J.id(),$device_id:G()}),C.persistence.set_property(yt,Pn)),R()},N=O.user();"then"in N&&qe(N.then)?N.then(L):L(N)})(I,(()=>{S.register((C=>{typeof Promise<"u"&&Promise.resolve||Wo.warn("This browser does not have Promise support, and can not use the segment integration");var R=(O,L)=>{if(!L)return O;O.event.userId||O.event.anonymousId===C.get_distinct_id()||(Wo.info("No userId set, resetting PostHog"),C.reset()),O.event.userId&&O.event.userId!==C.get_distinct_id()&&(Wo.info("UserId set, identifying with PostHog"),C.identify(O.event.userId));var N=C.calculateEventProperties(L,O.event.properties);return O.event.properties=Object.assign({},N,O.event.properties),O};return{name:"PostHog JS",type:"enrichment",version:"1.0.0",isLoaded:()=>!0,load:()=>Promise.resolve(),track:O=>R(O,O.event.event),page:O=>R(O,ii),identify:O=>R(O,jo),screen:O=>R(O,"$screen")}})(I)).then((()=>{T()}))}))})(this,(()=>this.On())):this.On(),qe(this.config._onCapture)&&this.config._onCapture!==Rs&&(P.warn("onCapture is deprecated. Please use `before_send` instead"),this.on("eventCaptured",(I=>this.config._onCapture(I.event,I)))),this.config.ip&&P.warn('The `ip` config option has NO EFFECT AT ALL and has been deprecated. Use a custom transformation or "Discard IP data" project setting instead. See https://posthog.com/tutorials/web-redact-properties#hiding-customer-ip-address for more information.'),this.config.disableDeviceModel||(function(){return _h.apply(this,arguments)})().then((I=>{I&&this.register({[Bo]:I})})).catch(Rs),this}Fn(){var e,n,i,r,s,o,a=(e=(n=this.config.__extensionClasses)==null?void 0:n.featureFlags)!==null&&e!==void 0?e:(i=st.__defaultExtensionClasses)==null?void 0:i.featureFlags;a&&(this.featureFlags&&this.featureFlags instanceof a||((r=this.Dn)==null||r.call(this),this.Dn=void 0,this.featureFlags=new a(this)),qe(this.featureFlags.onReloading)&&qe(this.featureFlags.setup)?this.Dn||(this.Dn=this.featureFlags.onReloading((()=>{this.dn.emit("featureFlagsReloading",!0)})),this.$n().add(this.featureFlags)):(s=(o=this.featureFlags).initialize)==null||s.call(o))}Ln(e){var n,i,r,s,o,a,l,u=performance.now(),c=k({},st.__defaultExtensionClasses,this.config.__extensionClasses),d=[];c.exceptions&&this.sn.push(this.exceptions=(n=this.exceptions)!==null&&n!==void 0?n:new c.exceptions(this)),c.historyAutocapture&&this.sn.push(this.historyAutocapture=new c.historyAutocapture(this)),c.tracingHeaders&&this.sn.push(this.tracingHeaders=new c.tracingHeaders(this)),c.siteApps&&this.sn.push(this.siteApps=new c.siteApps(this)),c.sessionRecording&&!e&&this.sn.push(this.sessionRecording=new c.sessionRecording(this)),this.config.disable_scroll_properties||d.push((()=>{this.scrollManager.startMeasuringScrollPosition()})),c.autocapture&&this.sn.push(this.autocapture=new c.autocapture(this)),c.surveys&&this.sn.push(this.surveys=(i=this.surveys)!==null&&i!==void 0?i:new c.surveys(this)),c.logs&&this.sn.push(this.logs=(r=this.logs)!==null&&r!==void 0?r:new c.logs(this)),c.metrics&&this.sn.push(this.metrics=(s=this.metrics)!==null&&s!==void 0?s:new c.metrics(this)),c.conversations&&this.sn.push(this.conversations=(o=this.conversations)!==null&&o!==void 0?o:new c.conversations(this)),c.productTours&&this.sn.push(this.productTours=new c.productTours(this)),c.heatmaps&&this.sn.push(this.heatmaps=new c.heatmaps(this)),c.webVitalsAutocapture&&this.sn.push(this.webVitalsAutocapture=new c.webVitalsAutocapture(this)),c.exceptionObserver&&this.sn.push(this.exceptionObserver=new c.exceptionObserver(this)),c.deadClicksAutocapture&&this.sn.push(this.deadClicksAutocapture=new c.deadClicksAutocapture(this,Dm)),c.toolbar&&this.sn.push(this.toolbar=(a=this.toolbar)!==null&&a!==void 0?a:new c.toolbar(this)),c.experiments&&this.sn.push(this.experiments=(l=this.experiments)!==null&&l!==void 0?l:new c.experiments(this)),this.sn.forEach((f=>{f.initialize&&d.push((()=>{f.initialize==null||f.initialize()}))})),d.push((()=>{if(this.Nn){var f=this.Nn;this.Nn=void 0,this.sn.forEach((p=>p.onRemoteConfig==null?void 0:p.onRemoteConfig(f)))}})),this.qn(d,u)}qn(e,n){for(;e.length>0;){if(this.config.__preview_deferred_init_extensions&&performance.now()-n>=30&&e.length>0)return void setTimeout((()=>{this.qn(e,n)}),0);var i=e.shift();if(i)try{i()}catch(s){P.error("Error initializing extension:",s)}}var r=Math.round(performance.now()-n);this.register_for_session({[Mf]:this.config.__preview_deferred_init_extensions?"deferred":"synchronous",[$f]:r}),this.config.__preview_deferred_init_extensions&&P.info("PostHog extensions initialized ("+r+"ms)")}Zi(e){var n;if(!F||!F.body)return P.info("document not ready yet, trying again in 500 milliseconds..."),void setTimeout((()=>{this.Zi(e)}),500);if(this.config.__preview_deferred_init_extensions&&(this.Nn=e),this.hn=e,this.compression=void 0,e.ok){var i,r=e.config;r.supportedCompression&&!this.config.disable_compression&&(this.compression=j(r.supportedCompression,ze.GZipJS)?ze.GZipJS:j(r.supportedCompression,ze.Base64)?ze.Base64:void 0),(i=r.analytics)!=null&&i.endpoint&&(this.analyticsDefaultEndpoint=r.analytics.endpoint)}this.set_config({person_profiles:this.xn?this.xn:Na}),(n=this.jn)==null||n.handleRemoteConfig(e),this.sn.forEach((s=>s.onRemoteConfig==null?void 0:s.onRemoteConfig(e)))}On(){try{this.config.loaded(this)}catch(i){P.critical("`loaded` function failed",i)}if(this.Bn(),this.config.internal_or_test_user_hostname&&Ee!=null&&Ee.hostname){var e=Ee.hostname,n=this.config.internal_or_test_user_hostname;(typeof n=="string"?e===n:n.test(e))&&this.setInternalOrTestUser()}this.config.capture_pageview&&setTimeout((()=>{(this.consent.isOptedIn()||this.gn())&&this.Hn()}),1),this.Un=new oh(this),this.Un.load()}Bn(){var e;this.is_capturing()&&this.config.request_batching&&((e=this.In)==null||e.enable())}_dom_loaded(){this.is_capturing()&&Or(this.__request_queue,(e=>this.Pn(e))),this.__request_queue=[],this.Bn()}_handle_unload(){var e,n,i,r,s;(e=this.surveys)==null||e.handlePageUnload==null||e.handlePageUnload(),(n=this.metrics)==null||n.flush("sendBeacon"),this.config.request_batching?(this.zn()&&this.capture(Do),(i=this.logs)==null||i.flushLogs("sendBeacon"),(r=this.In)==null||r.unload(),(s=this.Rn)==null||s.unload()):this.zn()&&this.capture(Do,null,{transport:"sendBeacon"})}_send_request(e){this.__loaded?kh?this.__request_queue.push(e):this.rateLimiter.isServerRateLimited(e.batchKey)?e.fireCallbackOnDrop&&(e.callback==null||e.callback({statusCode:429})):(e.transport=e.transport||this.config.api_transport,e.headers=k({},this.config.request_headers,e.headers),e.compression=e.compression==="best-available"?this.compression:e.compression,(A(this.config.disable_beacon)?this.config.__preview_disable_beacon:this.config.disable_beacon)&&(e.disableTransport=["sendBeacon"]),e.fetchOptions=e.fetchOptions||this.config.fetch_options,(n=>{var i,r,s,o=k({},n);o.timeout=o.timeout||6e4;var a,l,u,c,d,f=(i=o.transport)!==null&&i!==void 0?i:"fetch";f==="sendBeacon"&&A(o.compression)&&o.data&&(o.compression=ze.Base64),o.method==="POST"&&o.data&&(o.timestampMode==="capture-body"?o.data={api_key:(l=(d=(c=U(a=o.data)?a:[a])[0])==null||(u=d.properties)==null?void 0:u.token)!==null&&l!==void 0?l:d?.token,batch:c,sent_at:new Date().toISOString()}:o.timestampMode==="body"&&(o.data=(function(m,v){return v===void 0&&(v=new Date().toISOString()),U(m)?m.map((x=>k({},x,{sent_at:v}))):k({},m,{sent_at:v})})(o.data))),o.url=Cu(o.url,o.method,o.compression,o.timestampMode);var p=ts.filter((m=>!o.disableTransport||!m.transport||!o.disableTransport.includes(m.transport))),h=(r=(s=(function(m,v){for(var x=0;m.length>x;x++)if(m[x].transport===f)return m[x]})(p))==null?void 0:s.method)!==null&&r!==void 0?r:p[0].method;if(!h)throw new Error("No available transport method");var g=m=>{try{h(m)}catch(v){mh(v)?P.warn(v):P.error(v),o.callback==null||o.callback({statusCode:0,error:v})}};f!=="sendBeacon"&&o.data&&o.compression===ze.GZipJS&&Eg&&typeof Promise<"u"&&!es?nv(o).then((m=>{g(m)})).catch((m=>{if(Gc(m))return es=!0,void g(k({},o,{compression:void 0,url:Cu(n.url,n.method,void 0,n.timestampMode)}));(v=>{if(!v||typeof v!="object")return!1;var x="name"in v?String(v.name):"";return Gc(v)||x===zd})(m)&&(es=!0),g(o)})):h(o)})(k({},e,{callback:n=>{var i,r;this.rateLimiter.checkForLimiting(n),400>n.statusCode||(i=(r=this.config).on_request_error)==null||i.call(r,n),e.callback==null||e.callback(n)}}))):e.fireCallbackOnDrop&&(e.callback==null||e.callback({statusCode:0}))}Pn(e){this.Rn?this.Rn.retriableRequest(e):this._send_request(e)}_execute_array(e){Xo++;try{var n,i=[],r=[],s=[];Or(e,(a=>{if(a)if(U(n=a[0]))s.push(a);else if(qe(a))try{a.call(this)}catch(l){P.error("Error executing queued PostHog call",a,l)}else U(a)&&n==="alias"?i.push(a):U(a)&&n.indexOf("capture")!==-1&&qe(this[n])?s.push(a):r.push(a)}));var o=function(a,l){Or(a,(function(u){try{if(U(u[0])){var c=l;ae(u,(function(d){c=c[d[0]].apply(c,d.slice(1))}))}else l[u[0]].apply(l,u.slice(1))}catch(d){P.error("Error executing queued PostHog call",u,d)}}))};o(i,this),o(r,this),o(s,this)}finally{Xo--}}push(e){if(Xo>0&&U(e)&&X(e[0])){var n=st.prototype[e[0]];qe(n)&&n.apply(this,e.slice(1))}else this._execute_array([e])}capture(e,n,i){var r,s,o,a,l;if(this.__loaded&&this.persistence&&this.sessionPersistence&&this.In){if(this.is_capturing())if(!A(e)&&X(e)){var u=!this.config.opt_out_useragent_filter&&this._is_bot();if(!u||this.config.__preview_capture_bot_pageviews){var c=i!=null&&i.skip_client_rate_limiting?void 0:this.rateLimiter.clientRateLimitContext();if(c==null||!c.isRateLimited){n!=null&&n.$current_url&&!X(n?.$current_url)&&(P.error("Invalid `$current_url` property provided to `posthog.capture`. Input must be a string. Ignoring provided value."),n==null||delete n.$current_url),e!=="$exception"||i!=null&&i.Wn||P.warn("Using `posthog.capture('$exception')` is unreliable because it does not attach required metadata. Use `posthog.captureException(error)` instead, which attaches required metadata automatically."),this.sessionPersistence.update_search_keyword(),this.config.save_campaign_params&&this.sessionPersistence.update_campaign_params(),this.config.save_referrer&&this.sessionPersistence.update_referrer_info(),(this.config.save_campaign_params||this.config.save_referrer)&&this.persistence.set_initial_person_info();var d=new Date,f=i?.timestamp||d,p=Xc(i?.uuid,Xt),h={uuid:p,event:e,properties:this.calculateEventProperties(e,n||{},f,p)};e===ii&&this.config.__preview_capture_bot_pageviews&&u&&(h.event="$bot_pageview",h.properties.$browser_type="bot"),c&&(h.properties.$lib_rate_limit_remaining_tokens=c.remainingTokens);var g=e==="$feature_flag_called"&&h.properties.$feature_flag_has_experiment===!1&&this.get_property(ys)===!0;i?.$set&&!g&&(h.$set=i?.$set);var m=i?.$unset;m&&(h.$unset=m);var v,x,E,y=g?void 0:this.Vn(i?.$set_once,e!==ru,e===jo);if(y&&(h.$set_once=y),i!=null&&i._noTruncate||(s=this.config.properties_string_max_length,o=h,a=L=>X(L)?L.slice(0,s):L,l=new Set,h=(function L(N,J){if(N!==Object(N))return a?a(N):N;if(!l.has(N)){var G;if(l.add(N),U(N))G=[],Or(N,(K=>{G.push(L(K))}));else{var M={};ae(N,((K,ie)=>{l.has(K)||(M[ie]=L(K))})),G=M}return G}})(o)),h.timestamp=f,A(i?.timestamp)||(h.properties.$event_time_override_provided=!0,h.properties.$event_time_override_system_time=d),g&&(h.properties=(function(L,N){N===void 0&&(N=[]);var J={},G=M=>{L[M]!==void 0&&(J[M]=L[M])};return Sg.forEach(G),N.forEach(G),J})(h.properties,_v)),e===rn.DISMISSED||e===rn.SENT){var b=n?.[Go.SURVEY_ID],I=n?.[Go.SURVEY_ITERATION];xh({id:b,current_iteration:I}),h.$set=k({},h.$set,{[(v={id:b,current_iteration:I},x=e===rn.SENT?"responded":"dismissed",E="$survey_"+x+"/"+v.id,v.current_iteration&&v.current_iteration>0&&(E="$survey_"+x+"/"+v.id+"/"+v.current_iteration),E)]:!0})}else e===rn.SHOWN&&(h.$set=k({},h.$set,{[Go.SURVEY_LAST_SEEN_DATE]:new Date().toISOString()}));if(e===Km.SHOWN){var T=n?.[bu.TOUR_TYPE];T&&(h.$set=k({},h.$set,{[bu.TOUR_LAST_SEEN_DATE+"/"+T]:new Date().toISOString()}))}var S=k({},h.properties.$set,h.$set);if(an(S)||this.setPersonPropertiesForFlags(S),!q(this.config.before_send)){var C=this.Pt(h);if(!C)return;(h=C).uuid=Xc(h.uuid,Xt)}this.dn.emit("eventCaptured",h);var R=(r=i?._url)!==null&&r!==void 0?r:this.requestRouter.endpointFor("api",this.analyticsDefaultEndpoint),O={method:"POST",url:R,data:h,compression:"best-available",timestampMode:i?._batchKey==="recordings"||/\/s\/(?:\?|$)/.test(R)?"body":"capture-body",batchKey:i?._batchKey,transport:i?.transport};return!this.config.request_batching||i&&(i==null||!i._batchKey)||i!=null&&i.send_instantly?this.Pn(O):this.In.enqueue(O),h}P.critical("This capture call is ignored due to client rate limiting.")}}else P.error("No event name provided to posthog.capture")}else P.uninitializedWarning("posthog.capture")}_addCaptureHook(e){return this.on("eventCaptured",(n=>e(n.event,n)))}$n(){var e;return(e=this.jn)!==null&&e!==void 0?e:this.jn=new yv(this)}cn(e){this._n.push(e);var n=!0;return()=>{if(n){n=!1;var i=this._n.indexOf(e);i!==-1&&this._n.splice(i,1)}}}calculateEventProperties(e,n,i,r,s){if(i=i||new Date,!this.persistence||!this.sessionPersistence)return n;var o=s?void 0:this.persistence.remove_event_timer(e),a=k({},n);if(a.token=this.config.token,a.$config_defaults=this.config.defaults,this.gn()&&(a[Tf]=!0),e==="$snapshot"){var l=k({},this.persistence.properties(),this.sessionPersistence.properties());return a.distinct_id=l.distinct_id,(!X(a.distinct_id)&&!Fe(a.distinct_id)||ma(a.distinct_id))&&P.error("Invalid distinct_id for replay event. This indicates a bug in your implementation"),a}var u,c=(function(b,I,T,S){var C,R,O,L;if(S===void 0&&(S=!1),!Qe)return{};var N,J=b?[...vi,...I||[]]:[],G=(function(Ze){for(var Te=0;Jc.length>Te;Te++){var qt=Jc[Te],gt=qt[1],rt=qt[0].exec(Ze),mt=rt&&(qe(gt)?gt(rt,Ze):gt);if(mt)return mt}return["",""]})(Qe),M=G[0],K=G[1],ie=(N=typeof navigator<"u"?navigator:void 0)!=null&&N.brave?{brave:!0}:{},ue={};A(T)||(ue.detectGoogleSearchApp=T);var we={},be=(C=navigator)==null||(C=C.userAgentData)==null?void 0:C.platform,Re=(R=navigator)==null?void 0:R.maxTouchPoints,Q=w==null||(O=w.screen)==null?void 0:O.width,de=w==null||(L=w.screen)==null?void 0:L.height,pe=w?.devicePixelRatio;A(be)||(we.userAgentDataPlatform=be),A(Re)||(we.maxTouchPoints=Re),A(Q)||(we.screenWidth=Q),A(de)||(we.screenHeight=de),A(pe)||(we.devicePixelRatio=pe);var Ne,pt,re,We,Je,Pt,$,ee,Be=ve($l({$os:M,$os_version:K,$browser:vf(Qe,navigator.vendor,ie,ue),$device:Zc(Qe),$device_type:(pt=Qe,re=we,ee=Zc(pt),ee===Xd||ee===Zd||ee==="Kobo"||ee==="Kindle Fire"||ee===ff?hi:ee===or||ee===ci||ee===ar||ee===ya?"Console":ee===ef?"Wearable":ee?ft:re?.userAgentDataPlatform==="Android"&&((We=re?.maxTouchPoints)!==null&&We!==void 0?We:0)>0?600>Math.min((Je=re?.screenWidth)!==null&&Je!==void 0?Je:0,(Pt=re?.screenHeight)!==null&&Pt!==void 0?Pt:0)/(($=re?.devicePixelRatio)!==null&&$!==void 0?$:1)?ft:hi:"Desktop"),$timezone:sh(),$timezone_offset:zm()}),{$current_url:ur(S?Sn(Ee?.href):Ee?.href,J,dr),$host:Ee?.host,$pathname:Ee?.pathname,$raw_user_agent:Qe.length>1e3?Qe.substring(0,997)+"...":Qe,$browser_version:Hg(Qe,navigator.vendor,ie,ue),$browser_language:wu(),$browser_language_prefix:(Ne=wu(),typeof Ne=="string"?Ne.split("-")[0]:void 0),$screen_height:w?.screen.height,$screen_width:w?.screen.width,$viewport_height:w?.innerHeight,$viewport_width:w?.innerWidth,$lib:oe.LIB_NAME,$lib_version:oe.LIB_VERSION,$insert_id:Math.random().toString(36).substring(2,10)+Math.random().toString(36).substring(2,10),$time:Date.now()/1e3});return oe.SDK_DIST_CHANNEL&&(Be.$sdk_dist_channel=oe.SDK_DIST_CHANNEL),Be})(this.config.mask_personal_data_properties,this.config.custom_personal_data_properties,this.config.detect_google_search_app,this.config.disable_capture_url_hashes);if(this.sessionManager){var d=this.sessionManager.checkAndGetSessionAndWindowId(s,i.getTime()),f=d.windowId;a.$session_id=d.sessionId,a.$window_id=f}this.sessionPropsManager&&ve(a,this.sessionPropsManager.getSessionProps());try{var p;this.sessionRecording&&ve(a,this.sessionRecording.sdkDebugProperties),a.$sdk_debug_retry_queue_size=(p=this.Rn)==null?void 0:p.length}catch(b){a.$sdk_debug_error_capturing_properties=String(b)}if(this.requestRouter.region===Va&&(a.$lib_custom_api_host=this.config.api_host),u=e!==ii||s?e!==Do||s?this.pageViewManager.doEvent():this.pageViewManager.doPageLeave(i):this.pageViewManager.doPageView(i,r),a=ve(a,u),e===ii&&F&&(a.title=F.title),!A(o)){var h=i.getTime()-o;a.$duration=parseFloat((h/1e3).toFixed(3))}Qe&&this.config.opt_out_useragent_filter&&(a.$browser_type=this._is_bot()?"bot":"browser");var g=this.persistence.properties(),m=this.sessionPersistence.properties();ae(["$referrer","$referring_domain"],(b=>{b in g&&delete m[b]}));var v={};if(this._n.length>0)for(var x of this._n.slice())try{ve(v,x())}catch(b){P.error("Failed to produce browser extension event properties",b)}(a=ve({},c,g,m,k({},v,a))).$is_identified=this._isIdentified(),U(this.config.property_denylist)?ae(this.config.property_denylist,(function(b){delete a[b]})):P.error(Ih+this.config.property_denylist+" or property_blacklist config: "+this.config.property_blacklist);var E=this.config.sanitize_properties;E&&(P.error(Mu),a=E(a,e));var y=this.Zn();return a.$process_person_profile=y,y&&!s&&this.Gn("_calculate_event_properties"),a}Vn(e,n,i){var r;if(n===void 0&&(n=!0),i===void 0&&(i=!1),!this.persistence||!this.Zn()||this.mn&&!i)return e;var s=this.persistence.get_initial_props(),o=(r=this.sessionPropsManager)==null?void 0:r.getSetOnceProps(),a=ve({},s,o||{},e||{}),l=this.config.sanitize_properties;return l&&(P.error(Mu),a=l(a,"$set_once")),n&&(this.mn=!0),an(a)?void 0:a}register(e,n){var i;(i=this.persistence)==null||i.register(e,n)}register_once(e,n,i){var r;(r=this.persistence)==null||r.register_once(e,n,i)}register_for_session(e){var n;(n=this.sessionPersistence)==null||n.register(e),Object.keys(e).forEach((i=>this.yn.add(i))),this.Qn()}unregister(e){var n;(n=this.persistence)==null||n.unregister(e)}unregister_for_session(e){var n;(n=this.sessionPersistence)==null||n.unregister(e),this.yn.delete(e),this.Qn()}Kn(e,n){this.register({[e]:n})}An(){this.yn.forEach((e=>{var n;(n=this.sessionPersistence)==null||n.unregister(e)})),this.yn.clear(),this.Qn()}Qn(){var e;if(this.bn)if(this.config.persistence==="memory"||(e=this.sessionPersistence)!=null&&e.xi||!Ce.N())Ce.q(this.bn);else{var n=[];this.yn.forEach((i=>n.push(i))),n.length>0?Ce.F(this.bn,n):Ce.q(this.bn)}}getFeatureFlag(e,n){var i;return(i=this.featureFlags)==null?void 0:i.getFeatureFlag(e,n)}getFeatureFlagPayload(e){var n;return(n=this.featureFlags)==null?void 0:n.getFeatureFlagPayload(e)}getFeatureFlagResult(e,n){var i;return(i=this.featureFlags)==null?void 0:i.getFeatureFlagResult(e,n)}getAllFeatureFlags(){var e,n;return(e=(n=this.featureFlags)==null?void 0:n.getAllFeatureFlags())!==null&&e!==void 0?e:[]}isFeatureEnabled(e,n){var i,r;return(i=(r=this.featureFlags)==null?void 0:r.isFeatureEnabled(e,n))!==null&&i!==void 0?i:n?.defaultValue}reloadFeatureFlags(){var e;(e=this.featureFlags)==null||e.reloadFeatureFlags()}updateFlags(e,n,i){var r;(r=this.featureFlags)==null||r.updateFlags(e,n,i)}updateEarlyAccessFeatureEnrollment(e,n,i){var r;(r=this.featureFlags)==null||r.updateEarlyAccessFeatureEnrollment(e,n,i)}getEarlyAccessFeatures(e,n,i){var r;return n===void 0&&(n=!1),(r=this.featureFlags)==null?void 0:r.getEarlyAccessFeatures(e,n,i)}on(e,n){return this.dn.on(e,n)}onFeatureFlags(e){return this.featureFlags?this.featureFlags.onFeatureFlags(e):(e([],{},{errorsLoading:!0}),()=>{})}onSurveysLoaded(e){return this.surveys?this.surveys.onSurveysLoaded(e):(e([],{isLoaded:!1,error:Oi}),()=>{})}onSessionId(e){var n,i;return(n=(i=this.sessionManager)==null?void 0:i.onSessionId(e))!==null&&n!==void 0?n:()=>{}}getSurveys(e,n){n===void 0&&(n=!1),this.surveys?this.surveys.getSurveys(e,n):e([],{isLoaded:!1,error:Oi})}getActiveMatchingSurveys(e,n){n===void 0&&(n=!1),this.surveys?this.surveys.getActiveMatchingSurveys(e,n):e([],{isLoaded:!1,error:Oi})}renderSurvey(e,n){var i;(i=this.surveys)==null||i.renderSurvey(e,n)}displaySurvey(e,n){var i;n===void 0&&(n=fv),(i=this.surveys)==null||i.displaySurvey(e,n)}cancelPendingSurvey(e){var n;(n=this.surveys)==null||n.cancelPendingSurvey(e)}canRenderSurvey(e){var n,i;return(n=(i=this.surveys)==null?void 0:i.canRenderSurvey(e))!==null&&n!==void 0?n:{visible:!1,disabledReason:Oi}}canRenderSurveyAsync(e,n){var i,r;return n===void 0&&(n=!1),(i=(r=this.surveys)==null?void 0:r.canRenderSurveyAsync(e,n))!==null&&i!==void 0?i:Promise.resolve({visible:!1,disabledReason:Oi})}Jn(e){return!e||ma(e)?(P.critical("Unique user id has not been set in posthog.identify"),!1):e===Nr?(P.critical('The string "'+e+'" was set in posthog.identify which indicates an error. This ID is only used as a sentinel value.'),!1):!["distinct_id","distinctid"].includes(e.toLowerCase())&&!["undefined","null"].includes(e.toLowerCase())||(P.critical('The string "'+e+'" was set in posthog.identify which indicates an error. This ID should be unique to the user and not a hardcoded string.'),!1)}identify(e,n,i){if(!this.__loaded||!this.persistence)return P.uninitializedWarning("posthog.identify");if(Fe(e)&&(e=e.toString(),P.warn("The first argument to posthog.identify was a number, but it should be a string. It has been converted to a string.")),this.Jn(e)&&this.Gn("posthog.identify")){var r=this.get_distinct_id();this.register({$user_id:e}),this.get_property(lr)||this.register_once({$had_persisted_distinct_id:!0,$device_id:r},""),e!==r&&e!==this.get_property(Wi)&&(this.unregister(Wi),this.register({distinct_id:e}));var s,o=(this.persistence.get_property(yt)||Xn)===Xn,a=e!==r,l=!a&&o;if(a&&o)this.persistence.set_property(yt,Pn),this.setPersonPropertiesForFlags({$set:n||{},$set_once:i||{}},!1),this.capture(jo,{distinct_id:e,$anon_distinct_id:r},{$set:n||{},$set_once:i||{}}),this.Sn=Zo(e,n,i),(s=this.featureFlags)==null||s.setAnonymousDistinctId(r);else if(l){this.persistence.set_property(yt,Pn);var u=n||{},c=i||{};this.setPersonPropertiesForFlags({$set:u,$set_once:c},!1),this.capture("$set",{$set:u,$set_once:c}),this.Sn=Zo(e,n,i)}else(n||i)&&this.setPersonProperties(n,i);a?(this.reloadFeatureFlags(),this.featureFlags?this.featureFlags.resetFlagCallReported():this.unregister(Dn)):l&&(n||i)&&this.reloadFeatureFlags()}}setPersonProperties(e,n){if((e||n)&&this.Gn("posthog.setPersonProperties")){var i=Zo(this.get_distinct_id(),e,n);this.Sn!==i?(this.setPersonPropertiesForFlags({$set:e||{},$set_once:n||{}},!0),this.capture("$set",{$set:e||{},$set_once:n||{}}),this.Sn=i):P.info("A duplicate setPersonProperties call was made with the same properties. It has been ignored.")}}unsetPersonProperties(e){var n,i=(U(e)?e:[e]).filter((r=>X(r)&&r.length>0));i.length!==0&&this.Gn("posthog.unsetPersonProperties")&&((n=this.featureFlags)==null||n.unsetPersonPropertiesForFlags(i,!0),this.capture("$set",{$unset:i}),this.Sn=null)}group(e,n,i){if(e&&n){var r=this.getGroups(),s=r[e]!==n;if(s&&this.resetGroupPropertiesForFlags(e),this.register({$groups:k({},r,{[e]:n})}),s||i){var o={$group_type:e,$group_key:n};i&&(o.$group_set=i),this.capture(ru,o)}i&&this.setGroupPropertiesForFlags({[e]:i}),s&&!i&&this.reloadFeatureFlags()}else P.error("posthog.group requires a group type and group key")}resetGroups(){this.register({$groups:{}}),this.resetGroupPropertiesForFlags(),this.reloadFeatureFlags()}setPersonPropertiesForFlags(e,n){var i;n===void 0&&(n=!0),(i=this.featureFlags)==null||i.setPersonPropertiesForFlags(e,n)}resetPersonPropertiesForFlags(e){var n;e===void 0&&(e=!0),(n=this.featureFlags)==null||n.resetPersonPropertiesForFlags(e)}setGroupPropertiesForFlags(e,n){var i;n===void 0&&(n=!0),this.Gn("posthog.setGroupPropertiesForFlags")&&((i=this.featureFlags)==null||i.setGroupPropertiesForFlags(e,n))}resetGroupPropertiesForFlags(e){var n;(n=this.featureFlags)==null||n.resetGroupPropertiesForFlags(e)}reset(e){this.Yn(e)}Yn(e,n){var i,r,s,o,a,l,u,c,d,f;if(n===void 0&&(n=!1),P.info("reset"),!this.__loaded)return P.uninitializedWarning("posthog.reset");var p,h=this.get_property(lr),g=this.get_property(Bo),m=this.get_property(jn),v=this.is_capturing();if(this.consent.reset(),n||!v||this.is_capturing()||console.warn("[PostHog.js]","reset() cleared the stored consent, and capturing is now off because of `opt_out_capturing_by_default`. Call opt_in_capturing() again, and prefer calling reset() before opting in rather than after."),(i=this.persistence)==null||i.clear(),(r=this.sessionPersistence)==null||r.clear(),this.yn.clear(),this.Qn(),A(m)||(p=this.persistence)==null||p.register({[jn]:m}),(s=this.surveys)==null||s.reset(),(o=this.Un)==null||o.stop(),(a=this.featureFlags)==null||a.reset(),(l=this.conversations)==null||l.reset(),(u=this.logs)==null||u.reset(),(c=this.metrics)==null||c.reset(),(d=this.persistence)==null||d.set_property(yt,Xn),(f=this.sessionManager)==null||f.resetSessionId(),this.Sn=null,this.config.cookieless_mode===tn)this.register_once({distinct_id:Nr,$device_id:null},"");else{var x=this.config.get_device_id(Xt());this.register_once({distinct_id:x,$device_id:e?x:h},""),e||A(g)||this.register({[Bo]:g})}this.register({$last_posthog_reset:new Date().toISOString()},1),delete this.config.identity_distinct_id,delete this.config.identity_hash,this.reloadFeatureFlags()}shutdown(e){var n=this;return ce((function*(){var i,r,s,o,a,l,u;if(n.__loaded){(i=n.Un)==null||i.stop(),(r=n.jn)==null||r.dispose(),(s=n.sessionRecording)==null||s.dispose(),(o=n.logs)==null||o.flushLogs("sendBeacon"),(a=n.metrics)==null||a.flush("sendBeacon"),(l=n.In)==null||l.unload(),(u=n.Rn)==null||u.unload();try{var c;(c=n.featureFlags)==null||c.destroy()}catch(d){P.error("Error while destroying feature flags",d)}}else P.uninitializedWarning("posthog.shutdown")}))()}setIdentity(e,n){var i;this.config.identity_distinct_id=e,this.config.identity_hash=n,this.alias(e),(i=this.conversations)==null||i.Xn()}clearIdentity(){var e;delete this.config.identity_distinct_id,delete this.config.identity_hash,(e=this.conversations)==null||e.ts()}get_distinct_id(){return this.get_property("distinct_id")}getGroups(){return this.get_property("$groups")||{}}get_session_id(){var e,n;return(e=(n=this.sessionManager)==null?void 0:n.checkAndGetSessionAndWindowId(!0).sessionId)!==null&&e!==void 0?e:""}get_session_replay_url(e){if(!this.sessionManager)return"";var n=this.sessionManager.checkAndGetSessionAndWindowId(!0),i=n.sessionStartTimestamp,r=this.requestRouter.endpointFor("ui","/project/"+this.config.token+"/replay/"+n.sessionId);if(e!=null&&e.withTimestamp&&i){var s,o=(s=e.timestampLookBack)!==null&&s!==void 0?s:10;if(!i)return r;r+="?t="+Math.max(Math.floor((new Date().getTime()-i)/1e3)-o,0)}return r}alias(e,n){return e===this.get_property(kf)?(P.critical("Attempting to create alias for existing People user - aborting."),-2):this.Gn("posthog.alias")?(A(n)&&(n=this.get_distinct_id()),e!==n?(this.Kn(Wi,e),this.capture("$create_alias",{alias:e,distinct_id:n})):(P.warn("alias matches current distinct_id - skipping api call."),this.identify(e),-1)):void 0}set_config(e){var n=k({},this.config);if(ye(e)){var i,r,s,o,a,l,u,c,d,f,p,h;ve(this.config,$u(e));var g=this.En();(i=this.persistence)==null||i.update_config(this.config,n,g),this.sessionPersistence=this.config.persistence==="sessionStorage"||this.config.persistence==="memory"?this.persistence:new zo(k({},this.config,{persistence:"sessionStorage"}),g,!1);var m=this.Cn(this.config.debug);kt(m)&&(this.config.debug=m),kt(this.config.debug)&&(this.config.debug?(oe.DEBUG=!0,fe.N()&&fe.F("ph_debug",!0),P.info("set_config",{config:e,oldConfig:n,newConfig:k({},this.config)})):(oe.DEBUG=!1,fe.N()&&fe.q("ph_debug"))),(r=this.featureFlags)==null||r.updateConfig==null||r.updateConfig(this.config,this.Qi()),(s=this.exceptionObserver)==null||s.onConfigChange(),(o=this.exceptions)==null||o.onConfigChange(),(a=this.sessionRecording)==null||a.startIfEnabledOrStop(),(l=this.tracingHeaders)==null||l.startIfEnabledOrStop(),(u=this.autocapture)==null||u.startIfEnabled(),(c=this.heatmaps)==null||c.startIfEnabled(),(d=this.exceptionObserver)==null||d.startIfEnabledOrStop(),(f=this.deadClicksAutocapture)==null||f.startIfEnabledOrStop(),(p=this.surveys)==null||p.loadIfEnabled(),this.es(),(h=this.externalIntegrations)==null||h.startIfEnabledOrStop()}}_overrideSDKInfo(e,n){oe.LIB_NAME=e,oe.LIB_VERSION=n}startSessionRecording(e){var n,i,r,s,o,a=e===!0,l={sampling:a||!(e==null||!e.sampling),linked_flag:a||!(e==null||!e.linked_flag),url_trigger:a||!(e==null||!e.url_trigger),event_trigger:a||!(e==null||!e.event_trigger)};Object.values(l).some(Boolean)&&((n=this.sessionManager)==null||n.checkAndGetSessionAndWindowId(),l.sampling&&((i=this.sessionRecording)==null||i.overrideSampling()),l.linked_flag&&((r=this.sessionRecording)==null||r.overrideLinkedFlag()),l.url_trigger&&((s=this.sessionRecording)==null||s.overrideTrigger("url")),l.event_trigger&&((o=this.sessionRecording)==null||o.overrideTrigger("event"))),this.set_config({disable_session_recording:!1})}stopSessionRecording(){this.set_config({disable_session_recording:!0})}sessionRecordingStarted(){var e;return!((e=this.sessionRecording)==null||!e.started)}captureException(e,n){if(this.exceptions){var i=new Error("PostHog syntheticException"),r=this.exceptions.buildProperties(e,{handled:!0,syntheticException:i});return this.exceptions.sendExceptionEvent(k({},r,n))}}addExceptionStep(e,n){var i;(i=this.exceptions)==null||i.addExceptionStep(e,n)}captureLog(e){var n;(n=this.logs)==null||n.captureLog(e)}get logger(){var e,n;return(e=(n=this.logs)==null?void 0:n.logger)!==null&&e!==void 0?e:st.rs}startExceptionAutocapture(e){this.set_config({capture_exceptions:e==null||e})}stopExceptionAutocapture(){this.set_config({capture_exceptions:!1})}loadToolbar(e){var n,i;return(n=(i=this.toolbar)==null?void 0:i.loadToolbar(e))!==null&&n!==void 0&&n}get_property(e){var n;return(n=this.persistence)==null?void 0:n.props[e]}getSessionProperty(e){var n;return(n=this.sessionPersistence)==null?void 0:n.props[e]}toString(){var e,n=(e=this.config.name)!==null&&e!==void 0?e:ri;return n!==ri&&(n=ri+"."+n),n}_isIdentified(){var e,n;return((e=this.persistence)==null?void 0:e.get_property(yt))===Pn||((n=this.sessionPersistence)==null?void 0:n.get_property(yt))===Pn}Zn(){var e,n;return!(this.config.person_profiles==="never"||this.config.person_profiles===Na&&!this._isIdentified()&&an(this.getGroups())&&((e=this.persistence)==null||(e=e.props)==null||!e[Wi])&&((n=this.persistence)==null||(n=n.props)==null||!n[bs]))}zn(){return this.config.capture_pageleave===!0||this.config.capture_pageleave==="if_capture_pageview"&&(this.config.capture_pageview===!0||this.config.capture_pageview==="history_change")}createPersonProfile(){this.Zn()||this.Gn("posthog.createPersonProfile")&&this.setPersonProperties({},{})}setInternalOrTestUser(){this.Gn("posthog.setInternalOrTestUser")&&this.setPersonProperties({$internal_or_test_user:!0})}Gn(e){return this.config.person_profiles==="never"?(P.error(e+' was called, but process_person is set to "never". This call will be ignored.'),!1):(this.Kn(bs,!0),!0)}En(){if(this.config.cookieless_mode==="always")return!0;var e=this.consent.isOptedOut();return this.config.disable_persistence||e&&!(!this.config.opt_out_persistence_by_default&&this.config.cookieless_mode!==Bn)}es(){var e,n,i,r,s=this.En();return((e=this.persistence)==null?void 0:e.xi)!==s&&((i=this.persistence)==null||i.set_disabled(s)),((n=this.sessionPersistence)==null?void 0:n.xi)!==s&&((r=this.sessionPersistence)==null||r.set_disabled(s)),s&&(this.yn.clear(),this.Qn()),s}opt_in_capturing(e){var n;if(this.config.cookieless_mode!==tn){if(this.gn()){var i,r,s,o,a;this.Yn(!0,!0),(i=this.sessionManager)==null||i.destroy(),(r=this.pageViewManager)==null||r.destroy(),this.sessionManager=new Pu(this),this.pageViewManager=new _u(this),this.persistence&&(this.sessionPropsManager=new Au(this,this.sessionManager,this.persistence));var l,u=(s=(o=this.config.__extensionClasses)==null?void 0:o.sessionRecording)!==null&&s!==void 0?s:(a=st.__defaultExtensionClasses)==null?void 0:a.sessionRecording;u&&(this.sessionRecording=this.pn(this.sessionRecording,new u(this)),this.hn&&((l=this.sessionRecording)==null||l.onRemoteConfig==null||l.onRemoteConfig(this.hn)))}var c,d;this.consent.optInOut(!0),this.es(),this.Bn(),(n=this.sessionRecording)==null||n.startIfEnabledOrStop(),this.config.cookieless_mode==Bn&&((c=this.surveys)==null||c.loadIfEnabled()),(A(e?.captureEventName)||e!=null&&e.captureEventName)&&this.capture((d=e?.captureEventName)!==null&&d!==void 0?d:"$opt_in",e?.captureProperties,{send_instantly:!0}),this.config.capture_pageview&&this.Hn()}else P.warn(Tu)}opt_out_capturing(){var e,n,i;this.config.cookieless_mode!==tn?(this.config.cookieless_mode===Bn&&this.consent.isOptedIn()&&this.Yn(!0,!0),this.consent.optInOut(!1),this.es(),this.config.cookieless_mode===Bn&&(this.register({distinct_id:Nr,$device_id:null}),(e=this.sessionRecording)==null||e.stopRecording(),this.sessionRecording=void 0,(n=this.sessionManager)==null||n.destroy(),(i=this.pageViewManager)==null||i.destroy(),this.sessionManager=void 0,this.sessionPropsManager=void 0,this.config.capture_pageview&&this.Hn(),this.Bn())):P.warn(Tu)}has_opted_in_capturing(){return this.consent.isOptedIn()}has_opted_out_capturing(){return this.consent.isOptedOut()}get_explicit_consent_status(){var e=this.consent.consent;return e===1?"granted":e===0?"denied":"pending"}is_capturing(){return this.config.cookieless_mode===tn||(this.config.cookieless_mode===Bn?this.consent.isRejected()||this.consent.isOptedIn():!this.has_opted_out_capturing())}clear_opt_in_out_capturing(){this.consent.reset(),this.es()}_is_bot(){return Ve?yh(Ve,this.config.custom_blocked_useragents):void 0}Hn(){F&&(F.visibilityState==="visible"?this.wn||(this.wn=!0,this.capture(ii,{title:F.title},{send_instantly:!0}),this.kn&&(F.removeEventListener(Es,this.kn),this.kn=null)):this.kn||(this.kn=this.Hn.bind(this),Se(F,Es,this.kn)))}debug(e){e===!1?(w?.console.log("You've disabled debug mode."),this.set_config({debug:!1})):(w?.console.log("You're now in debug mode. All calls to PostHog will be logged in your console.\nYou can disable this with `posthog.debug(false)`."),this.set_config({debug:!0}))}Qi(){var e=this.Mn||{};return"advanced_disable_flags"in e?!!e.advanced_disable_flags:this.config.advanced_disable_flags!==!1?!!this.config.advanced_disable_flags:this.config.advanced_disable_decide===!0?(P.warn("Config field 'advanced_disable_decide' is deprecated. Please use 'advanced_disable_flags' instead. The old field will be removed in a future major version."),!0):(function(n,i,r,s,o){var a=i in n&&!q(n[i]),l=r in n&&!q(n[r]);return a?n[i]:!!l&&(o&&o.warn("Config field '"+r+"' is deprecated. Please use '"+i+"' instead. The old field will be removed in a future major version."),n[r])})(e,"advanced_disable_flags","advanced_disable_decide",0,P)}Pt(e){var n;if(q(this.config.before_send))return e;var i=Object.keys((n=e.properties)!==null&&n!==void 0?n:{}).filter(Fg),r=U(this.config.before_send)?this.config.before_send:[this.config.before_send],s=e;for(var o of r){if(s=o(s),q(s)){var a="Event '"+e.event+"' was rejected in beforeSend function";return Pg(e.event)?P.warn(a+". This can cause unexpected behavior."):P.info(a),null}s.properties&&!an(s.properties)||P.warn("Event '"+e.event+"' has no properties after beforeSend function, this is likely an error.")}for(var l of i)if(s.properties&&q(s.properties[l]))return P.warn("Event '"+e.event+"' had its '"+l+"' property removed in a beforeSend function. This property is required for ingestion, so the event will be dropped."),null;return s}getPageViewId(){var e;return(e=this.pageViewManager.ui)==null?void 0:e.pageViewId}captureTraceFeedback(e,n){this.capture("$ai_feedback",{$ai_trace_id:String(e),$ai_feedback_text:n})}captureTraceMetric(e,n,i){this.capture("$ai_metric",{$ai_trace_id:String(e),$ai_metric_name:n,$ai_metric_value:String(i)})}Cn(e){var n=kt(e)&&!e,i=fe.N()&&fe.P("ph_debug")==="true";return!n&&(!!i||e)}}st.__defaultExtensionClasses={},st.rs=(()=>{var t=()=>{};return{trace:t,debug:t,info:t,warn:t,error:t,fatal:t}})(),(function(t,e){for(var n=0;e.length>n;n++)t.prototype[e[n]]=ym(t.prototype[e[n]])})(st,["identify"]);class Lu{constructor(e){this.disabled=e===!1;var n=ye(e)?e:{};this.thresholdPx=n.threshold_px||30,this.timeoutMs=n.timeout_ms||1e3,this.clickCount=n.click_count||3,this.clicks=[]}isRageClick(e,n,i){if(this.disabled)return!1;var r=this.clicks[this.clicks.length-1];if(r&&Math.abs(e-r.x)+Math.abs(n-r.y)i-r.timestamp){if(this.clicks.push({x:e,y:n,timestamp:i}),this.clicks.length===this.clickCount)return!0}else this.clicks=[{x:e,y:n,timestamp:i}];return!1}}var ea="$copy_autocapture",ta=_e("[AutoCapture]");function na(t,e){return e.length>t?e.slice(0,t)+"...":e}function Ev(t){if(t.previousElementSibling)return t.previousElementSibling;var e=t;do e=e.previousSibling;while(e&&!xn(e));return e}function Sv(t,e){var n,i,r=e.e,s=e.maskAllElementAttributes,o=e.maskAllText,a=e.elementAttributeIgnoreList,l=e.elementsChainAsString,u=e.disableCaptureUrlHashes;if(!xn(t))return{props:{}};for(var c=[t],d=new Set([t]),f=t;f.parentNode&&!lt(f,"body")&&Hf>c.length;)if(Uf(f.parentNode)){var p=f.parentNode.host;if(d.has(p))break;d.add(p),c.push(p),f=p}else{if(!xn(f.parentNode)||d.has(f.parentNode))break;d.add(f.parentNode),c.push(f.parentNode),f=f.parentNode}var h,g,m=[],v={},x=!1,E=!1;if(ae(c,(S=>{var C=Da(S);if(lt(S,"a")){var R=S.getAttribute("href");x=!!(C&&R&&er(R))&&(u?Sn(R):R)}j(Is(S),"ph-no-capture")&&(E=!0),m.push((function(L,N,J,G,M){M===void 0&&(M=!1);var K=L.tagName.toLowerCase(),ie={tag_name:K};Nl.indexOf(K)>-1&&!J&&(ie.$el_text=K.toLowerCase()==="a"||K.toLowerCase()==="button"?na(1024,mu(L)):na(1024,cr(L)));var ue=Is(L);ue.length>0&&(ie.classes=ue.filter((function(Q){return Q!==""}))),ae(L.attributes,(function(Q){var de;if((!Gf(L)||["name","id","class","aria-label"].indexOf(Q.name)!==-1)&&(G==null||!G.includes(Q.name))&&!N&&er(Q.value)&&(!X(de=Q.name)||de.substring(0,10)!=="_ngcontent"&&de.substring(0,7)!=="_nghost")){var pe=Q.value;Q.name==="class"&&(pe=Ll(pe).join(" ")),ie["attr__"+Q.name]=na(1024,Q.name==="href"&&M?Sn(pe):pe)}}));for(var we=1,be=1,Re=L;Re=Ev(Re);)we++,Re.tagName===L.tagName&&be++;return ie.nth_child=we,ie.nth_of_type=be,ie})(S,s,o,a,u));var O=(function(L){if(!Da(L))return{};var N={};return ae(L.attributes,(function(J){if(J.name&&J.name.indexOf("data-ph-capture-attribute")===0){var G=J.name.replace("data-ph-capture-attribute-",""),M=J.value;G&&M&&er(M)&&(N[G]=M)}})),N})(S);ve(v,O)})),E)return{props:{},explicitNoCapture:E};if(o||(m[0].$el_text=lt(t,"a")||lt(t,"button")?mu(t):cr(t)),x){var y,b;m[0].attr__href=x;var I=(y=ks(x))==null?void 0:y.host,T=w==null||(b=w.location)==null?void 0:b.host;I&&T&&I!==T&&(h=x)}return{props:ve({$event_type:r.type,$ce_version:1},l?{}:{$elements:m},{$elements_chain:(g=m,(function(S){return S.map((C=>{var R,O,L="";if(C.tag_name&&(L+=C.tag_name),C.attr_class)for(var N of(C.attr_class.sort(),C.attr_class))L+="."+N.replace(/"/g,"");var J=k({},C.text?{text:C.text}:{},{"nth-child":(R=C.nth_child)!==null&&R!==void 0?R:0,"nth-of-type":(O=C.nth_of_type)!==null&&O!==void 0?O:0},C.href?{href:C.href}:{},C.attr_id?{attr_id:C.attr_id}:{},C.attributes),G={};return Qr(J).sort(((M,K)=>M[0].localeCompare(K[0]))).forEach((M=>{var K=M[1];return G[vu(M[0].toString())]=vu(K.toString())})),(L+=":")+Qr(G).map((M=>M[0]+'="'+M[1]+'"')).join("")})).join(";")})((function(S){return S.map((C=>{var R,O,L={text:(R=C.$el_text)==null?void 0:R.slice(0,400),tag_name:C.tag_name,href:(O=C.attr__href)==null?void 0:O.slice(0,2048),attr_class:Om(C),attr_id:C.attr__id,nth_child:C.nth_child,nth_of_type:C.nth_of_type,attributes:{}};return Qr(C).filter((N=>N[0].indexOf("attr__")===0)).forEach((N=>L.attributes[N[0]]=N[1])),L}))})(g)))},(n=m[0])!=null&&n.$el_text?{$el_text:(i=m[0])==null?void 0:i.$el_text}:{},h&&r.type==="click"?{$external_click_url:h}:{},v)}}var Bi=_e("[ExceptionAutocapture]"),Nu=()=>{},xv=_e("[TracingHeaders]"),Tn=_e("[Web Vitals]"),Ou=9e5,Bu="disabled",Du="lazy_loading",Di="awaiting_config",Wr="missing_config";_e("[SessionRecording]"),_e("[SessionRecording]");var Ga="[SessionRecording]",Kt=_e(Ga),Iv=_e("[Heatmaps]");function ia(t){return ye(t)&&"clientX"in t&&"clientY"in t&&Fe(t.clientX)&&Fe(t.clientY)}var qr=_e("[Product Tours]"),ra=t=>{var e;return!t.config.disable_product_tours&&!((e=t.persistence)==null||!e.get_property(Rl))},kv=["$set_once","$set"],Ft=_e("[SiteApps]"),ju="Error while initializing PostHog app with config id ";function ti(t,e,n){if(q(t))return!1;switch(n){case"exact":return t===e;case"contains":var i=e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/_/g,".").replace(/%/g,".*");return new RegExp(i,"i").test(t);case"regex":try{return new RegExp(e).test(t)}catch{return!1}default:return!1}}class Cv{constructor(e){this.ns=new jl,this.ss=(n,i)=>this.os(n,i)&&this.ls(n,i)&&this.us(n,i)&&this.hs(n,i),this.os=(n,i)=>i==null||!i.event||n?.event===i?.event,this._instance=e,this.ds=new Set,this.vs=new Set}init(){var e,n;A((e=this._instance)==null?void 0:e._addCaptureHook)||(n=this._instance)==null||n._addCaptureHook(((i,r)=>{this.on(i,r)}))}register(e){var n,i;if(!A((n=this._instance)==null?void 0:n._addCaptureHook)&&(e.forEach((o=>{var a,l;(a=this.vs)==null||a.add(o),(l=o.steps)==null||l.forEach((u=>{var c;(c=this.ds)==null||c.add(u?.event||"")}))})),(i=this._instance)!=null&&i.autocapture)){var r,s=new Set;e.forEach((o=>{var a;(a=o.steps)==null||a.forEach((l=>{l!=null&&l.selector&&s.add(l?.selector)}))})),(r=this._instance)==null||r.autocapture.setElementSelectors(s)}}on(e,n){var i;n!=null&&e.length!=0&&(this.ds.has(e)||this.ds.has(n.event))&&this.vs&&((i=this.vs)==null?void 0:i.size)>0&&this.vs.forEach((r=>{this.cs(n,r)&&this.ns.emit("actionCaptured",r.name)}))}fs(e){this.onAction("actionCaptured",(n=>e(n)))}cs(e,n){if(n?.steps==null)return!1;for(var i of n.steps)if(this.ss(e,i))return!0;return!1}onAction(e,n){return this.ns.on(e,n)}ls(e,n){if(n!=null&&n.url){var i,r=e==null||(i=e.properties)==null?void 0:i.$current_url;if(!r||typeof r!="string"||!ti(r,n.url,n.url_matching||"contains"))return!1}return!0}us(e,n){return!!this.ps(e,n)&&!!this.gs(e,n)&&!!this.ys(e,n)}ps(e,n){var i;if(n==null||!n.href)return!0;var r=this.bs(e);if(r.length>0)return r.some((a=>ti(a.href,n.href,n.href_matching||"exact")));var s,o=(e==null||(i=e.properties)==null?void 0:i.$elements_chain)||"";return!!o&&ti((s=o.match(/(?::|")href="(.*?)"/))?s[1]:"",n.href,n.href_matching||"exact")}gs(e,n){var i;if(n==null||!n.text)return!0;var r=this.bs(e);if(r.length>0)return r.some((u=>ti(u.text,n.text,n.text_matching||"exact")||ti(u.$el_text,n.text,n.text_matching||"exact")));var s,o,a,l=(e==null||(i=e.properties)==null?void 0:i.$elements_chain)||"";return!!l&&(s=(function(u){for(var c,d=[],f=/(?::|")text="(.*?)"/g;!q(c=f.exec(u));)d.includes(c[1])||d.push(c[1]);return d})(l),o=n.text,a=n.text_matching||"exact",s.some((u=>ti(u,o,a))))}ys(e,n){var i,r;if(n==null||!n.selector)return!0;var s=e==null||(i=e.properties)==null?void 0:i.$element_selectors;if(s!=null&&s.includes(n.selector))return!0;var o=(e==null||(r=e.properties)==null?void 0:r.$elements_chain)||"";if(n.selector_regex&&o)try{return new RegExp(n.selector_regex).test(o)}catch{return!1}return!1}bs(e){var n;return(e==null||(n=e.properties)==null?void 0:n.$elements)==null?[]:e?.properties.$elements}hs(e,n){return n==null||!n.properties||n.properties.length===0||bh(n.properties.reduce(((i,r)=>{var s=U(r.value)?r.value.map(String):r.value!=null?[String(r.value)]:[];return i[r.key]={values:s,operator:r.operator||"exact"},i}),{}),e?.properties)}}class Av{constructor(e){var n;this._s=[],this._instance=e,this.ws=new Map,this.ks=new Map,this.xs=new Map,(n=this._instance)==null||n.onSessionId==null||n.onSessionId((i=>this.Ss(i)))}Cs(e){return!1}Ms(){return null}Ts(e){}Es(){}Is(e,n){return!!e&&bh(e.propertyFilters,n?.properties)}Ps(e,n){var i=new Map;return e.forEach((r=>{var s;(s=r.conditions)==null||(s=s[n])==null||(s=s.values)==null||s.forEach((o=>{if(o!=null&&o.name){var a=i.get(o.name)||[];a.push(r.id),i.set(o.name,a)}}))})),i}Rs(e,n,i){var r=(i===Mi.Activation?this.ws:this.ks).get(e),s=[];return this.As((o=>{s=o.filter((a=>r?.includes(a.id)))})),s.filter((o=>{var a,l=(a=o.conditions)==null||(a=a[i])==null||(a=a.values)==null?void 0:a.find((u=>u.name===e));return this.Is(l,n)}))}register(e){var n;A((n=this._instance)==null?void 0:n._addCaptureHook)||(this.Fs(e),this.Ls(e))}Ls(e){var n=e.filter((i=>{var r,s;return((r=i.conditions)==null?void 0:r.actions)&&((s=i.conditions)==null||(s=s.actions)==null||(s=s.values)==null?void 0:s.length)>0}));n.length!==0&&(this.Os==null&&(this.Os=new Cv(this._instance),this.Os.init(),this.Os.fs((i=>{this.onAction(i)}))),n.forEach((i=>{var r,s,o,a,l;i.conditions&&(r=i.conditions)!=null&&r.actions&&(s=i.conditions)!=null&&(s=s.actions)!=null&&s.values&&((o=i.conditions)==null||(o=o.actions)==null||(o=o.values)==null?void 0:o.length)>0&&((a=this.Os)==null||a.register(i.conditions.actions.values),(l=i.conditions)==null||(l=l.actions)==null||(l=l.values)==null||l.forEach((u=>{if(u&&u.name){var c=this.xs.get(u.name);c&&c.push(i.id),this.xs.set(u.name,c||[i.id])}})))})))}Fs(e){var n,i=e.filter((s=>{var o,a;return((o=s.conditions)==null?void 0:o.events)&&((a=s.conditions)==null||(a=a.events)==null||(a=a.values)==null?void 0:a.length)>0})),r=e.filter((s=>{var o,a;return((o=s.conditions)==null?void 0:o.cancelEvents)&&((a=s.conditions)==null||(a=a.cancelEvents)==null||(a=a.values)==null?void 0:a.length)>0}));i.length===0&&r.length===0||((n=this._instance)==null||n._addCaptureHook(((s,o)=>{this.onEvent(s,o)})),this.ws=this.Ps(e,Mi.Activation),this.ks=this.Ps(e,Mi.Cancellation))}onEvent(e,n){var i,r,s=this.Ds(),o=(n==null||(i=n.properties)==null?void 0:i.$survey_id)||(n==null||(r=n.properties)==null?void 0:r.$product_tour_id);if(o&&this.getActivatedIds().includes(o)){var a=this.$s(e,o);if(a==="consume")return s.info("event consumed activated item, removing it",{event:e,itemId:o}),void this.Ns([o]);if(a==="persist")return s.info("shown item promoted to persisted activation",{event:e,itemId:o}),this.qs(o),void this.js([o])}if(this.ks.has(e)){var l=this.Rs(e,n,Mi.Cancellation);l.length>0&&(s.info("cancel event matched, cancelling items",{event:e,itemsToCancel:l.map((c=>c.id))}),this.Ns(l.map((c=>c.id))),l.forEach((c=>this.Bs(c.id))))}if(this.ws.has(e)){s.info("event name matched",{event:e,eventPayload:n,items:this.ws.get(e)});var u=this.Rs(e,n,Mi.Activation);this.Hs(u.map((c=>c.id)))}}onAction(e){this.xs.has(e)&&this.Hs(this.xs.get(e)||[])}Hs(e){var n;if(e.length!==0){var i=!((n=this._instance)==null||n.get_session_id==null||!n.get_session_id()),r=[];for(var s of e)i&&this.Cs(s)?this.qs(s)&&this.Us(s):r.push(s);r.length>0&&(this._s=[...new Set([...this._s,...r])]),this.Ds().info("updating activated items",{activatedItems:this.getActivatedIds()})}}qs(e){this._s=this._s.filter((i=>i!==e));var n=this.zs();return!n.includes(e)&&(this.Ws([...n,e]),this.Vs(),!0)}Ns(e){var n=new Set(e);this._s=this._s.filter((s=>!n.has(s)));var i=this.Zs(),r=i.filter((s=>!n.has(s)));r.length!==i.length&&(this.Ws(r),r.length===0&&this.Gs()),this.js(e)}Qs(){var e,n=this.Ms();if(!n)return{};var i=(e=this._instance)==null||(e=e.persistence)==null?void 0:e.props[n];return i&&typeof i=="object"?i:{}}Us(e){if(this.Ms()){var n=this.Qs();this.Ts(k({},n,{[e]:Date.now()}))}}js(e){if(this.Ms()){var n=this.Qs(),i={},r=!1;for(var s of Object.entries(n)){var o=s[0],a=s[1];e.includes(o)?r=!0:i[o]=a}r&&(an(i)?this.Es():this.Ts(i))}}Ks(){this.Ms()&&this.Es()}getActivationTimestamp(e){if(this.zs().includes(e)){var n=this.Qs()[e];return Fe(n)?n:void 0}}Zs(){var e,n=this.Js();return((e=this._instance)==null||(e=e.persistence)==null?void 0:e.props[n])||[]}zs(){var e,n,i=this.Zs();if(i.length===0)return[];var r=(e=this._instance)==null||(e=e.persistence)==null?void 0:e.props[this.Ys()],s=(n=this._instance)==null||n.get_session_id==null?void 0:n.get_session_id();return s&&r===s?i:[]}Vs(){var e,n=(e=this._instance)==null||e.get_session_id==null?void 0:e.get_session_id();n&&this.Xs(n)}Gs(){this.ta()}Ss(e){var n,i=(n=this._instance)==null||(n=n.persistence)==null?void 0:n.props[this.Ys()];if(i&&i!==e){var r=this.Zs(),s=this.Qs();r.length>0&&(this.Ws([]),r.filter((o=>Fe(s[o]))).forEach((o=>this.Bs(o)))),this.Gs(),this.Ks()}}getActivatedIds(){return[...new Set([...this.zs(),...this._s])].filter((e=>!this.ea(e)))}reset(){this._s=[],this.Zs().length>0&&this.Ws([]),this.Gs(),this.Ks()}getEventToItemsMap(){return this.ws}ia(){return this.Os}}class Pv extends Av{constructor(e){super(e)}Js(){return Ra}Ys(){return Jr}Ms(){return Zr}Ts(e){var n;(n=this._instance)==null||(n=n.persistence)==null||n.register({[Zr]:e})}Es(){var e;(e=this._instance)==null||(e=e.persistence)==null||e.unregister(Zr)}Cs(e){var n,i;this.As((s=>{i=s.find((o=>o.id===e))}));var r=(n=i)==null||(n=n.appearance)==null?void 0:n.surveyPopupDelaySeconds;return Fe(r)&&r>0}ra(){return rn.SHOWN}As(e){var n;(n=this._instance)==null||n.getSurveys(e)}Bs(e){var n;(n=this._instance)==null||n.cancelPendingSurvey(e)}Ds(){return te}Ws(e){var n;(n=this._instance)==null||(n=n.persistence)==null||n.register({[Ra]:e})}Xs(e){var n;(n=this._instance)==null||(n=n.persistence)==null||n.register({[Jr]:e})}ta(){var e;(e=this._instance)==null||(e=e.persistence)==null||e.unregister(Jr)}ea(){return!1}$s(e,n){var i;this.As((s=>{i=s.find((o=>o.id===n))}));var r=!i||(function(s){var o;return Eh(s)&&!((o=s.conditions)==null||(o=o.events)==null||!o.repeatedActivation)||s.schedule==="always"})(i);return r?e===rn.SHOWN?"consume":"ignore":e===rn.SHOWN?"persist":e===rn.DISMISSED||e===rn.SENT?"consume":"ignore"}getSurveys(){return this.getActivatedIds()}getEventToSurveys(){return this.getEventToItemsMap()}}var zr="SDK is not enabled or survey functionality is not yet loaded",Uu="Disabled. Not loading surveys.",Fv=w!=null&&w.location?Cs(w.location.hash,"__posthog")||Cs(location.hash,"state"):null,Hu="_postHogToolbarParams",Wu=_e("[Toolbar]"),qu=_e("[FeatureFlags]");class Rv{constructor(e,n){n===void 0&&(n=!1),this.na=!1,this.update(e,n)}update(e,n){this.sa=((i,r)=>{var s,o,a,l;return{bootstrap:{featureFlags:(s=i.bootstrap)==null?void 0:s.featureFlags,featureFlagPayloads:(o=i.bootstrap)==null?void 0:o.featureFlagPayloads},remoteRequestsDisabled:r,featureFlagsDisabled:!!i.advanced_disable_feature_flags,onlyEvaluateSurveyFeatureFlags:!!i.advanced_only_evaluate_survey_feature_flags,deduplicateCallsPerSession:!!i.advanced_feature_flags_dedup_per_session,cacheTtlMs:i.feature_flag_cache_ttl_ms,requestTimeoutMs:i.feature_flag_request_timeout_ms,compression:i.disable_compression?"none":"base64",evaluationContexts:(a=(l=i.evaluation_contexts)!==null&&l!==void 0?l:i.evaluation_environments)!==null&&a!==void 0?a:[],flagKeys:U(i.flag_keys)?i.flag_keys:void 0}})(e,n),!e.evaluation_environments||e.evaluation_contexts||this.na||(qu.warn("evaluation_environments is deprecated. Use evaluation_contexts instead. evaluation_environments will be removed in a future version."),this.na=!0),A(e.flag_keys)||U(e.flag_keys)||qu.error("Invalid flag_keys found:",e.flag_keys,"Expected array of non-empty strings")}get(){return this.sa}}var zu=_e("[FeatureFlags]"),Mn=_e("[FeatureFlags]",{debugEnabled:!0}),sa=`" failed. Feature flags didn't load in time.`,Vu="connection_error",Gu=t=>{for(var e={},n=0;t.length>n;n++)e[t[n]]=!0;return e},Ku=t=>{var e={};for(var n of Qr(t||{})){var i=n[1];i&&(e[n[0]]=i)}return e},Rt=_e("[Error tracking]"),Yu="Refusing to render web experiment since the viewer is a likely bot",Tv={icontains:(t,e)=>e.toLowerCase().indexOf(t.toLowerCase())>-1,not_icontains:(t,e)=>e.toLowerCase().indexOf(t.toLowerCase())===-1,regex:(t,e)=>Fs(e,t),not_regex:(t,e)=>!Fs(e,t),exact:(t,e)=>e===t,is_not:(t,e)=>e!==t};class De{get Ne(){return this._instance.config}constructor(e){var n=this;this.getWebExperimentsAndEvaluateDisplayLogic=function(i){i===void 0&&(i=!1),n.getWebExperiments((r=>{De.aa("retrieved web experiments from the server"),n.oa=new Map,r.forEach((s=>{if(s.feature_flag_key){var o;n.oa&&(De.aa("setting flag key ",s.feature_flag_key," to web experiment ",s),(o=n.oa)==null||o.set(s.feature_flag_key,s));var a=n._instance.getFeatureFlag(s.feature_flag_key);X(a)&&s.variants[a]&&n.la(s.name,a,s.variants[a].transforms)}else if(s.variants)for(var l in s.variants){var u=s.variants[l];De.ua(u,n._instance)&&n.la(s.name,l,u.transforms)}}))}),i)},this._instance=e,this._instance.onFeatureFlags((i=>{this.onFeatureFlags(i)}))}initialize(){}onFeatureFlags(e){if(this._is_bot())De.aa(Yu);else if(!this.Ne.disable_web_experiments){if(q(this.oa))return this.oa=new Map,this.loadIfEnabled(),void this.previewWebExperiment();De.aa("applying feature flags",e),e.forEach((n=>{var i;if(this.oa&&(i=this.oa)!=null&&i.has(n)){var r,s=this._instance.getFeatureFlag(n),o=(r=this.oa)==null?void 0:r.get(n);s&&o!=null&&o.variants[s]&&this.la(o.name,s,o.variants[s].transforms)}}))}}previewWebExperiment(){var e=De.getWindowLocation();if(e!=null&&e.search){var n=mi(e?.search,"__experiment_id"),i=mi(e?.search,"__experiment_variant");n&&i&&(De.aa("previewing web experiments "+n+" && "+i),this.getWebExperiments((r=>{this.ha(parseInt(n),i,r)}),!1,!0))}}loadIfEnabled(){this.Ne.disable_web_experiments||this.getWebExperimentsAndEvaluateDisplayLogic()}getWebExperiments(e,n,i){if(this.Ne.disable_web_experiments&&!i)return e([]);var r=this._instance.get_property("$web_experiments");if(r&&!n)return e(r);this._instance._send_request({url:this._instance.requestRouter.endpointFor("api","/api/web_experiments/?token="+this.Ne.token),method:"GET",timestampMode:"query",callback:s=>e(s.statusCode===200&&s.json&&s.json.experiments||[])})}ha(e,n,i){var r=i.filter((s=>s.id===e));r&&r.length>0&&(De.aa("Previewing web experiment ["+r[0].name+"] with variant ["+n+"]"),this.la(r[0].name,n,r[0].variants[n].transforms))}static ua(e,n){return!q(e.conditions)&&De.da(e,n)&&De.va(e)}static da(e,n){var i;if(q(e.conditions)||q((i=e.conditions)==null?void 0:i.url))return!0;var r=De.getWindowLocation();if(r){var s,o,a,l=Bf(n,r.href);return(s=e.conditions)==null||!s.url||Tv[(o=(a=e.conditions)==null?void 0:a.urlMatchType)!==null&&o!==void 0?o:"icontains"](e.conditions.url,l)}return!1}static getWindowLocation(){return w?.location}static va(e){var n;if(q(e.conditions)||q((n=e.conditions)==null?void 0:n.utm))return!0;var i=Qf();if(i.utm_source){var r,s,o,a,l,u,c,d,f=(r=e.conditions)==null||(r=r.utm)==null||!r.utm_campaign||((s=e.conditions)==null||(s=s.utm)==null?void 0:s.utm_campaign)==i.utm_campaign,p=(o=e.conditions)==null||(o=o.utm)==null||!o.utm_source||((a=e.conditions)==null||(a=a.utm)==null?void 0:a.utm_source)==i.utm_source,h=(l=e.conditions)==null||(l=l.utm)==null||!l.utm_medium||((u=e.conditions)==null||(u=u.utm)==null?void 0:u.utm_medium)==i.utm_medium,g=(c=e.conditions)==null||(c=c.utm)==null||!c.utm_term||((d=e.conditions)==null||(d=d.utm)==null?void 0:d.utm_term)==i.utm_term;return f&&h&&g&&p}return!1}static aa(e){for(var n=arguments.length,i=new Array(n>1?n-1:0),r=1;n>r;r++)i[r-1]=arguments[r];P.info("[WebExperiments] "+e,i)}la(e,n,i){this._is_bot()?De.aa(Yu):n!=="control"?i.forEach((r=>{if(r.selector){var s;De.aa("applying transform of variant "+n+" for experiment "+e+" ",r);var o=(s=document)==null?void 0:s.querySelectorAll(r.selector);o?.forEach((a=>{var l=a;r.html&&(l.innerHTML=r.html),r.css&&l.setAttribute("style",r.css)}))}})):De.aa("Control variants leave the page unmodified.")}_is_bot(){return Ve&&this._instance?yh(Ve,this.Ne.custom_blocked_useragents):void 0}}var vt=_e("[Conversations]"),$n="Conversations not available yet.",Ju="console",Ch="__posthogHandledLogsRequestError",oa=(t,e)=>{var n=t instanceof Error?t:new Error(e);return n[Ch]=!0,n},Zu=t=>!!t&&typeof t=="object"&&t[Ch]===!0,Zs={featureFlags:class{constructor(t){this.name="featureFlags",this.ca=!1,this.featureFlagEventHandlers=[],this.rt=zu,this.fa={},this.pa={},this.ga=[],this.ma=!1,this.ya=!1,this.ba=0,this._a=!1,this.wa=!1,this.ka=!1,this.xa=!1,this.Sa=0,this.Ca=()=>{var e=this.Ma();this.Sa=0,e&&this.reloadFeatureFlags()},"get"in t?this.Ta=t:(this.Ea=new Rv(t.config,t.Qi()),this.Ta=this.Ea)}updateConfig(t,e){var n;(n=this.Ea)==null||n.update(t,e)}setup(t){return this.Ia=t,this.rt=t.logger.createLogger("[FeatureFlags]"),n=()=>{this.Ia===t&&(this.Ia=void 0,this.nn=t,this.Pa(t))},(e=t.kv.initialize())!=null&&e.then?e.then(n):n();var e,n}Pa(t){if(this.nn===t)return w&&Se(w,"online",this.Ca),this.Ra=t.registerDynamicEventProperties((()=>this.Aa()?this.fa:this.pa)),this.Fa(),this.initialize()}destroy(){w?.removeEventListener("online",this.Ca)}dispose(){var t;this.ba++,this.wa=!1,this.Ia=void 0,this.nn&&(this.La(),(t=this.Ra)==null||t.dispose(),this.Ra=void 0,this.ga=[],w?.removeEventListener("online",this.Ca),this.nn=void 0)}get Ne(){return this.Ta.get()}Oa(t){var e;return(e=this.nn)==null?void 0:e.kv.get(t)}F(t){this.Da((()=>{var e;return(e=this.nn)==null?void 0:e.kv.set(t)}))}q(t){this.Da((()=>{var e;return(e=this.nn)==null?void 0:e.kv.remove(t)}))}Da(t){try{t()}catch(e){this.rt.error("Failed to update feature flag persistence",e)}}Fa(){var t={};for(var e of[zi,Vi,Yr,Mt]){var n=this.Oa(e);A(n)||(t[e]=n)}this.fa=t;var i=k({},t),r=this.Oa(Ln);if(r)for(var s of Object.entries(r))i["$feature/"+s[0]]=s[1];this.pa=i}Aa(){var t=this.Ne.cacheTtlMs;if(!t||0>=t)return!1;var e=this.Oa(Qi);return typeof e!="number"||Date.now()-e>t}$a(){return!!this.Aa()&&(this.xa||this.ya||(this.xa=!0,this.rt.warn("Feature flag cache is stale, triggering refresh..."),this.reloadFeatureFlags()),!0)}Na(){var t=this.Ne.evaluationContexts;return t!=null&&t.length?t.filter((e=>{var n=e&&typeof e=="string"&&e.trim().length>0;return n||this.rt.error("Invalid evaluation context found:",e,"Expected non-empty string"),n})):[]}qa(){var t=this.Ne.flagKeys;if(!A(t))return t.filter((e=>{var n=e&&typeof e=="string"&&e.trim().length>0;return n||this.rt.error("Invalid flag key found:",e,"Expected non-empty string"),n}))}initialize(){var t,e,n=this.Ne,i=(t=(e=n.bootstrap)==null?void 0:e.featureFlags)!==null&&t!==void 0?t:{};if(Object.keys(i).length){var r,s,o=(r=(s=n.bootstrap)==null?void 0:s.featureFlagPayloads)!==null&&r!==void 0?r:{},a=Object.keys(i).filter((u=>!!i[u])).reduce(((u,c)=>(u[c]=i[c]||!1,u)),{}),l=Object.keys(o).filter((u=>a[u])).reduce(((u,c)=>(o[c]&&(u[c]=o[c]),u)),{});return this.ja({featureFlags:a,featureFlagPayloads:l})}}updateFlags(t,e,n){var i,r,s=n!=null&&n.merge&&(i=this.Oa(Ln))!==null&&i!==void 0?i:{},o=n!=null&&n.merge&&(r=this.Oa(Vi))!==null&&r!==void 0?r:{},a=k({},s,t),l=k({},o,e),u={};for(var c of Object.entries(a)){var d=c[0],f=c[1];u[d]={key:d,enabled:Wc(f),variant:qc(f),reason:void 0,metadata:A(l?.[d])?void 0:{id:0,version:void 0,description:void 0,payload:l[d]}}}this.ja({flags:u})}get hasLoadedFlags(){return this.ma}getFlags(){return Object.keys(this.getFlagVariants())}getFlagsWithDetails(){var t=this.Oa(Pa),e=this.Oa(Mt),n=this.Oa(Nn);if(!n&&!e)return t||{};var i=ve({},t||{}),r=[...new Set([...Object.keys(n||{}),...Object.keys(e||{})])];for(var s of r){var o,a,l=i[s],u=e?.[s],c=A(u)?(o=l?.enabled)!==null&&o!==void 0&&o:!!u,d=A(u)?l?.variant:typeof u=="string"?u:void 0,f=n?.[s],p=k({},l,{enabled:c,variant:c?d??l?.variant:void 0});c!==l?.enabled&&(p.original_enabled=l?.enabled),d!==l?.variant&&(p.original_variant=l?.variant),f&&(p.metadata=k({},l?.metadata,{payload:f,original_payload:l==null||(a=l.metadata)==null?void 0:a.payload})),i[s]=p}return this.ca||(this.rt.warn(" Overriding feature flag details!",{flagDetails:t,overriddenPayloads:n,finalDetails:i}),this.ca=!0),i}getAllFeatureFlags(){var t=this.getFlagVariants(),e=this.getFlagPayloads();return Object.keys(t).map((n=>{var i=t[n];return{key:n,enabled:Wc(i),variant:qc(i),payload:Hc(e[n])}}))}getFlagVariants(){var t=this.Oa(Ln),e=this.Oa(Mt);if(!e)return t||{};for(var n=ve({},t||{}),i=Object.keys(e),r=0;i.length>r;r++)n[i[r]]=e[i[r]];return this.ca||(this.rt.warn(" Overriding feature flags!",{enabledFlags:t,overriddenFlags:e,finalFlags:n}),this.ca=!0),n}getFlagPayloads(){var t=this.Oa(Vi),e=this.Oa(Nn);if(!e)return t||{};for(var n=ve({},t||{}),i=Object.keys(e),r=0;i.length>r;r++)n[i[r]]=e[i[r]];return this.ca||(this.rt.warn(" Overriding feature flag payloads!",{flagPayloads:t,overriddenPayloads:e,finalPayloads:n}),this.ca=!0),n}reloadFeatureFlags(){this._a||this.Ne.featureFlagsDisabled||this.Ma()||this.Ba||(this.ga.slice().forEach((t=>{try{t()}catch(e){this.rt.error("Error while running feature flags reloading callback",e)}})),this.Ba=setTimeout((()=>{this.Ha()}),5))}La(){clearTimeout(this.Ba),this.Ba=void 0}onReloading(t){return this.ga.push(t),()=>{this.ga=this.ga.filter((e=>e!==t))}}ensureFlagsLoaded(){this.ma||this.ya||this.Ba||this.reloadFeatureFlags()}setAnonymousDistinctId(t){this.$anon_distinct_id=t}setReloadingPaused(t){this._a=t}resetFlagCallReported(){this.q(Dn)}Ha(t){this.La();var e=this.nn;if(e&&!this.Ne.remoteRequestsDisabled&&!this.Ma())if(this.ya)this.wa=!0;else{var n={token:e.projectToken,distinct_id:e.distinctId,groups:e.groups,$anon_distinct_id:this.$anon_distinct_id,person_properties:k({},e.initialPersonProperties,this.Oa(Jt)||{},{$lib:e.library.name,$lib_version:e.library.version}),group_properties:this.Oa(On),timezone:sh()};A(e.deviceId)||(n.$device_id=e.deviceId),(t!=null&&t.disableFlags||this.Ne.featureFlagsDisabled)&&(n.disable_flags=!0);var i=this.Na();i.length&&(n.evaluation_contexts=i);var r=this.qa();A(r)||(n.flag_keys=r);var s=this.Ne.onlyEvaluateSurveyFeatureFlags,o="/flags/?v=2"+(s?"&only_evaluate_survey_feature_flags=true":""),a=this.ba;this.ya=!0;var l=()=>{this.wa&&(this.wa=!1,this.Ha())},u=c=>{this.ya=!1,a===this.ba&&(this.F({[Xr]:[Vu]}),this.rt.error("Feature flag request failed",c)),l()};try{e.sendRequest(o,{target:"flags",method:"POST",body:n,compression:this.Ne.compression==="base64"?ze.Base64:void 0,sentAt:"body",timeoutMs:this.Ne.requestTimeoutMs}).then((c=>{var d,f,p=(d=c.json)!==null&&d!==void 0?d:{},h=c.statusCode!==200;if(this.ya=!1,a===this.ba){if(this.Ua(c.statusCode),h||this.wa||(this.$anon_distinct_id=void 0),!n.disable_flags||this.wa){this.ka=!h;var g=[];c.error?g.push(c.error instanceof Error&&c.error.name==="AbortError"?"timeout":c.error instanceof Error?Vu:"unknown_error"):c.statusCode!==200&&g.push("api_error_"+c.statusCode),p.errorsWhileComputingFlags&&g.push("errors_while_computing_flags");var m=!((f=p.quotaLimited)==null||!f.includes("feature_flags"));m&&g.push("quota_limited"),this.F({[Xr]:g}),m?this.rt.warn("You have hit your feature flags quota limit, and will not be able to load feature flags until the quota is reset. Please visit https://posthog.com/docs/billing/limits-alerts to learn more."):n.disable_flags||this.ja(p,h,{partialResponse:s}),l()}}else l()})).catch(u)}catch(c){u(c)}}}Ma(){return Zf(this.Sa,3)}Ua(t){this.Sa=Xf(t,this.Sa,3,(()=>this.rt.warn("Feature flag requests are failing before receiving an HTTP response; this can happen due to network issues, CORS, browser blocking, or ad blockers. Stopped refreshing feature flags; will try again when connectivity changes.")))}getFeatureFlag(t,e){var n;if(e===void 0&&(e={}),!e.fresh||this.ka)if(this.ma||this.getFlags()&&this.getFlags().length>0){if(!this.$a()){var i=this.getFeatureFlagResult(t,e);return(n=i?.variant)!==null&&n!==void 0?n:i?.enabled}}else this.rt.warn('getFeatureFlag for key "'+t+sa)}getFeatureFlagDetails(t){return this.getFlagsWithDetails()[t]}getFeatureFlagPayload(t){var e=this.getFeatureFlagResult(t,{send_event:!1});return e?.payload}getFeatureFlagResult(t,e){if(e===void 0&&(e={}),!e.fresh||this.ka)if(this.ma||this.getFlags()&&this.getFlags().length>0){if(!this.$a()){var n,i=this.getFlagVariants(),r=t in i,s=i[t],o=this.getFlagPayloads()[t],a=String(s),l=this.Oa(Yr)||void 0,u=this.Oa(Qi)||void 0,c=this.Oa(Dn)||{};if(this.Ne.deduplicateCallsPerSession){var d,f=(d=this.nn)==null?void 0:d.session.sessionId,p=this.Oa(Ki);f&&f!==p&&(c={},n=f)}if(e.send_event||!("send_event"in e))if(t in c&&c[t].includes(a))n&&this.F({[Dn]:c,[Ki]:n});else{var h,g,m,v,x,E,y,b,I,T;U(c[t])?c[t].push(a):c[t]=[a],this.F(k({[Dn]:c},n?{[Ki]:n}:{}));var S=this.getFeatureFlagDetails(t),C=[...(h=this.Oa(Xr))!==null&&h!==void 0?h:[]];A(s)&&C.push("flag_missing");var R={$feature_flag:t,$feature_flag_response:s,$feature_flag_payload:o||null,$feature_flag_request_id:l,$feature_flag_evaluated_at:u,$feature_flag_bootstrapped_response:((g=this.Ne.bootstrap)==null||(g=g.featureFlags)==null?void 0:g[t])||null,$feature_flag_bootstrapped_payload:((m=this.Ne.bootstrap)==null||(m=m.featureFlagPayloads)==null?void 0:m[t])||null,$used_bootstrap_value:!this.ka};A(S==null||(v=S.metadata)==null?void 0:v.has_experiment)||(R.$feature_flag_has_experiment=S.metadata.has_experiment),A(S==null||(x=S.metadata)==null?void 0:x.version)||(R.$feature_flag_version=S.metadata.version);var O,L=(E=S==null||(y=S.reason)==null?void 0:y.description)!==null&&E!==void 0?E:S==null||(b=S.reason)==null?void 0:b.code;L&&(R.$feature_flag_reason=L),S!=null&&(I=S.metadata)!=null&&I.id&&(R.$feature_flag_id=S.metadata.id),A(S?.original_variant)&&A(S?.original_enabled)||(R.$feature_flag_original_response=A(S.original_variant)?S.original_enabled:S.original_variant),S!=null&&(T=S.metadata)!=null&&T.original_payload&&(R.$feature_flag_original_payload=S==null||(O=S.metadata)==null?void 0:O.original_payload),C.length&&(R.$feature_flag_error=C.join(",")),this.za(R)}else n&&this.F({[Dn]:c,[Ki]:n});if(r)return{key:t,enabled:!!s,variant:typeof s=="string"?s:void 0,payload:Hc(o)}}}else this.rt.warn('getFeatureFlagResult for key "'+t+sa)}za(t){try{var e;(e=this.nn)==null||e.capture("$feature_flag_called",t).catch((n=>{this.rt.error("Failed to capture feature flag call",n)}))}catch(n){this.rt.error("Failed to capture feature flag call",n)}}getRemoteConfigPayload(t,e){this.Wa(t,e)}Wa(t,e){var n=this;return ce((function*(){var i=n.nn;if(i){var r={distinct_id:i.distinctId,token:i.projectToken,person_properties:{$lib:i.library.name,$lib_version:i.library.version}},s=n.Na();s.length&&(r.evaluation_contexts=s);var o,a=n.qa();A(a)||(r.flag_keys=a);try{var l,u=(l=(yield i.sendRequest("/flags/?v=2",{target:"flags",method:"POST",body:r,compression:n.Ne.compression==="base64"?ze.Base64:void 0,sentAt:"body",timeoutMs:n.Ne.requestTimeoutMs})).json)==null?void 0:l.featureFlagPayloads;o=u?.[t]||void 0}catch(c){return void n.rt.error("Remote config feature flag request failed",c)}try{e(o)}catch(c){n.rt.error("Remote config feature flag callback failed",c)}}}))()}isFeatureEnabled(t,e){if(e===void 0&&(e={}),e.fresh&&!this.ka)return e.defaultValue;if(!(this.ma||this.getFlags()&&this.getFlags().length>0))return this.rt.warn('isFeatureEnabled for key "'+t+sa),e.defaultValue;var n=this.getFeatureFlag(t,e);return A(n)?e.defaultValue:!!n}addFeatureFlagsHandler(t){this.featureFlagEventHandlers.push(t)}removeFeatureFlagsHandler(t){this.featureFlagEventHandlers=this.featureFlagEventHandlers.filter((e=>e!==t))}receivedFeatureFlags(t,e,n){this.ja(t,e,n)}ja(t,e,n){if(this.nn){this.ma=!0;var i=(function(r,s,o,a,l,u){s===void 0&&(s={}),o===void 0&&(o={}),a===void 0&&(a={}),u===void 0&&(u=zu);var c=((I,T)=>{var S=I.flags;return S?k({},I,{featureFlags:Object.fromEntries(Object.keys(S).map((C=>{var R;return[C,(R=S[C].variant)!==null&&R!==void 0?R:S[C].enabled]}))),featureFlagPayloads:Object.fromEntries(Object.keys(S).filter((C=>S[C].enabled)).filter((C=>{var R;return(R=S[C].metadata)==null?void 0:R.payload})).map((C=>{var R;return[C,(R=S[C].metadata)==null?void 0:R.payload]})))}):(I.featureFlags&&T.warn("Using an older version of the feature flags endpoint. Please upgrade your PostHog server to the latest version"),I)})(r,u),d=c.flags,f=c.featureFlags,p=c.featureFlagPayloads;if(f){var h=r.requestId,g=r.evaluatedAt;if(U(f)){u.warn("v1 of the feature flags endpoint is deprecated. Please use the latest version.");var m={};if(f)for(var v=0;f.length>v;v++)m[f[v]]=!0;return{[zi]:f,[Ln]:m,[ys]:!1}}var x=f,E=p,y=d;if(l!=null&&l.partialResponse)x=k({},s,x),E=k({},o,E),y=k({},a,y);else if(r.errorsWhileComputingFlags)if(d){var b=new Set(Object.keys(d).filter((I=>{var T;return!((T=d[I])!=null&&T.failed)})));x=k({},s,Object.fromEntries(Object.entries(x).filter((I=>b.has(I[0]))))),E=k({},o,Object.fromEntries(Object.entries(E||{}).filter((I=>b.has(I[0]))))),y=k({},a,Object.fromEntries(Object.entries(y||{}).filter((I=>b.has(I[0])))))}else x=k({},s,x),E=k({},o,E),y=k({},a,y);return k({[zi]:Object.keys(Ku(x)),[Ln]:x||{},[Vi]:E||{},[Pa]:y||{},[ys]:r.minimalFlagCalledEvents===!0},h?{[Yr]:h}:{},g?{[Qi]:g}:{})}})(t,this.getFlagVariants(),this.getFlagPayloads(),this.getFlagsWithDetails(),n,this.rt);i&&this.F(i),e||(this.xa=!1),this.Va(e)}}override(t,e){e===void 0&&(e=!1),this.rt.warn("override is deprecated. Please use overrideFeatureFlags instead."),this.overrideFeatureFlags({flags:t,suppressWarning:e})}overrideFeatureFlags(t){this.Za(t)}Za(t){if(this.nn){if(t===!1)return this.q([Mt,Nn]),this.Va(),void Mn.info("All overrides cleared");if(U(t))return this.F({[Mt]:Gu(t)}),this.Va(),void Mn.info("Flag overrides set",{flags:t});if(t&&typeof t=="object"&&("flags"in t||"payloads"in t)){var e,n=t;this.ca=!!((e=n.suppressWarning)!==null&&e!==void 0&&e);var i={},r=n.flags,s=n.payloads;return r&&(i[Mt]=U(r)?Gu(r):r),s&&(i[Nn]=s),Object.keys(i).length&&this.F(i),r===!1&&s===!1?this.q([Mt,Nn]):r===!1?this.q(Mt):s===!1&&this.q(Nn),this.Va(),r===!1?Mn.info("Flag overrides cleared"):r&&Mn.info("Flag overrides set",{flags:r}),void(s===!1?Mn.info("Payload overrides cleared"):s&&Mn.info("Payload overrides set",{payloads:s}))}if(t&&typeof t=="object")return this.F({[Mt]:t}),this.Va(),void Mn.info("Flag overrides set",{flags:t});this.rt.warn("Invalid overrideOptions provided to overrideFeatureFlags",{overrideOptions:t})}else this.rt.warn("posthog.featureFlags.overrideFeatureFlags called before feature flags were ready")}onFeatureFlags(t){if(this.addFeatureFlagsHandler(t),this.ma){var e=this.Ga(),n=e.flags,i=e.flagVariants;try{t(n,i)}catch(r){this.rt.error("Error while running feature flags callback",r)}}return()=>this.removeFeatureFlagsHandler(t)}updateEarlyAccessFeatureEnrollment(t,e,n){var i=(this.Oa(Kr)||[]).find((l=>l.flagKey===t)),r={["$feature_enrollment/"+t]:e},s={$feature_flag:t,$feature_enrollment:e,$set:r};i&&(s.$early_access_feature_name=i.name),n&&(s.$feature_enrollment_stage=n);var o=k({},this.getFlagVariants(),{[t]:e});this.F({[zi]:Object.keys(Ku(o)),[Ln]:o,[Jt]:k({},this.Oa(Jt)||{},r)}),this.Va();try{var a;(a=this.nn)==null||a.capture("$feature_enrollment_update",s).catch((l=>{this.rt.error("Failed to capture early access feature enrollment",l)}))}catch(l){this.rt.error("Failed to capture early access feature enrollment",l)}}getEarlyAccessFeatures(t,e,n){e===void 0&&(e=!1);var i=this.Oa(Kr);!i||e?this.Qa(t,n):t(i)}Qa(t,e){var n=this;return ce((function*(){var i=n.nn;if(i){var r,s=e?"&"+e.map((a=>"stage="+a)).join("&"):"";try{var o=yield i.sendRequest("/api/early_access_features/?token="+i.projectToken+s,{target:"api",method:"GET",sentAt:"query"});if(!o.json)return;n.F({[Kr]:r=o.json.earlyAccessFeatures})}catch(a){return void n.rt.error("Early access feature request failed",a)}try{t(r)}catch(a){n.rt.error("Early access feature callback failed",a)}}}))()}Ga(){var t=this.getFlags(),e=this.getFlagVariants();return{flags:t.filter((n=>e[n])),flagVariants:Object.keys(e).filter((n=>e[n])).reduce(((n,i)=>(n[i]=e[i],n)),{})}}Va(t){this.Fa();var e=this.Ga(),n=e.flags,i=e.flagVariants;this.featureFlagEventHandlers.forEach((r=>{try{r(n,i,{errorsLoading:t})}catch(s){this.rt.error("Error while running feature flags callback",s)}}))}setPersonPropertiesForFlags(t,e){e===void 0&&(e=!0),this.Ka(t,e)}Ka(t,e){e===void 0&&(e=!0);var n=this.Oa(Jt)||{},i=t?.$set||(t!=null&&t.$set_once?{}:t),r=t?.$set_once,s={};if(r)for(var o in r)({}).hasOwnProperty.call(r,o)&&(o in n||(s[o]=r[o]));this.F({[Jt]:k({},n,s,i)}),e&&this.reloadFeatureFlags()}unsetPersonPropertiesForFlags(t,e){e===void 0&&(e=!0);var n=k({},this.Oa(Jt)||{});t.forEach((i=>{delete n[i]})),this.F({[Jt]:n}),e&&this.reloadFeatureFlags()}resetPersonPropertiesForFlags(t){t===void 0&&(t=!0),this.q(Jt),t&&this.reloadFeatureFlags()}setGroupPropertiesForFlags(t,e){e===void 0&&(e=!0);var n=this.Oa(On)||{},i=k({},n);for(var r of Object.keys(t))i[r]=k({},n[r],t[r]);this.F({[On]:i}),e&&this.reloadFeatureFlags()}resetGroupPropertiesForFlags(t){if(t){var e=this.Oa(On)||{};this.F({[On]:k({},e,{[t]:{}})})}else this.q(On)}reset(){this.ba++,this.wa=!1,this.Fa(),this.ma=!1,this._a=!1,this.ka=!1,this.$anon_distinct_id=void 0,this.La(),this.ca=!1,this.Sa=0}}},Mv={sessionRecording:class{get Ne(){return this._instance.config}get Mr(){return this._instance.persistence}get started(){var t;return!((t=this.Ja)==null||!t.isStarted)}get status(){var t,e;return this.Ya===Di||this.Ya===Wr?this.Ya:(t=(e=this.Ja)==null?void 0:e.status)!==null&&t!==void 0?t:this.Ya}constructor(t){if(this._forceAllowLocalhostNetworkCapture=!1,this.Ya=Bu,this.Xa=void 0,this.eo=!1,this.io=(()=>{var e;if(F==null||!F.visibilityState||F.visibilityState==="visible")return!0;var n=w==null||(e=w.performance)==null||e.getEntriesByType==null?void 0:e.getEntriesByType("visibility-state");return!(n!=null&&n.length)||n.some((i=>i.name==="visible"))})(),this.Ie=()=>{var e;F?.visibilityState==="visible"&&(this.io=!0,(e=this.Ja)==null||e.setDocumentWasEverVisible==null||e.setDocumentWasEverVisible(!0))},this._instance=t,!this._instance.sessionManager)throw Kt.error("started without valid sessionManager"),new Error(Ga+" started without valid sessionManager. This is a bug.");if(this.Ne.cookieless_mode===tn)throw new Error(Ga+' cannot be used with cookieless_mode="always"');F!=null&&F.addEventListener&&Se(F,"visibilitychange",this.Ie)}initialize(){this.startIfEnabledOrStop()}dispose(){this.eo=!0,F==null||F.removeEventListener==null||F.removeEventListener("visibilitychange",this.Ie),this.stopRecording()}get ro(){var t,e=!((t=this._instance.get_property(jn))==null||!t.enabled),n=!this.Ne.disable_session_recording,i=this.Ne.disable_session_recording||this._instance.consent.isOptedOut();return w&&e&&n&&!i}startIfEnabledOrStop(t){var e;if(!(this.eo||this.ro&&(e=this.Ja)!=null&&e.isStarted)){var n=!A(Object.assign)&&!A(Array.from);this.ro&&n?(this.no(t),Kt.info("starting")):(this.Ya=Bu,this.stopRecording())}}no(t){var e,n,i;this.ro&&(this.Ya!==Di&&this.Ya!==Wr&&(this.Ya=Du),B!=null&&(e=B.__PosthogExtensions__)!=null&&(e=e.rrweb)!=null&&e.record&&(n=B.__PosthogExtensions__)!=null&&n.initSessionRecording?this.so(t):(i=B.__PosthogExtensions__)==null||i.loadExternalDependency==null||i.loadExternalDependency(this._instance,this.ao,(r=>{if(r)return Kt.error("could not load recorder",r);this.so(t)})))}stopRecording(){var t,e;(t=this.Xa)==null||t.call(this),this.Xa=void 0,(e=this.Ja)==null||e.stop()}oo(){var t,e;(t=this.Xa)==null||t.call(this),this.Xa=void 0,(e=this.Ja)==null||e.discard()}lo(){var t,e;(t=this.Mr)==null||t.unregister(Tl),(e=this.Mr)==null||e.unregister(Cf)}uo(t,e){if(q(t))return null;var n,i=Fe(t)?t:parseFloat(t);return typeof(n=i)!="number"||!Number.isFinite(n)||0>n||n>1?(Kt.warn(e+" must be between 0 and 1. Ignoring invalid value:",t),null):i}ho(t){if(this.Mr){var e,n,i=this.Mr,r=()=>{var s,o=t.sessionRecording===!1?void 0:t.sessionRecording,a=this.uo((s=this.Ne.session_recording)==null?void 0:s.sampleRate,"session_recording.sampleRate"),l=this.uo(o?.sampleRate,"remote config sampleRate"),u=a??l;q(u)&&this.lo();var c=o?.minimumDurationMilliseconds;i.register({[jn]:k({cache_timestamp:Date.now(),enabled:!!o},o,{networkPayloadCapture:k({capturePerformance:t.capturePerformance},o?.networkPayloadCapture),canvasRecording:{enabled:o?.recordCanvas,fps:o?.canvasFps,quality:o?.canvasQuality},sampleRate:u,minimumDurationMilliseconds:A(c)?null:c,endpoint:o?.endpoint,triggerMatchType:o?.triggerMatchType,masking:o?.masking,urlTriggers:o?.urlTriggers,version:o?.version,triggerGroups:o?.triggerGroups})})};r(),(e=this.Xa)==null||e.call(this),this.Xa=(n=this._instance.sessionManager)==null?void 0:n.onSessionId(r)}}onRemoteConfig(t){var e=t.ok?t.config:void 0;return e&&"sessionRecording"in e?e.sessionRecording===!1?(this.ho(e),void this.oo()):(this.ho(e),void this.startIfEnabledOrStop()):(this.Ya===Di&&(this.Ya=Wr,Kt.warn("config refresh failed, recording will not start until page reload")),void this.startIfEnabledOrStop())}log(t,e){var n;e===void 0&&(e="log"),(n=this.Ja)!=null&&n.log?this.Ja.log(t,e):Kt.warn("log called before recorder was ready")}get ao(){var t,e,n=(t=this._instance)==null||(t=t.persistence)==null?void 0:t.get_property(jn);return(n==null||(e=n.scriptConfig)==null?void 0:e.script)||"lazy-recorder"}do(){var t,e=this._instance.get_property(jn);if(!e)return!1;try{t=typeof e=="object"?e:JSON.parse(e)}catch(n){return Kt.warn("persisted remote config for session recording is invalid and will be ignored",n),!1}return!q(t.cache_timestamp)&&36e5>=Date.now()-t.cache_timestamp}so(t){var e,n,i;if(!this.eo){if((e=B.__PosthogExtensions__)==null||!e.initSessionRecording)return Kt.warn("Called on script loaded before session recording is available. This can be caused by adblockers."),void this._instance.register_for_session({[Lf]:!0});var r;if(this.Ja||(this.Ja=(r=B.__PosthogExtensions__)==null?void 0:r.initSessionRecording(this._instance,this.io),this.Ja._forceAllowLocalhostNetworkCapture=this._forceAllowLocalhostNetworkCapture),!this.do())return this.Ya===Wr||this.Ya===Di?void 0:(this.Ya=Di,Kt.info("persisted remote config is stale, requesting fresh config before starting"),void new oh(this._instance).load());this.Ya=Du,(n=(i=this.Ja).setDocumentWasEverVisible)==null||n.call(i,this.io),this.Ja.start(t)}}onRRwebEmit(t){var e;(e=this.Ja)==null||e.onRRwebEmit==null||e.onRRwebEmit(t)}overrideLinkedFlag(){var t,e;this.Ja||(e=this.Mr)==null||e.register({[Pf]:!0}),(t=this.Ja)==null||t.overrideLinkedFlag()}overrideSampling(){var t,e;this.Ja||(e=this.Mr)==null||e.register({[Af]:!0}),(t=this.Ja)==null||t.overrideSampling()}overrideTrigger(t){var e,n;this.Ja||(n=this.Mr)==null||n.register({[t==="url"?Ff:Rf]:!0}),(e=this.Ja)==null||e.overrideTrigger(t)}get sdkDebugProperties(){var t;return((t=this.Ja)==null?void 0:t.sdkDebugProperties)||{$recording_status:this.status}}tryAddCustomEvent(t,e){var n;return!((n=this.Ja)==null||!n.tryAddCustomEvent(t,e))}}},$v={autocapture:class{constructor(t){this.vo=!1,this.co=null,this.fo=!1,this.po=!1,this.instance=t,this.rageclicks=new Lu(t.config.rageclick),this.mo=null}initialize(){this.startIfEnabled()}get Ne(){var t,e,n=ye(this.instance.config.autocapture)?this.instance.config.autocapture:{};return n.url_allowlist=(t=n.url_allowlist)==null?void 0:t.map((i=>new RegExp(i))),n.url_ignorelist=(e=n.url_ignorelist)==null?void 0:e.map((i=>new RegExp(i))),n}yo(){if(this.isBrowserSupported()){if(w&&F){var t=n=>{n=n||w?.event;try{this.bo(n)}catch(i){ta.error("Failed to capture event",i)}};if(Se(F,"submit",t,{capture:!0}),Se(F,"change",t,{capture:!0}),Se(F,"click",t,{capture:!0}),this.Ne.capture_copied_text){var e=n=>{n=n||w?.event;try{this.bo(n,ea)}catch(i){ta.error("Failed to capture copy/cut event",i)}};Se(F,"copy",e,{capture:!0}),Se(F,"cut",e,{capture:!0})}}}else ta.info("Disabling Automatic Event Collection because this browser is not supported")}startIfEnabled(){this.isEnabled&&!this.vo&&(this.yo(),this.vo=!0)}onRemoteConfig(t){if(this.fo=!0,t.ok){var e=t.config;e.elementsChainAsString&&(this.po=e.elementsChainAsString);var n=e.autocapture_opt_out;kt(n)&&(this.instance.persistence&&this.instance.persistence.register({[Ea]:n}),this.co=n),this.startIfEnabled()}else this.startIfEnabled()}setElementSelectors(t){this.mo=t}getElementSelectors(t){var e,n=[];return(e=this.mo)==null||e.forEach((i=>{var r=F?.querySelectorAll(i);r?.forEach((s=>{t===s&&n.push(i)}))})),n}get isEnabled(){var t,e,n=(t=this.instance.persistence)==null?void 0:t.props[Ea],i=this.co,r=this.instance.Qi()&&!this.fo;if(it(i)&&!kt(n)&&!r)return!1;var s=(e=this.co)!==null&&e!==void 0?e:!!n;return!!this.instance.config.autocapture&&!s}bo(t,e){if(e===void 0&&(e="$autocapture"),this.isEnabled){var n,i=Ho(t);jf(i)&&(i=i.parentNode||null),e==="$autocapture"&&t.type==="click"&&t instanceof MouseEvent&&this.instance.config.rageclick&&(n=this.rageclicks)!=null&&n.isRageClick(t.clientX,t.clientY,t.timeStamp||new Date().getTime())&&du(i,this.instance.config.rageclick)&&this.bo(t,"$rageclick");var r=e===ea;if(i&&(function(d,f,p,h,g,m){var v;if(!w||Ol(d)||p!=null&&p.url_allowlist&&!lu(p.url_allowlist,m)||p!=null&&p.url_ignorelist&&lu(p.url_ignorelist,m))return!1;if(p!=null&&p.dom_event_allowlist){var x=p.dom_event_allowlist;if(x&&!x.some((S=>f.type===S)))return!1}var E=Vf(d,h),y=E.parentIsUsefulElement,b=E.targetElementList;if(!(function(S,C){var R=C?.element_allowlist;if(A(R))return!0;var O,L=function(J){if(R.some((G=>J.tagName.toLowerCase()===G)))return{v:!0}};for(var N of S)if(O=L(N))return O.v;return!1})(b,p)||!Ba(b,p?.css_selector_allowlist)||Ba(b,(v=p?.css_selector_ignorelist)!==null&&v!==void 0?v:Rm))return!1;try{var I=w.getComputedStyle(d);if(I&&I.getPropertyValue("cursor")==="pointer"&&f.type==="click")return!0}catch{}var T=d.tagName.toLowerCase();switch(T){case"html":return!1;case"form":return(g||["submit"]).indexOf(f.type)>=0;case"input":case"select":case"textarea":return(g||["change","click"]).indexOf(f.type)>=0;default:return y?(g||["click"]).indexOf(f.type)>=0:(g||["click"]).indexOf(f.type)>=0&&(Nl.indexOf(T)>-1||d.getAttribute("contenteditable")==="true")}})(i,t,this.Ne,r,r?["copy","cut"]:void 0,this.instance)){var s=Sv(i,{e:t,maskAllElementAttributes:this.instance.config.mask_all_element_attributes,maskAllText:this.instance.config.mask_all_text,elementAttributeIgnoreList:this.Ne.element_attribute_ignorelist,elementsChainAsString:this.po,disableCaptureUrlHashes:this.instance.config.disable_capture_url_hashes}),o=s.props;if(s.explicitNoCapture)return!1;var a=this.getElementSelectors(i);if(a&&a.length>0&&(o.$element_selectors=a),e===ea){var l,u=Wf(w==null||(l=w.getSelection())==null?void 0:l.toString()),c=t.type||"clipboard";if(!u)return!1;o.$selected_content=u,o.$copy_type=c}return this.instance.capture(e,o),!0}}}isBrowserSupported(){return qe(F?.querySelectorAll)}},historyAutocapture:class{constructor(t){var e;this._instance=t,this._o=(w==null||(e=w.location)==null?void 0:e.pathname)||""}initialize(){this.startIfEnabled()}get isEnabled(){return this._instance.config.capture_pageview==="history_change"}startIfEnabled(){this.isEnabled&&(P.info("History API monitoring enabled, starting..."),this.monitorHistoryChanges())}stop(){this.wo&&this.wo(),this.wo=void 0,P.info("History API monitoring stopped")}monitorHistoryChanges(){w&&w.history&&(this.ko("pushState"),this.ko("replaceState"),this.xo())}ko(t){var e;if(w&&((e=w.history[t])==null||!e.__posthog_wrapped__)){var n=this;(function(i,r,s){try{if(!(r in i))return Nu;var o={next:i[r]},a=s((function(){for(var l=arguments.length,u=new Array(l),c=0;l>c;c++)u[c]=arguments[c];return o.next.apply(this,u)}));return qe(a)&&(a.prototype=a.prototype||{},Object.defineProperties(a,{__posthog_wrapped__:{enumerable:!1,value:!0},__posthog_layer__:{enumerable:!1,value:o}})),i[r]=a,()=>{if(i[r]!==a)for(var l=i[r];qe(l)&&l.__posthog_layer__;){var u=l.__posthog_layer__;if(u.next===a)return void(u.next=o.next);l=u.next}else i[r]=o.next}}catch{return Nu}})(w.history,t,(i=>function(r,s,o){i.call(this,r,s,o),n.So(t)}))}}So(t){try{var e,n=w==null||(e=w.location)==null?void 0:e.pathname;if(!n)return;n!==this._o&&this.isEnabled&&this._instance.capture(ii,{navigation_type:t}),this._o=n}catch(i){P.error("Error capturing "+t+" pageview",i)}}xo(){if(!this.wo){var t=()=>{this.So("popstate")};Se(w,"popstate",t),this.wo=()=>{w&&w.removeEventListener("popstate",t)}}}},heatmaps:class{get Ne(){return this.instance.config}constructor(t){var e;this.Co=!1,this.vo=!1,this.Mo=null,this.instance=t,this.Co=!((e=this.instance.persistence)==null||!e.props[Sa]),this.rageclicks=new Lu(t.config.rageclick)}initialize(){this.startIfEnabled()}get flushIntervalMilliseconds(){var t=5e3;return ye(this.Ne.capture_heatmaps)&&this.Ne.capture_heatmaps.flush_interval_milliseconds&&(t=this.Ne.capture_heatmaps.flush_interval_milliseconds),t}get isEnabled(){return q(this.Ne.capture_heatmaps)?q(this.Ne.enable_heatmaps)?this.Co:this.Ne.enable_heatmaps:this.Ne.capture_heatmaps!==!1}startIfEnabled(){if(this.isEnabled){if(this.vo)return;Iv.info("starting..."),this.To(),this.Ie()}else{var t;clearInterval((t=this.Mo)!==null&&t!==void 0?t:void 0),this.Eo(),this.getAndClearBuffer()}}onRemoteConfig(t){if(t.ok){var e=t.config;if("heatmaps"in e){var n=!!e.heatmaps;this.instance.persistence&&this.instance.persistence.register({[Sa]:n}),this.Co=n,this.startIfEnabled()}}}getAndClearBuffer(){var t=this.R;return this.R=void 0,t}Io(t){ia(t.originalEvent)&&this.ke(t.originalEvent,"deadclick")}Ie(){this.Mo&&clearInterval(this.Mo),this.Mo=F?.visibilityState==="visible"?setInterval(this.cr.bind(this),this.flushIntervalMilliseconds):null}To(){w&&F&&(this.Po=this.cr.bind(this),Se(w,Ss,this.Po),this.Ro=t=>this.ke(t||w?.event),Se(F,"click",this.Ro,{capture:!0}),this.Ao=t=>this.Fo(t||w?.event),Se(F,"mousemove",this.Ao,{capture:!0}),this.Lo=new yu(this.instance,Bm,this.Io.bind(this)),this.Lo.startIfEnabledOrStop(),this.Oo=this.Ie.bind(this),Se(F,Es,this.Oo),this.vo=!0)}Eo(){var t;w&&F&&(this.Po&&w.removeEventListener(Ss,this.Po),this.Ro&&F.removeEventListener("click",this.Ro,{capture:!0}),this.Ao&&F.removeEventListener("mousemove",this.Ao,{capture:!0}),this.Oo&&F.removeEventListener(Es,this.Oo),clearTimeout(this.Do),(t=this.Lo)==null||t.stop(),this.vo=!1)}$o(t,e){var n=this.instance.scrollManager.scrollY(),i=this.instance.scrollManager.scrollX(),r=this.instance.scrollManager.scrollElement(),s=(function(o,a,l){for(var u=o;u&&xn(u)&&!lt(u,"body");){if(u===l)return!1;var c=void 0;try{var d,f,p;c=(d=(f=(p=u.ownerDocument)==null?void 0:p.defaultView)!==null&&f!==void 0?f:w)==null?void 0:d.getComputedStyle(u).position}catch{return!1}if(j(a,c))return!0;u=qf(u)}return!1})(Ho(t),["fixed","sticky"],r);return{x:t.clientX+(s?0:i),y:t.clientY+(s?0:n),target_fixed:s,type:e}}ke(t,e){var n;if(e===void 0&&(e="click"),!au(t.target)&&ia(t)){var i=this.$o(t,e);(n=this.rageclicks)!=null&&n.isRageClick(t.clientX,t.clientY,new Date().getTime())&&du(Ho(t),this.instance.config.rageclick)&&this.Vt(k({},i,{type:"rageclick"})),this.Vt(i)}}Fo(t){!au(t.target)&&ia(t)&&(clearTimeout(this.Do),this.Do=setTimeout((()=>{this.Vt(this.$o(t,"mousemove"))}),500))}Vt(t){if(w){var e=this.Ne.disable_capture_url_hashes?Sn(w.location.href):w.location.href,n=this.Ne.custom_personal_data_properties,i=this.Ne.mask_personal_data_properties?[...vi,...n||[]]:[],r=ur(e,i,dr);this.R=this.R||{},this.R[r]||(this.R[r]=[]),this.R[r].push(t)}}cr(){this.R&&!an(this.R)&&this.instance.capture("$$heatmap",{$heatmap_data:this.getAndClearBuffer()})}},deadClicksAutocapture:yu,webVitalsAutocapture:class{constructor(t){var e;this.Co=!1,this.vo=!1,this.R={navigationKey:void 0,url:void 0,metrics:[],firstMetricTimestamp:void 0},this.No=()=>{clearTimeout(this.qo),this.qo=void 0,this.R.metrics.length!==0&&(this._instance.capture("$web_vitals",k({$current_url:this.R.url},this.R.metrics.reduce(((n,i)=>k({},n,{["$web_vitals_"+i.name+"_event"]:k({},i),["$web_vitals_"+i.name+"_value"]:i.value})),{}))),this.R={navigationKey:void 0,url:void 0,metrics:[],firstMetricTimestamp:void 0})},this.jo=n=>{var i;if(this.R=this.R||{navigationKey:void 0,url:void 0,metrics:[],firstMetricTimestamp:void 0},q(n?.name)||q(n?.value))Tn.error("Invalid metric received",n);else{var r=typeof n.navigationURL=="string"?n.navigationURL:void 0,s=this.Bo(r);if(!A(s)){var o=Fe(n.navigationId)||typeof n.navigationId=="string"?"navigation:"+n.navigationId:"url:"+s;if(!this.Ho||this.Ho>n.value){this.R.navigationKey!==o&&(this.No(),this.qo=setTimeout(this.No,this.flushToCaptureTimeoutMs)),A(this.R.navigationKey)&&(this.R.navigationKey=o,this.R.url=s),this.R.firstMetricTimestamp=A(this.R.firstMetricTimestamp)?Date.now():this.R.firstMetricTimestamp,n.attribution&&n.attribution.interactionTargetElement&&(n.attribution.interactionTargetElement=void 0);var a=(i=this._instance.sessionManager)==null?void 0:i.checkAndGetSessionAndWindowId(!0),l=k({},n,r?{navigationURL:s}:{},{$current_url:s,timestamp:Date.now()});A(a)||(l.$session_id=a.sessionId,l.$window_id=a.windowId),this.R.metrics.push(l),this.R.metrics.length===this.allowedMetrics.length&&this.No()}else Tn.error("Ignoring metric with value >= "+this.Ho,n)}}},this.Uo=()=>{if(!this.vo){var n,i,r,s,o=B.__PosthogExtensions__,a=o?.postHogWebVitalsCallbacksByFlavor,l=a?.[this.zo]||(this.zo==="web-vitals"&&A(a)?o?.postHogWebVitalsCallbacks:void 0);if(A(l)||(n=l.onLCP,i=l.onCLS,r=l.onFCP,s=l.onINP),n&&i&&r&&s){var u={reportSoftNavs:this.useSoftNavs};this.allowedMetrics.indexOf("LCP")>-1&&n(this.jo.bind(this),u),this.allowedMetrics.indexOf("CLS")>-1&&i(this.jo.bind(this),u),this.allowedMetrics.indexOf("FCP")>-1&&r(this.jo.bind(this),u),this.allowedMetrics.indexOf("INP")>-1&&s(this.jo.bind(this),u),this.vo=!0}else Tn.error("web vitals callbacks not loaded - not starting")}},this._instance=t,this.Co=!((e=this._instance.persistence)==null||!e.props[Ca]),this.startIfEnabled()}get Wo(){return this._instance.config.capture_performance}get allowedMetrics(){var t,e,n=ye(this.Wo)?(t=this.Wo)==null?void 0:t.web_vitals_allowed_metrics:void 0;return q(n)?((e=this._instance.persistence)==null?void 0:e.props[Aa])||["CLS","FCP","INP","LCP"]:n}get flushToCaptureTimeoutMs(){return(ye(this.Wo)?this.Wo.web_vitals_delayed_flush_ms:void 0)||5e3}get useAttribution(){var t=ye(this.Wo)?this.Wo.web_vitals_attribution:void 0;return t!=null&&t}get useSoftNavs(){var t=ye(this.Wo)?this.Wo.__preview_web_vitals_soft_navs:void 0;return t!=null&&t}get Ho(){var t=ye(this.Wo)&&Fe(this.Wo.__web_vitals_max_value)?this.Wo.__web_vitals_max_value:Ou;return t>0&&6e4>=t?Ou:t}get isEnabled(){var t=Ee?.protocol;if(t!=="http:"&&t!=="https:")return Tn.info("Web Vitals are disabled on non-http/https protocols"),!1;var e=ye(this.Wo)?this.Wo.web_vitals:kt(this.Wo)?this.Wo:void 0;return kt(e)?e:this.Co}startIfEnabled(){this.isEnabled&&!this.vo&&(Tn.info("enabled, starting..."),this.ai(this.Uo))}onRemoteConfig(t){if(t.ok){var e=t.config;if("capturePerformance"in e){var n=ye(e.capturePerformance)&&!!e.capturePerformance.web_vitals,i=ye(e.capturePerformance)?e.capturePerformance.web_vitals_allowed_metrics:void 0;this._instance.persistence&&(this._instance.persistence.register({[Ca]:n}),this._instance.persistence.register({[Aa]:i})),this.Co=n,this.startIfEnabled()}}}get zo(){return this.useSoftNavs?this.useAttribution?"web-vitals-with-attribution-soft-navs":"web-vitals-soft-navs":this.useAttribution?"web-vitals-with-attribution":"web-vitals"}ai(t){var e=B.__PosthogExtensions__,n=this.zo,i=e?.postHogWebVitalsCallbacksByFlavor;i!=null&&i[n]||n==="web-vitals"&&A(i)&&e!=null&&e.postHogWebVitalsCallbacks?t():e==null||e.loadExternalDependency==null||e.loadExternalDependency(this._instance,n,(r=>{r?Tn.error("failed to load script",r):t()}))}Bo(t){var e=t||w?.location.href;if(e){var n=this._instance.config.disable_capture_url_hashes?Sn(e):e,i=this._instance.config.custom_personal_data_properties,r=this._instance.config.mask_personal_data_properties?[...vi,...i||[]]:[];return ur(n,r,dr)}Tn.error("Could not determine current URL")}}},Lv={exceptionObserver:class{constructor(t){var e;this.Uo=()=>{var n;if(w&&this.isEnabled&&(n=B.__PosthogExtensions__)!=null&&n.errorWrappingFunctions){var i=B.__PosthogExtensions__.errorWrappingFunctions.wrapOnError,r=B.__PosthogExtensions__.errorWrappingFunctions.wrapUnhandledRejection,s=B.__PosthogExtensions__.errorWrappingFunctions.wrapConsoleError;try{!this.Vo&&this.Ne.capture_unhandled_errors&&(this.Vo=i(this.captureException.bind(this))),!this.Zo&&this.Ne.capture_unhandled_rejections&&(this.Zo=r(this.captureException.bind(this))),!this.Go&&this.Ne.capture_console_errors&&(this.Go=s(this.captureException.bind(this)))}catch(o){Bi.error("failed to start",o),this.Qo()}}},this._instance=t,this.Ko=!((e=this._instance.persistence)==null||!e.props[xa]),this.Jo=new Mg(k({},(function(n){var i,r,s,o;return n===void 0&&(n={}),{refillRate:(i=(r=n.exceptionRateLimiterRefillRate)!==null&&r!==void 0?r:n.__exceptionRateLimiterRefillRate)!==null&&i!==void 0?i:1,bucketSize:(s=(o=n.exceptionRateLimiterBucketSize)!==null&&o!==void 0?o:n.__exceptionRateLimiterBucketSize)!==null&&s!==void 0?s:10}})(this._instance.config.error_tracking),{refillInterval:1e4,rt:Bi})),this.Ne=this.Yo(),this.startIfEnabledOrStop()}Yo(){var t=this._instance.config.capture_exceptions,e={capture_unhandled_errors:!1,capture_unhandled_rejections:!1,capture_console_errors:!1};return ye(t)?e=k({},e,t):(A(t)?this.Ko:t)&&(e=k({},e,{capture_unhandled_errors:!0,capture_unhandled_rejections:!0})),e}get isEnabled(){return this.Ne.capture_console_errors||this.Ne.capture_unhandled_errors||this.Ne.capture_unhandled_rejections}startIfEnabledOrStop(){this.isEnabled?(Bi.info("enabled"),this.Qo(),this.ai(this.Uo)):this.Qo()}ai(t){var e,n;(e=B.__PosthogExtensions__)!=null&&e.errorWrappingFunctions?t():(n=B.__PosthogExtensions__)==null||n.loadExternalDependency==null||n.loadExternalDependency(this._instance,"exception-autocapture",(i=>{if(i)return Bi.error("failed to load script",i);t()}))}Qo(){var t,e,n;(t=this.Vo)==null||t.call(this),this.Vo=void 0,(e=this.Zo)==null||e.call(this),this.Zo=void 0,(n=this.Go)==null||n.call(this),this.Go=void 0}onRemoteConfig(t){if(t.ok){var e=t.config;"autocaptureExceptions"in e&&(this.Ko=!!e.autocaptureExceptions||!1,this._instance.persistence&&this._instance.persistence.register({[xa]:this.Ko}),this.Ne=this.Yo(),this.startIfEnabledOrStop())}}onConfigChange(){this.Ne=this.Yo()}captureException(t){var e,n,i,r=(e=t==null||(n=t.$exception_list)==null||(n=n[0])==null?void 0:n.type)!==null&&e!==void 0?e:"Exception";this.Jo.consumeRateLimit(r)?Bi.info("Skipping exception capture because of client rate limiting.",{exception:r}):(i=this._instance.exceptions)==null||i.sendExceptionEvent(t)}},exceptions:class{constructor(t){var e,n;this.Xo=[],this.tl=new Jg([new rm,new hm,new om,new sm,new dm,new um,new lm,new fm],(function(i){for(var r=arguments.length,s=new Array(r>1?r-1:0),o=1;r>o;o++)s[o-1]=arguments[o];return function(a,l){l===void 0&&(l=0);for(var u=[],c=a.split(` +`),d=l;c.length>d;d++){var f=c[d];if(1024>=f.length){var p=iu.test(f)?f.replace(iu,"$1"):f;if(!p.match(/\S*Error: /)){for(var h of s){var g=h(p,i);if(g){u.push(g);break}}if(u.length>=50)break}}}return(function(m){if(!m.length)return[];var v=Array.from(m);return v.reverse(),v.slice(0,50).map((x=>{return k({},x,{filename:x.filename||(E=v,E[E.length-1]||{}).filename,function:x.function||gi});var E}))})(u)}})("web:javascript",em,im)),this._instance=t,this.Xo=(e=(n=this._instance.persistence)==null?void 0:n.get_property(Ia))!==null&&e!==void 0?e:[],this.el=vs(this.il()),this.rl=new gm(this.el)}onConfigChange(){this.el=vs(this.il()),this.rl.setConfig(this.el)}onRemoteConfig(t){var e,n,i;if(t.ok){var r=t.config;if("errorTracking"in r){var s=(e=(n=r.errorTracking)==null?void 0:n.suppressionRules)!==null&&e!==void 0?e:[],o=(i=r.errorTracking)==null?void 0:i.captureExtensionExceptions;this.Xo=s,this._instance.persistence&&this._instance.persistence.register({[Ia]:this.Xo,[ka]:o})}}}get nl(){var t,e=!!this._instance.get_property(ka),n=this._instance.config.error_tracking.captureExtensionExceptions;return(t=n??e)!==null&&t!==void 0&&t}buildProperties(t,e){return this.tl.buildFromUnknown(t,{syntheticException:e?.syntheticException,mechanism:{handled:e?.handled}})}addExceptionStep(t,e){if(this.el.enabled)try{if(!X(t)||t.trim().length===0)return void Rt.warn("Ignoring exception step because message must be a non-empty string");var n=(function(s){if(!s)return{sanitizedProperties:{},droppedKeys:[]};var o=[];return{sanitizedProperties:Object.keys(s).reduce(((a,l)=>pm.has(l)?(o.push(l),a):(a[l]=s[l],a)),{}),droppedKeys:o}})(this.sl(e)),i=n.sanitizedProperties,r=n.droppedKeys;r.length>0&&Rt.warn("Ignoring reserved exception step fields",{droppedKeys:r}),this.rl.add(k({[gs]:t,[ms]:new Date().toISOString()},i))}catch(s){Rt.error("Failed to add exception step. Ignoring breadcrumb.",s)}}sendExceptionEvent(t){try{var e=t.$exception_list;if(this.al(e)){if(this.ol(e))return this.ll("Exception dropped: matched a suppression rule"),void Rt.info("Skipping exception capture because a suppression rule matched");if(!this.nl&&this.ul(e))return this.ll("Exception dropped: thrown by a browser extension"),void Rt.info("Skipping exception capture because it was thrown by an extension");if(!this._instance.config.error_tracking.__capturePostHogExceptions&&this.hl(e))return this.ll("Exception dropped: thrown by the PostHog SDK"),void Rt.info("Skipping exception capture because it was thrown by the PostHog SDK")}var n=this.el.enabled&&q(t.$exception_steps)?this.dl(t):t,i=typeof(s=globalThis._posthogReleaseId)=="string"&&s.length>0?s:void 0;i&&(n.$release_id=i);try{var r=this._instance.capture("$exception",n,{_noTruncate:!0,_batchKey:"exceptionEvent",Wn:!0});return r&&this.rl.clear(),r}catch(o){return Rt.error("Failed to capture exception event. Dropping this exception.",o),void this.rl.clear()}}catch(o){return void Rt.error("Failed to process exception event. Ignoring this exception.",o)}var s}dl(t){try{var e=this.rl.getAttachable();return e.length===0?t:k({},t,{$exception_steps:e})}catch(n){return Rt.error("Failed to read buffered exception steps. Capturing exception without steps.",n),t}}ll(t){this.el.enabled&&this.rl.add({[gs]:t,[ms]:new Date().toISOString()})}sl(t){return ye(t)?k({},t):{}}il(){var t,e;return(t=(e=this._instance.config.error_tracking)==null?void 0:e.exception_steps)!==null&&t!==void 0?t:{}}ol(t){if(t.length===0)return!1;try{var e=t.reduce(((n,i)=>{var r=i.type,s=i.value;return X(r)&&r.length>0&&n.$exception_types.push(r),X(s)&&s.length>0&&n.$exception_values.push(s),n}),{$exception_types:[],$exception_values:[]});return this.Xo.some((n=>{var i=n.values.map((r=>{var s=wh[r.operator],o=e[r.key];if(!s||!o)return!1;var a=U(r.value)?r.value:[r.value];return a.length>0&&s(a,o)}));return n.type==="OR"?i.some(Boolean):i.every(Boolean)}))}catch(n){return Rt.warn("Failed to evaluate suppression rules. Capturing the exception.",n),!1}}ul(t){return t.flatMap((e=>{var n,i;return(n=(i=e.stacktrace)==null?void 0:i.frames)!==null&&n!==void 0?n:[]})).some((e=>e.filename&&e.filename.startsWith("chrome-extension://")))}hl(t){if(t.length>0){var e,n,i,r,s=(e=(n=t[0].stacktrace)==null?void 0:n.frames)!==null&&e!==void 0?e:[],o=s[s.length-1];return(i=o==null||(r=o.filename)==null?void 0:r.includes("posthog.com/static"))!==null&&i!==void 0&&i}return!1}al(t){return!q(t)&&U(t)}}},Nv=k({productTours:class{get Mr(){return this._instance.persistence}constructor(t){this.vl=null,this.cl=null,this._instance=t}initialize(){this.loadIfEnabled()}onRemoteConfig(t){if(t.ok){var e=t.config;if("productTours"in e){var n,i;if(this.Mr&&this.Mr.register({[Rl]:!!e.productTours}),!ra(this._instance))return!this.vl&&q((n=this.Mr)==null?void 0:n.props[Gi])||qr.info("product tours disabled; stopping and clearing cached tours"),(i=this.vl)==null||i.stop(),this.vl=null,void this.clearCache();this.loadIfEnabled()}}}loadIfEnabled(){!this.vl&&ra(this._instance)&&this.ai((()=>this.fl()))}ai(t){var e,n;(e=B.__PosthogExtensions__)!=null&&e.generateProductTours?t():(n=B.__PosthogExtensions__)==null||n.loadExternalDependency==null||n.loadExternalDependency(this._instance,"product-tours",(i=>{i?qr.error("Could not load product tours script",i):t()}))}fl(){var t;!this.vl&&(t=B.__PosthogExtensions__)!=null&&t.generateProductTours&&(this.vl=B.__PosthogExtensions__.generateProductTours(this._instance,!0))}getProductTours(t,e){if(e===void 0&&(e=!1),!U(this.cl)||e){var n=this.Mr;if(n){var i=n.props[Gi];if(U(i)&&!e)return this.cl=i,void t(i,{isLoaded:!0})}this._instance._send_request({url:this._instance.requestRouter.endpointFor("api","/api/product_tours/?token="+this._instance.config.token),method:"GET",timestampMode:"query",callback:r=>{if(ra(this._instance)){var s=r.statusCode;if(s!==200||!r.json){var o="Product Tours API could not be loaded, status: "+s;return s===0?r.error||qr.warn(o):qr.error(o),void t([],{isLoaded:!1,error:o})}var a=U(r.json.product_tours)?r.json.product_tours:[];this.cl=a,n&&n.register({[Gi]:a}),t(a,{isLoaded:!0})}else t([],{isLoaded:!0})}})}else t(this.cl,{isLoaded:!0})}getActiveProductTours(t){q(this.vl)?t([],{isLoaded:!1,error:"Product tours not loaded"}):this.vl.getActiveProductTours(t)}showProductTour(t){var e;(e=this.vl)==null||e.showTourById(t)}previewTour(t){this.vl?this.vl.previewTour(t):this.ai((()=>{var e;this.fl(),(e=this.vl)==null||e.previewTour(t)}))}dismissProductTour(){var t;(t=this.vl)==null||t.dismissTour("user_clicked_skip")}nextStep(){var t;(t=this.vl)==null||t.nextStep()}previousStep(){var t;(t=this.vl)==null||t.previousStep()}clearCache(){var t;this.cl=null,(t=this.Mr)==null||t.unregister(Gi)}resetTour(t){var e;(e=this.vl)==null||e.resetTour(t)}resetAllTours(){var t;(t=this.vl)==null||t.resetAllTours()}cancelPendingTour(t){var e;(e=this.vl)==null||e.cancelPendingTour(t)}}},Zs),Ov={siteApps:class{constructor(t){this.pl=0,this._instance=t,this.gl=[],this.apps={}}get isEnabled(){return!!this._instance.config.opt_in_site_apps}ml(t,e){if(e){var n=this.globalsForEvent(e);this.gl.push(n),this.gl.length>1e3&&(this.gl=this.gl.slice(10))}}get siteAppLoaders(){var t;return(t=B._POSTHOG_REMOTE_CONFIG)==null||(t=t[this._instance.config.token])==null?void 0:t.siteApps}initialize(){if(this.isEnabled){var t=this._instance._addCaptureHook(this.ml.bind(this));this.yl=()=>{t(),this.gl=[],this.yl=void 0}}}globalsForEvent(t){var e,n,i,r,s,o,a;if(!t)throw new Error("Event payload is required");var l={},u=this._instance.get_property("$groups")||[],c=this._instance.get_property("$stored_group_properties")||{};for(var d of Object.entries(c)){var f=d[0];l[f]={id:u[f],type:f,properties:d[1]}}var p=t.$set_once,h=t.$set;return{event:k({},qd(t,kv),{properties:k({},t.properties,h?{$set:k({},(e=(n=t.properties)==null?void 0:n.$set)!==null&&e!==void 0?e:{},h)}:{},p?{$set_once:k({},(i=(r=t.properties)==null?void 0:r.$set_once)!==null&&i!==void 0?i:{},p)}:{}),elements_chain:(s=(o=t.properties)==null?void 0:o.$elements_chain)!==null&&s!==void 0?s:"",distinct_id:(a=t.properties)==null?void 0:a.distinct_id}),person:{properties:this._instance.get_property("$stored_person_properties")},groups:l}}bl(t){var e,n=(e=t.tagName)==null?void 0:e.toLowerCase();return n==="style"&&this._instance.config.prepare_external_dependency_stylesheet?this._instance.config.prepare_external_dependency_stylesheet(t)||(Ft.error("prepare_external_dependency_stylesheet returned null"),null):n==="script"&&this._instance.config.prepare_external_dependency_script?this._instance.config.prepare_external_dependency_script(t)||(Ft.error("prepare_external_dependency_script returned null"),null):t}_l(){var t,e,n,i,r,s,o,a;if(!this._instance.config.prepare_external_dependency_stylesheet&&!this._instance.config.prepare_external_dependency_script)return()=>{};var l=F?.defaultView,u=l==null||(t=l.Node)==null?void 0:t.prototype;if(!l||!u)return()=>{};if(this.pl++,this.wl)return this.kl();var c=[],d=this,f=new WeakSet,p=(m,v,x)=>{if(m!=null&&m[v]){var E=m[v];m[v]=x(E),c.push((()=>{m[v]=E}))}},h=m=>{if(f.has(m))return m;var v=d.bl(m);return v&&f.add(v),v},g=m=>m.map((v=>typeof v=="string"?v:h(v))).filter((v=>!it(v)));return p(u,"appendChild",(m=>function(v){var x=h(v);return x?m.call(this,x):v})),p(u,"insertBefore",(m=>function(v,x){var E=h(v);return E?m.call(this,E,x):v})),p(u,"replaceChild",(m=>function(v,x){var E=h(v);return E?m.call(this,E,x):x})),[(e=l.Element)==null?void 0:e.prototype,(n=l.Document)==null?void 0:n.prototype,(i=l.DocumentFragment)==null?void 0:i.prototype].forEach((m=>{p(m,"append",(v=>function(){for(var x=arguments.length,E=new Array(x),y=0;x>y;y++)E[y]=arguments[y];return v.apply(this,g(E))})),p(m,"prepend",(v=>function(){for(var x=arguments.length,E=new Array(x),y=0;x>y;y++)E[y]=arguments[y];return v.apply(this,g(E))}))})),[(r=l.Element)==null?void 0:r.prototype,(s=l.CharacterData)==null?void 0:s.prototype,(o=l.DocumentType)==null?void 0:o.prototype].forEach((m=>{p(m,"before",(v=>function(){for(var x=arguments.length,E=new Array(x),y=0;x>y;y++)E[y]=arguments[y];return v.apply(this,g(E))})),p(m,"after",(v=>function(){for(var x=arguments.length,E=new Array(x),y=0;x>y;y++)E[y]=arguments[y];return v.apply(this,g(E))})),p(m,"replaceWith",(v=>function(){for(var x=arguments.length,E=new Array(x),y=0;x>y;y++)E[y]=arguments[y];var b=g(E);return E.length&&!b.length?void 0:v.apply(this,b)}))})),p((a=l.Element)==null?void 0:a.prototype,"insertAdjacentElement",(m=>function(v,x){var E=h(x);return E?m.call(this,v,E):null})),this.wl=()=>{c.forEach((m=>m())),this.wl=void 0},this.kl()}kl(){var t=!1;return()=>{var e;t||(t=!0,this.pl--,this.pl===0&&((e=this.wl)==null||e.call(this)))}}xl(t,e){e===void 0&&(e=!0);var n=this._l();try{var i=t(n);return e&&n(),i}catch(r){throw n(),r}}setupSiteApp(t){var e=this.apps[t.id],n=()=>{var o;!e.errored&&this.gl.length&&(Ft.info("Processing "+this.gl.length+" events for site app with id "+t.id),this.gl.forEach((a=>this.xl((()=>e.processEvent==null?void 0:e.processEvent(a))))),e.processedBuffer=!0),Object.values(this.apps).every((a=>a.processedBuffer||a.errored))&&((o=this.yl)==null||o.call(this))},i=!1,r=o=>{e.errored=!o,e.loaded=!0,Ft.info("Site app with id "+t.id+" "+(o?"loaded":"errored")),i&&n()};try{var s=this.xl((o=>t.init({posthog:this._instance,callback(a){o(),r(a)}})),!1).processEvent;s&&(e.processEvent=s),i=!0}catch(o){Ft.error(ju+t.id,o),r(!1)}if(i&&e.loaded)try{n()}catch(o){Ft.error("Error while processing buffered events PostHog app with config id "+t.id,o),e.errored=!0}}Sl(){var t=this.siteAppLoaders||[];for(var e of t)this.apps[e.id]={id:e.id,loaded:!1,errored:!1,processedBuffer:!1};for(var n of t)this.setupSiteApp(n)}Cl(t){var e=this;if(Object.keys(this.apps).length!==0){var n=this.globalsForEvent(t),i=function(s){try{e.xl((()=>s.processEvent==null?void 0:s.processEvent(n)))}catch(o){Ft.error("Error while processing event "+t.event+" for site app "+s.id,o)}};for(var r of Object.values(this.apps))i(r)}}onRemoteConfig(t){var e,n,i,r=this;if((e=this.siteAppLoaders)!=null&&e.length)return this.isEnabled?(this.Sl(),void this._instance.on("eventCaptured",(l=>this.Cl(l)))):void Ft.error('PostHog site apps are disabled. Enable the "opt_in_site_apps" config to proceed.');if((n=this.yl)==null||n.call(this),t.ok){var s=t.config;if((i=s.siteApps)!=null&&i.length)if(this.isEnabled){var o=function(){var l,u=a.id,c=a.url;B["__$$ph_site_app_"+u]=r._instance,(l=B.__PosthogExtensions__)==null||l.loadSiteApp==null||l.loadSiteApp(r._instance,c,(d=>{if(d)return Ft.error(ju+u,d)}))};for(var a of s.siteApps)o()}else Ft.error('PostHog site apps are disabled. Enable the "opt_in_site_apps" config to proceed.')}}}},Bv={tracingHeaders:class{constructor(t){this.Ml=void 0,this.Tl=void 0,this.El=void 0,this.Uo=()=>{var e,n,i=this.Il();i?(A(this.Ml)&&(this.Ml=(e=B.__PosthogExtensions__)==null||(e=e.tracingHeadersPatchFns)==null?void 0:e._patchXHR(i,(()=>this._instance.get_distinct_id()),this._instance.sessionManager)),A(this.Tl)&&(this.Tl=(n=B.__PosthogExtensions__)==null||(n=n.tracingHeadersPatchFns)==null?void 0:n._patchFetch(i,(()=>this._instance.get_distinct_id()),this._instance.sessionManager))):this.Qo()},this._instance=t}initialize(){this.startIfEnabledOrStop()}ai(t){var e,n;(e=B.__PosthogExtensions__)!=null&&e.tracingHeadersPatchFns?t():(n=B.__PosthogExtensions__)==null||n.loadExternalDependency==null||n.loadExternalDependency(this._instance,"tracing-headers",(i=>{if(i)return xv.error("failed to load script",i);t()}))}Pl(){var t,e;return(t=(e=this._instance.config.tracing_headers)!==null&&e!==void 0?e:this._instance.config.addTracingHeaders)!==null&&t!==void 0?t:this._instance.config.__add_tracing_headers}Il(){var t=this.Pl();return U(t)?(U(this.El)?this.El.splice(0,this.El.length,...t):this.El=[...t],t.length>0?this.El:void 0):(U(this.El)&&this.El.splice(0),this.El=t||void 0,this.El)}Qo(){var t,e;(t=this.Ml)==null||t.call(this),(e=this.Tl)==null||e.call(this),this.Ml=void 0,this.Tl=void 0}startIfEnabledOrStop(){this.Il()?this.ai(this.Uo):this.Qo()}}},Dv=k({surveys:class{get Ne(){return this._instance.config}constructor(t){this.Rl=void 0,this._surveyManager=null,this.Al=!1,this.Fl=[],this.Ll=null,this.Ol=null,this._instance=t,this._surveyEventReceiver=null}initialize(){this.loadIfEnabled()}onRemoteConfig(t){if(!this.Ne.disable_surveys){if(!t.ok)return te.warn("Remote config unavailable. Not loading surveys.");var e=t.config.surveys;if(q(e))return te.warn("Flags not loaded yet. Not loading surveys.");var n=U(e);this.Rl=n?e.length>0:e,te.info("flags response received, isSurveysEnabled: "+this.Rl),this.loadIfEnabled()}}reset(){try{var t;(t=this._surveyEventReceiver)==null||t.reset(),localStorage.removeItem("lastSeenSurveyDate");for(var e=[],n=0;nlocalStorage.removeItem(r)))}catch{}}loadIfEnabled(){if(!this._surveyManager)if(this.Al)te.info("Already initializing surveys, skipping...");else if(this.Ne.disable_surveys)te.info(Uu);else if(this.Ne.cookieless_mode&&this._instance.consent.isOptedOut())te.info("Not loading surveys in cookieless mode without consent.");else{var t=B?.__PosthogExtensions__;if(t){if(!A(this.Rl)||this.Ne.advanced_enable_surveys){var e=this.Rl||this.Ne.advanced_enable_surveys;this.Al=!0;try{var n=t.generateSurveys;if(n)return void this.Dl(n,e);var i=t.loadExternalDependency;if(!i)return void this.$l(Ml);i(this._instance,"surveys",(r=>{r||!t.generateSurveys?this.$l("Could not load surveys script",r):this.Dl(t.generateSurveys,e)}))}catch(r){throw this.$l("Error initializing surveys",r),r}finally{this.Al=!1}}}else te.error("PostHog Extensions not found.")}}Dl(t,e){this._surveyManager=t(this._instance,e),this._surveyEventReceiver=new Pv(this._instance),te.info("Surveys loaded successfully"),this.Nl({isLoaded:!0})}$l(t,e){te.error(t,e),this.Nl({isLoaded:!1,error:t})}onSurveysLoaded(t){return this.Fl.push(t),this._surveyManager&&this.Nl({isLoaded:!0}),()=>{this.Fl=this.Fl.filter((e=>e!==t))}}getSurveys(t,e){if(e===void 0&&(e=!1),this.Ne.disable_surveys)return te.info(Uu),t([]);var n,i=this._instance.get_property(Fa);if(i&&!e)return t(i,{isLoaded:!0}),void(this.ql()&&this.getSurveys((()=>{}),!0));typeof Promise<"u"&&this.Ll?this.Ll.then((r=>t(r.surveys,r.context))):(typeof Promise<"u"&&(this.Ll=new Promise((r=>{n=r}))),this._instance._send_request({url:this._instance.requestRouter.endpointFor("api","/api/surveys/?token="+this.Ne.token),method:"GET",timestampMode:"query",timeout:this.Ne.surveys_request_timeout_ms,callback:r=>{var s;this.Ll=null;var o=r.statusCode;if(o!==200||!r.json){var a="Surveys API could not be loaded, status: "+o;o!==0?te.error(a):r.error||te.warn(a),this.Ol=Date.now();var l={isLoaded:!1,error:a};return t([],l),void(n==null||n({surveys:[],context:l}))}this.Ol=null;var u,c=r.json.surveys||[],d=c.filter((p=>(function(h){return!(!h.start_date||h.end_date)})(p)&&(Eh(p)||(function(h){var g;return!((g=h.conditions)==null||(g=g.actions)==null||(g=g.values)==null||!g.length)})(p))));d.length>0&&((u=this._surveyEventReceiver)==null||u.register(d)),(s=this._instance.persistence)==null||s.register({[Fa]:c,[_s]:Date.now()});var f={isLoaded:!0};t(c,f),n?.({surveys:c,context:f})}}))}ql(){return this.jl()&&!this.Ll&&!this.Bl()}jl(){var t=this._instance.get_property(_s);return Fe(t)&&Date.now()-t>3e5}Bl(){return Fe(this.Ol)&&3e5>Date.now()-this.Ol}markSurveyAsSeen(t,e){var n,i={id:t,current_iteration:(n=e?.iteration)!==null&&n!==void 0?n:null};xh(i);try{localStorage.setItem("lastSeenSurveyDate",new Date().toISOString())}catch{}}Nl(t){for(var e of this.Fl)try{if(!t.isLoaded)return e([],t);this.getSurveys(e)}catch(n){te.error("Error in survey callback",n)}}getActiveMatchingSurveys(t,e){if(e===void 0&&(e=!1),!q(this._surveyManager))return this._surveyManager.getActiveMatchingSurveys(t,e);te.warn("init was not called")}Hl(t){var e=null;return this.getSurveys((n=>{var i;e=(i=n.find((r=>r.id===t)))!==null&&i!==void 0?i:null})),e}Ul(t){if(q(this._surveyManager))return{eligible:!1,reason:zr};var e=typeof t=="string"?this.Hl(t):t;return e?this._surveyManager.checkSurveyEligibility(e):{eligible:!1,reason:"Survey not found"}}zl(t){if(q(this._surveyManager))return{eligible:!1,reason:zr};var e=typeof t=="string"?this.Hl(t):t;return e?this._surveyManager.checkSurveyRenderability(e):{eligible:!1,reason:"Survey not found"}}canRenderSurvey(t){if(q(this._surveyManager))return te.warn("init was not called"),{visible:!1,disabledReason:zr};var e=this.zl(t);return{visible:e.eligible,disabledReason:e.reason}}canRenderSurveyAsync(t,e){return q(this._surveyManager)?(te.warn("init was not called"),Promise.resolve({visible:!1,disabledReason:zr})):new Promise((n=>{this.getSurveys((i=>{var r,s=(r=i.find((a=>a.id===t)))!==null&&r!==void 0?r:null;if(s){var o=this.zl(s);n({visible:o.eligible,disabledReason:o.reason})}else n({visible:!1,disabledReason:"Survey not found"})}),e)}))}renderSurvey(t,e,n){var i;if(q(this._surveyManager))te.warn("init was not called");else{var r=typeof t=="string"?this.Hl(t):t;if(r!=null&&r.id)if(dv.includes(r.type)){var s=F?.querySelector(e);if(s)return(i=r.appearance)!=null&&i.surveyPopupDelaySeconds?(te.info("Rendering survey "+r.id+" with delay of "+r.appearance.surveyPopupDelaySeconds+" seconds"),void setTimeout((()=>{var o,a;te.info("Rendering survey "+r.id+" with delay of "+((o=r.appearance)==null?void 0:o.surveyPopupDelaySeconds)+" seconds"),(a=this._surveyManager)==null||a.renderSurvey(r,s,n),te.info("Survey "+r.id+" rendered")}),1e3*r.appearance.surveyPopupDelaySeconds)):void this._surveyManager.renderSurvey(r,s,n);te.warn("Survey element not found")}else te.warn("Surveys of type "+r.type+" cannot be rendered in the app");else te.warn("Survey not found")}}displaySurvey(t,e){var n;if(q(this._surveyManager))te.warn("init was not called");else{var i=this.Hl(t);if(i){var r=i;if((n=i.appearance)!=null&&n.surveyPopupDelaySeconds&&e.ignoreDelay&&(r=k({},i,{appearance:k({},i.appearance,{surveyPopupDelaySeconds:0})})),e.displayType!==ja.Popover&&e.initialResponses&&te.warn("initialResponses is only supported for popover surveys. prefill will not be applied."),e.ignoreConditions===!1){var s=this.Ul(i);if(!s.eligible)return void te.warn("Survey is not eligible to be displayed: ",s.reason)}e.displayType!==ja.Inline?this._surveyManager.handlePopoverSurvey(r,e):this.renderSurvey(r,e.selector,e.properties)}else te.warn("Survey not found")}}cancelPendingSurvey(t){q(this._surveyManager)?te.warn("init was not called"):this._surveyManager.cancelSurvey(t)}handlePageUnload(){var t;(t=this._surveyManager)==null||t.handlePageUnload==null||t.handlePageUnload()}}},Zs),jv={toolbar:class{constructor(t){this.instance=t}Wl(t){B.ph_toolbar_state=t}Vl(){var t;return(t=B.ph_toolbar_state)!==null&&t!==void 0?t:0}initialize(){return this.maybeLoadToolbar()}maybeLoadToolbar(t,e,n){if(t===void 0&&(t=void 0),e===void 0&&(e=void 0),n===void 0&&(n=void 0),Oa(this.instance.config)||!w||!F)return!1;t=t??w.location,n=n??w.history;try{if(!e){try{w.localStorage.setItem("test","test"),w.localStorage.removeItem("test")}catch{return!1}e=w?.localStorage}var i,r=Fv||Cs(t.hash,"__posthog")||Cs(t.hash,"state"),s=r?su((()=>JSON.parse(atob(decodeURIComponent(r)))))||su((()=>JSON.parse(decodeURIComponent(r)))):null;return s&&s.action==="ph_authorize"?((i=s).source="url",i&&Object.keys(i).length>0&&(s.desiredHash?t.hash=s.desiredHash:n?n.replaceState(n.state,"",t.pathname+t.search):t.hash="")):((i=JSON.parse(e.getItem(Hu)||"{}")).source="localstorage",delete i.userIntent),!(!i.token||this.instance.config.token!==i.token||(this.loadToolbar(i),0))}catch{return!1}}Zl(t){var e=B.ph_load_toolbar||B.ph_load_editor;!q(e)&&qe(e)?e(t,this.instance):Wu.warn("No toolbar load function found")}loadToolbar(t){var e=!(F==null||!F.getElementById(Df));if(!w||e)return!1;var n=this.instance.requestRouter.region==="custom"&&this.instance.config.advanced_disable_toolbar_metrics,i=k({token:this.instance.config.token},t,{apiURL:this.instance.requestRouter.endpointFor("ui")},n?{instrument:!1}:{});if(w.localStorage.setItem(Hu,JSON.stringify(k({},i,{source:void 0}))),this.Vl()===2)this.Zl(i);else if(this.Vl()===0){var r;this.Wl(1),(r=B.__PosthogExtensions__)==null||r.loadExternalDependency==null||r.loadExternalDependency(this.instance,"toolbar",(s=>{if(s)return Wu.error("[Toolbar] Failed to load",s),void this.Wl(0);this.Wl(2),this.Zl(i)})),Se(w,"turbolinks:load",(()=>{this.Wl(0),this.loadToolbar(i)}))}return!0}Gl(t){return this.loadToolbar(t)}maybeLoadEditor(t,e,n){return t===void 0&&(t=void 0),e===void 0&&(e=void 0),n===void 0&&(n=void 0),this.maybeLoadToolbar(t,e,n)}}},Uv=k({experiments:De},Zs),Hv={conversations:class{constructor(t){this.Ql=void 0,this._conversationsManager=null,this.Kl=!1,this.Jl=null,this.Yl=!1,this._instance=t}initialize(){this.loadIfEnabled()}onRemoteConfig(t){if(!this._instance.config.disable_conversations&&(this.Xl=t.ok,t.ok)){var e=t.config.conversations;q(e)||(kt(e)?this.Ql=e:(this.Ql=e.enabled,this.Jl=e),this.loadIfEnabled())}}reset(){var t;(t=this._conversationsManager)==null||t.reset(),this._conversationsManager=null,this.Ql=void 0,this.Jl=null,this.Xl=void 0,this.Yl=!1}loadIfEnabled(){if(!(this._conversationsManager||this.Kl||this._instance.config.disable_conversations||Oa(this._instance.config)||this._instance.config.cookieless_mode&&this._instance.consent.isOptedOut())){var t=B?.__PosthogExtensions__;if(t&&!A(this.Ql)&&this.Ql)if(this.Jl&&this.Jl.token){this.Kl=!0;try{var e=t.initConversations;if(e)return this.tu(e),void(this.Kl=!1);var n=t.loadExternalDependency;if(!n)return void this.eu(Ml);n(this._instance,"conversations",(i=>{i||!t.initConversations?this.eu("Could not load conversations script",i):this.tu(t.initConversations),this.Kl=!1}))}catch(i){this.eu("Error initializing conversations",i),this.Kl=!1}}else vt.error("Conversations enabled but missing token in remote config.")}}tu(t){if(this.Jl)try{this._conversationsManager=t(this.Jl,this._instance),this.Yl=!1,vt.info("Conversations loaded successfully")}catch(e){this.eu("Error completing conversations initialization",e)}else vt.error("Cannot complete initialization: remote config is null")}eu(t,e){vt.error(t,e),this._conversationsManager=null,this.Kl=!1,this.Yl=!0}show(){this._conversationsManager?this._conversationsManager.show():vt.warn("Conversations not loaded yet.")}hide(){this._conversationsManager&&this._conversationsManager.hide()}isAvailable(){return this.Ql===!0&&!it(this._conversationsManager)}getUnavailableReason(){return this.isAvailable()?null:this._instance.config.disable_conversations?"disabled_by_config":Oa(this._instance.config)?"disabled_for_toolbar":this._instance.config.cookieless_mode&&this._instance.consent.isOptedOut()?"consent_opted_out":this.Xl===!1?"remote_config_failed":A(this.Ql)?this.Xl?"disabled_in_project":"remote_config_pending":this.Ql?q(this.Jl)||!this.Jl.token?"missing_token":B!=null&&B.__PosthogExtensions__?this.Kl?"initializing":this.Yl?"load_failed":"not_loaded":"extensions_unavailable":"disabled_in_project"}isVisible(){var t,e;return(t=(e=this._conversationsManager)==null?void 0:e.isVisible())!==null&&t!==void 0&&t}sendMessage(t,e,n){var i=this;return ce((function*(){return i._conversationsManager?i._conversationsManager.sendMessage(t,e,n):(vt.warn($n),null)}))()}getMessages(t,e){var n=this;return ce((function*(){return n._conversationsManager?n._conversationsManager.getMessages(t,e):(vt.warn($n),null)}))()}markAsRead(t){var e=this;return ce((function*(){return e._conversationsManager?e._conversationsManager.markAsRead(t):(vt.warn($n),null)}))()}getTickets(t){var e=this;return ce((function*(){return e._conversationsManager?e._conversationsManager.getTickets(t):(vt.warn($n),null)}))()}requestRestoreLink(t){var e=this;return ce((function*(){return e._conversationsManager?e._conversationsManager.requestRestoreLink(t):(vt.warn($n),null)}))()}restoreFromToken(t){var e=this;return ce((function*(){return e._conversationsManager?e._conversationsManager.restoreFromToken(t):(vt.warn($n),null)}))()}restoreFromUrlToken(){var t=this;return ce((function*(){return t._conversationsManager?t._conversationsManager.restoreFromUrlToken():(vt.warn($n),null)}))()}getCurrentTicketId(){var t,e;return(t=(e=this._conversationsManager)==null?void 0:e.getCurrentTicketId())!==null&&t!==void 0?t:null}getWidgetSessionId(){var t,e;return(t=(e=this._conversationsManager)==null?void 0:e.getWidgetSessionId())!==null&&t!==void 0?t:null}Xn(){var t;(t=this._conversationsManager)==null||t.setIdentity()}ts(){var t;(t=this._conversationsManager)==null||t.clearIdentity()}}},Wv={logs:class{constructor(t){var e,n=this;this.iu=!1,this.ru=!1,this.rt=_e("[logs]"),this.nu=k({},this.rt,{error(){for(var i=arguments.length,r=new Array(i),s=0;i>s;s++)r[s]=arguments[s];r.some(Zu)||n.rt.error(...r)}}),this.tr=[],this.su=[],this.Sa=0,this.au=()=>{var i,r;this.Sa=0,(i=this.ou)==null||i.onReconnect(),(r=this.lu)==null||r.onReconnect()},this._instance=t,this._instance&&(e=this._instance.config.logs)!=null&&e.captureConsoleLogs&&(this.iu=!0),w&&Se(w,"online",this.au)}uu(t,e,n,i){var r,s=(function(o,a){var l,u,c,d,f,p,h,g=(l=o?.flushIntervalMs)!==null&&l!==void 0?l:3e3,m=(u=o?.maxBufferSize)!==null&&u!==void 0?u:100,v=a!=null&&a.consoleCapture?void 0:(c=o?.maxLogsPerInterval)!==null&&c!==void 0?c:1e3,x=A(v)?Math.max(m,2048):Math.max(m,v),E=o?.resourceAttributes;return{serviceName:(d=(f=E?.["service.name"])!==null&&f!==void 0?f:o?.serviceName)!==null&&d!==void 0?d:a?.serviceNameDefault,serviceVersion:(p=E?.["service.version"])!==null&&p!==void 0?p:o?.serviceVersion,environment:(h=E?.["deployment.environment"])!==null&&h!==void 0?h:o?.environment,resourceAttributes:E,beforeSend:o?.beforeSend,flushIntervalMs:g,maxBufferSize:m,maxQueueSize:x,maxBatchRecordsPerPost:100,rateCapWindowMs:g,maxLogsPerInterval:v,backgroundFlushBudgetMs:0,terminationFlushBudgetMs:0}})((r=this._instance)==null||(r=r.config)==null?void 0:r.logs,n);return[new Gg(this.hu(t,e),s,this.nu,(()=>this.du()),(o=>o()),void 0,i),s]}vu(){var t,e=(t=this._instance)==null||(t=t.config)==null?void 0:t.logs;if(!this.ou||this.cu!==e){var n;(n=this.ou)==null||n.reset(),this.cu=e;var i=this.uu((()=>this.tr),(r=>{this.tr=r}));this.ou=i[0],this.fu=i[1]}return this.ou}pu(){var t,e=(t=this._instance)==null||(t=t.config)==null?void 0:t.logs;if(!this.lu||this.gu!==e){var n;(n=this.lu)==null||n.reset(),this.gu=e;var i=this.uu((()=>this.su),(r=>{this.su=r}),{serviceNameDefault:"posthog-browser-logs",consoleCapture:!0},Ju);this.lu=i[0],this.mu=i[1]}return this.lu}initialize(){this.loadIfEnabled()}onRemoteConfig(t){var e;if(t.ok){var n=(e=t.config.logs)==null?void 0:e.captureConsoleLogs;!q(n)&&n&&(this.iu=!0,this.loadIfEnabled())}}reset(){var t,e;this.tr=[],(t=this.ou)==null||t.reset(),this.su=[],(e=this.lu)==null||e.reset(),this.Sa=0}captureLog(t){this.vu().captureLog(t)}he(t){this.pu().captureLog(t)}get logger(){return this.yu||(this.yu={trace:(t,e)=>this.captureLog({body:t,level:"trace",attributes:e}),debug:(t,e)=>this.captureLog({body:t,level:"debug",attributes:e}),info:(t,e)=>this.captureLog({body:t,level:"info",attributes:e}),warn:(t,e)=>this.captureLog({body:t,level:"warn",attributes:e}),error:(t,e)=>this.captureLog({body:t,level:"error",attributes:e}),fatal:(t,e)=>this.captureLog({body:t,level:"fatal",attributes:e})}),this.yu}flushLogs(t){t?this.bu(t):(this.ou&&this.ou.flush().catch((e=>this._u(e))),this.lu&&this.lu.flush().catch((e=>this._u(e))))}_u(t){Zu(t)||this.rt.error("PostHog logs flush failed:",t)}loadIfEnabled(){if(this.iu&&!this.ru){var t=B?.__PosthogExtensions__;if(t){var e=t.loadExternalDependency;e?e(this._instance,"logs",(n=>{var i;n||(i=t.logs)==null||!i.initializeLogs?this.rt.error("Could not load logs script",n):(t.logs.initializeLogs(this._instance),this.ru=!0)})):this.rt.error(Ml)}else this.rt.error("PostHog Extensions not found.")}}hu(t,e){var n=this._instance;return{get isDisabled(){return!1},get optedOut(){return!n.is_capturing()},getPersistedProperty:i=>i===Zt.LogsQueue?t():void 0,setPersistedProperty(i,r){var s;i===Zt.LogsQueue&&e((s=r)!==null&&s!==void 0?s:[])},Ot:i=>this.Ot(i),getLibraryId:()=>oe.LIB_NAME,getLibraryVersion:()=>oe.LIB_VERSION}}Ot(t){return new Promise((e=>{if(Zf(this.Sa,3))e({kind:"fatal",error:oa(void 0,"logs endpoint is unreachable, dropping batch")});else{var n=!1,i=s=>{n||(n=!0,clearTimeout(r),e(s))},r=setTimeout((()=>{this.rt.warn("Logs request timed out before receiving a response"),i({kind:"retry-later",error:oa(void 0,"logs request timed out")})}),9e4);this._instance._send_request({method:"POST",url:this.wu(),data:t,compression:"best-available",batchKey:"logs",fireCallbackOnDrop:!0,callback:s=>{var o=s.statusCode;if(this.ku(o),o>=200&&300>o)i({kind:"ok"});else if(o===413)i({kind:"too-large"});else if(o!==0&&o!==429&&500>o)i({kind:"fatal",error:new Error("logs request failed with status "+o)});else{var a;o===0?(s.error||this.rt.warn("Logs request failed before receiving an HTTP response"),i({kind:"retry-later",error:oa(s.error,"logs request failed before receiving an HTTP response")})):i({kind:"retry-later",error:(a=s.error)!==null&&a!==void 0?a:new Error("logs request failed with status "+o)})}}})}}))}ku(t){(t!==0||this._instance.__loaded)&&(this.Sa=Xf(t,this.Sa,3,(()=>this.rt.warn("Log requests are failing before receiving an HTTP response; this can happen due to network issues, CORS, browser blocking, or ad blockers. Stopped sending logs; will try again when connectivity changes."))))}bu(t){this.tr.length>0&&this.xu(t,this.tr,this.fu,oe.LIB_NAME,(e=>{this.tr=e})),this.su.length>0&&this.xu(t,this.su,this.mu,Ju,(e=>{this.su=e}))}xu(t,e,n,i,r){if(e.length!==0){var s=e.map((a=>a.record));r([]);var o=Ef(s,bf(n,oe.LIB_NAME,oe.LIB_VERSION),i,oe.LIB_VERSION);this._instance._send_request({method:"POST",url:this.wu(),data:o,compression:"best-available",batchKey:"logs",transport:t})}}wu(){return this._instance.requestRouter.endpointFor("api","/i/v1/logs")+"?token="+encodeURIComponent(this._instance.config.token)}du(){var t,e={};if(e.distinctId=this._instance.get_distinct_id(),this._instance.sessionManager){var n=this._instance.sessionManager.checkAndGetSessionAndWindowId(!0),i=n.windowId,r=n.sessionStartTimestamp,s=n.lastActivityTimestamp;e.sessionId=n.sessionId,e.windowId=i,q(r)||(e.sessionStartTimestamp=r),q(s)||(e.lastActivityTimestamp=s)}if(B!=null&&(t=B.location)!=null&&t.href&&(e.currentUrl=this._instance.config.disable_capture_url_hashes?Sn(B.location.href):B.location.href),this._instance.featureFlags){var o=this._instance.featureFlags.getFlags();o&&o.length>0&&(e.activeFeatureFlags=o)}return e}}},qv={metrics:class{constructor(t){this.rt=_e("[metrics]"),this._instance=t}initialize(){}vu(){var t,e,n=(t=this._instance)==null||(t=t.config)==null?void 0:t.metrics;return this.ou&&this.cu===n||((e=this.ou)==null||e.reset(),this.cu=n,this.ou=new Kg(this.hu(),(function(i){var r,s,o,a,l,u=i?.resourceAttributes;return{serviceName:(r=u?.["service.name"])!==null&&r!==void 0?r:i?.serviceName,serviceVersion:(s=u?.["service.version"])!==null&&s!==void 0?s:i?.serviceVersion,environment:(o=u?.["deployment.environment"])!==null&&o!==void 0?o:i?.environment,resourceAttributes:u,beforeSend:i?.beforeSend,flushIntervalMs:(a=i?.flushIntervalMs)!==null&&a!==void 0?a:1e4,maxSeriesPerFlush:(l=i?.maxSeriesPerFlush)!==null&&l!==void 0?l:1e3}})(n),this.rt)),this.ou}count(t,e,n){e===void 0&&(e=1),this.vu().count(t,e,n)}gauge(t,e,n){this.vu().gauge(t,e,n)}histogram(t,e,n){this.vu().histogram(t,e,n)}flush(t){if(!this.ou)return Promise.resolve();if(t){var e=this.ou.drainWindow();return e&&this.Jt(e,t),Promise.resolve()}return this.ou.flush().catch((n=>this.rt.error("PostHog metrics flush failed:",n)))}reset(){var t;(t=this.ou)==null||t.reset()}hu(){var t=this._instance,e=this;return{get isDisabled(){return!1},get optedOut(){return!t.is_capturing()},Jt:n=>e.Jt(n),getLibraryId:()=>oe.LIB_NAME,getLibraryVersion:()=>oe.LIB_VERSION}}Jt(t,e){return new Promise((n=>{var i=!1,r=o=>{i||(i=!0,clearTimeout(s),n(o))},s=setTimeout((()=>r({kind:"retry-later",error:new Error("metrics request timed out")})),9e4);this._instance._send_request(k({method:"POST",url:this.Su(),data:t,compression:"best-available",batchKey:"metrics"},e&&{transport:e},{fireCallbackOnDrop:!0,callback(o){var a=o.statusCode;if(a>=200&&300>a)r({kind:"ok"});else if(a===413)r({kind:"too-large"});else if(a!==0&&a!==429&&500>a)r({kind:"fatal",error:new Error("metrics request failed with status "+a)});else{var l;r({kind:"retry-later",error:(l=o.error)!==null&&l!==void 0?l:new Error("metrics request failed with status "+a)})}}}))}))}Su(){return this._instance.requestRouter.endpointFor("api","/i/v1/metrics")+"?token="+encodeURIComponent(this._instance.config.token)}}},zv=k({},Zs,Mv,$v,Lv,Nv,Ov,Dv,Bv,jv,Uv,Hv,Wv,qv);st.__defaultExtensionClasses=k({},zv);(function(){oe.SDK_DIST_CHANNEL="npm";var t=nr[ri]=new st;return(function(){function e(){e.done||(e.done=!0,kh=!1,ae(nr,(function(n){n._dom_loaded()})))}F!=null&&F.addEventListener?F.readyState==="complete"?e():Se(F,"DOMContentLoaded",e,{capture:!1}):w&&P.error("Browser doesn't support `document.addEventListener` so PostHog couldn't be initialized")})(),t})();const Vv=["a[href]","button:not([disabled])","input:not([disabled]):not([type='hidden'])","select:not([disabled])","textarea:not([disabled])","[tabindex]:not([tabindex='-1'])"].join(",");let et=null,Ts=null,Ah="";const Ka=new Map;function Ph(t){return[...t.querySelectorAll(Vv)].filter(e=>!e.hidden&&e.getAttribute("aria-hidden")!=="true"&&e.getClientRects().length>0)}function Gv(t){for(const n of document.body.children)n===t||n.tagName==="SCRIPT"||(Ka.set(n,{inert:n.inert,ariaHidden:n.getAttribute("aria-hidden")}),n.inert=!0,n.setAttribute("aria-hidden","true"));const e=document.activeElement;e&&e!==document.body&&!t.contains(e)&&e.blur()}function Kv(){for(const[t,e]of Ka)t.inert=e.inert,e.ariaHidden===null?t.removeAttribute("aria-hidden"):t.setAttribute("aria-hidden",e.ariaHidden);Ka.clear()}function Fh(t){return t?.dataset.modalDismissible!=="false"&&t?.getAttribute("aria-busy")!=="true"}function Ke(t,e={}){const n=typeof t=="string"?document.getElementById(t):t;if(!n)return!1;const i=et&&et!==n?et:null,r=Ts;if(i&&Ye(i,{restoreFocus:!1,force:!0}),et!==n){let a=e.trigger||document.activeElement;a&&(i?.contains(a)||n.contains(a))&&(a=r),Ts=a,Ah=document.body.style.overflow,Gv(n),document.body.style.overflow="hidden"}et=n,n.classList.add("open"),n.setAttribute("aria-hidden","false");const s=n.querySelector(".modal-content");s&&(s.style.transform="scale(1) translateY(0)");const o=()=>{if(et!==n)return;((e.initialFocus?n.querySelector(e.initialFocus):n.querySelector("[data-modal-initial-focus]"))||Ph(n)[0]||n.querySelector(".modal-content")||n).focus({preventScroll:!0})};return requestAnimationFrame(o),setTimeout(o,260),!0}function Ye(t,e={}){const n=typeof t=="string"?document.getElementById(t):t;if(!n||!e.force&&!Fh(n))return!1;if(n.classList.remove("open"),n.setAttribute("aria-hidden","true"),n!==et)return!0;Kv(),document.body.style.overflow=Ah,et=null;const i=Ts;return Ts=null,e.restoreFocus!==!1&&i?.isConnected&&i.focus({preventScroll:!0}),!0}function Yv(){return!!et}function Xu(t,e,n="Operation in progress"){const i=typeof t=="string"?document.getElementById(t):t;i&&(i.dataset.modalDismissible=e?"false":"true",i.setAttribute("aria-busy",String(!!e)),e?i.setAttribute("aria-label",n):i.removeAttribute("aria-label"))}function Jv(t){if(!Fh(t))return;const e=t.dataset.modalCloseHandler;e&&typeof window[e]=="function"?window[e]():Ye(t)}document.addEventListener("keydown",t=>{if(!et)return;if(t.key==="Escape"){t.preventDefault(),t.stopImmediatePropagation(),Jv(et);return}if(t.key!=="Tab"){t.stopPropagation();return}const e=Ph(et);if(!e.length){t.preventDefault(),(et.querySelector(".modal-content")||et).focus();return}const n=e[0],i=e[e.length-1];t.shiftKey&&document.activeElement===n?(t.preventDefault(),i.focus()):!t.shiftKey&&document.activeElement===i&&(t.preventDefault(),n.focus())},!0);function Zv(){document.querySelectorAll(".modal-overlay").forEach(t=>{t.setAttribute("role","dialog"),t.setAttribute("aria-modal","true"),t.setAttribute("aria-hidden",t.classList.contains("open")?"false":"true");const e=t.querySelector(".modal-content");e&&!e.hasAttribute("tabindex")&&(e.tabIndex=-1);const n=t.querySelector("h1, h2, h3");n&&(n.id||(n.id=`${t.id}-title`),t.setAttribute("aria-labelledby",n.id)),t.querySelectorAll(".modal-close").forEach(i=>{i.getAttribute("aria-label")||i.setAttribute("aria-label","Close dialog")})})}const Ul=Object.freeze({free:"Free",professional:"Pro",power:"Power"}),Xv=Object.freeze({free:2,professional:50,power:2e3}),Qv="(contact us)",ey=Object.freeze({free:Object.freeze(["2 generations/month","Gemini model only","Code Review"]),professional:Object.freeze(["50 generations/month","All models","Code Regeneration","Code Review"]),power:Object.freeze(["2000 generations/month","All models","Code Regeneration","Bring your own key (BYOK)","Code Review","All models + early access",`API & MCP access ${Qv}`])}),Rh="CodeFile",Th="GeneratedCode",ty={CustomAction:"A",CustomWidget:"W",CustomFunction:"F",CustomClass:"C",CodeFile:"C"};function wn(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}function Ya(t){return String(t||"").trim().replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function ny(t={},e=0){const n=Ya(t.artifactType||t.type||Rh),i=Ya(t.artifactName||t.name||t.fileName||`${Th}-${e+1}`);return`${n||"artifact"}-${i||e+1}`}function Mh(t={},e=0){const n=wn(t),i=n.artifactType||n.type||Rh,r=n.artifactName||n.name||Th;let s=n.fileName||r;return s.endsWith(".dart")||(s+=".dart"),{id:Ya(n.id)||ny({...n,artifactType:i,artifactName:r,fileName:s},e),artifactType:i,artifactName:r,fileName:s,deployPath:n.deployPath||"",description:n.description||"",code:n.code||n.content||"",dependencies:$h(n.dependencies),imports:Array.isArray(n.imports)?n.imports:[],publicApi:Array.isArray(n.publicApi)?n.publicApi:[],relationships:Lh(n.relationships),deployStatus:n.deployStatus||"pending",review:n.review||null,metadata:wn(n.metadata),codeType:n.codeType||ty[i]||"O"}}function $h(t){return t?Array.isArray(t)?t.map(e=>{if(typeof e=="string")return{name:e,version:null,inferred:!1};const n=wn(e),i=n.name||n.package;return i?{name:i,version:n.version||null,versionRequired:!!(n.versionRequired||n.required),inferred:!!n.inferred,...n.reason?{reason:n.reason}:{}}:null}).filter(Boolean):Object.entries(wn(t)).map(([e,n])=>({name:e,version:n||null,inferred:!1})):[]}function Lh(t){return t?(Array.isArray(t)?t:[t]).map(e=>{const n=wn(e);return!n.from&&!n.to?null:{from:n.from||null,to:n.to||null,type:n.type||"uses",description:n.description||""}}).filter(Boolean):[]}function Ja(t){if(typeof t!="string")return null;const e=t.trim();if(!e)return null;try{return JSON.parse(e)}catch{const n=e.match(/```(?:json)?\s*([\s\S]*?)```/i);if(!n)return null;try{return JSON.parse(n[1].trim())}catch{return null}}}function fr(t,e={}){const n=[],i=typeof t=="string"?Ja(t):t,s=wn(i||{});!i&&typeof t=="string"&&n.push("Structured bundle parse failed; using legacy single-artifact fallback.");const o=Array.isArray(s.artifacts)?s.artifacts:[{artifactType:s.artifactType||e.artifactType,artifactName:s.artifactName||e.artifactName,fileName:s.fileName||e.fileName,description:s.description,code:s.code||e.code||(typeof t=="string"?t:""),dependencies:s.dependencies||e.dependencies,relationships:s.relationships||e.relationships}];o.forEach((d,f)=>{!d?.artifactType&&!d?.type&&n.push(`Artifact ${f+1} has no artifactType; it will deploy as a standalone code file under lib/custom_code/ root.`)});const a=o.map((d,f)=>Mh(d,f)),l=new Map(o.map((d,f)=>[wn(d).id,a[f]?.id]).filter(([d,f])=>d&&f)),u=d=>l.get(d)||d,c=Lh(s.relationships||e.relationships).map(d=>({...d,from:d.from?u(d.from):d.from,to:d.to?u(d.to):d.to}));return{schemaVersion:s.schemaVersion||e.schemaVersion||null,id:s.id||e.id||"bundle-current",title:s.title||s.name||e.title||"Generated artifact bundle",description:s.description||e.description||"",artifacts:a,dependencies:$h(s.dependencies||e.dependencies),relationships:c,deployOrder:Array.isArray(s.deployOrder)?s.deployOrder.map(u):a.map(d=>d.id),warnings:[...n,...Array.isArray(s.warnings)?s.warnings:[]],metadata:wn(s.metadata)}}function _i(t){return fr(t).artifacts[0]||Mh()}function un(t){if(typeof t!="string")return t??"";const e=t.trim();if(!e)return"";try{return JSON.parse(e)}catch{return t}}function wi(t){return JSON.stringify(t,null,2)}function iy(t){return wi({task:"architect",userRequest:String(t??"")})}function ry(t){const e=un(t);return e&&typeof e=="object"&&typeof e.task=="string"?wi(e):wi({task:"generate_bundle",bundleSpec:e})}function sy(t){return wi({task:"review_bundle",generatedBundle:un(t),outputRequirements:{bundleReview:["status","score","summary","manualActions","findings"],scoreRange:[0,100],eachArtifact:["id","review.status","review.findings"],manualActions:{definition:"Setup the developer must perform by hand in the FlutterFlow editor that FlutterFlow will NOT do for them.",exclude:["creating the Custom Action, Widget or Code File itself - deploying the code creates it","declaring parameters or return values FlutterFlow derives from the function signature","anything that resolves as a side effect of using the action or widget in the editor","generic advice such as testing, reviewing or rebuilding the app"],preferEmpty:"Return an empty array when nothing qualifies - an empty list is the expected result for most bundles."}}})}function Hl(t,e=null){const n={stage:t};return e!=null&&(n.bundle=un(e)),n}function oy({bundleSpec:t,artifactBundle:e,bundleReview:n,artifactId:i,userFeedback:r}){return wi({task:"regenerate_artifact",artifactId:i,bundleSpec:un(t),artifactBundle:un(e),bundleReview:un(n),userFeedback:String(r)})}function Nh({bundleSpec:t,artifactBundle:e,bundleReview:n,userFeedback:i}){return wi({task:"regenerate_bundle",bundleSpec:un(t),artifactBundle:un(e),bundleReview:un(n),userFeedback:String(i??"")})}const Qu={csam:"child-safety content",dangerous:"dangerous content",harassment:"harassment",hate_speech:"hate speech",maliciousUrls:"a potentially malicious URL",malicious_uris:"a potentially malicious URL",pi_and_jailbreak:"prompt-injection or jailbreak instructions",promptInjection:"prompt-injection or jailbreak instructions",rai:"restricted content",sdp:"sensitive personal data",sexually_explicit:"sexually explicit content",virus_scan:"potentially malicious file content"},ay=["sanitizationResult","modelArmor","modelArmorResult","data","result","error"];function ct(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function ly(t){return ct(t)?typeof t.filterMatchState=="string"||typeof t.invocationResult=="string"||Array.isArray(t.matchedFilters)||ct(t.filterSummary)||ct(t.filterResults):!1}function Oh(t,e=0){if(!ct(t)||e>3)return null;if(ly(t))return t;for(const n of ay){const i=t[n];if(ct(i)){const r=Oh(i,e+1);if(r)return r}}return null}function Ms(t){return Array.isArray(t)?t.some(Ms):ct(t)?t.matched===!0||t.matchState==="MATCH_FOUND"?!0:Object.values(t).some(Ms):!1}function Za(t){return Array.isArray(t)?t.some(Za):ct(t)?typeof t.executionState=="string"&&t.executionState!=="EXECUTION_SUCCESS"?!0:Object.values(t).some(Za):!1}function Bh(t){return{csamFilterFilterResult:"csam",maliciousUriFilterResult:"malicious_uris",piAndJailbreakFilterResult:"pi_and_jailbreak",raiFilterResult:"rai",sdpFilterResult:"sdp",virusScanFilterResult:"virus_scan"}[t]||t}function cy(t,e){if(ct(t))for(const[n,i]of Object.entries(t)){if(!ct(i))continue;const r=ct(i.categories)?i.categories:{},s=Object.entries(r).filter(([,o])=>ct(o)&&o.matched===!0).map(([o])=>o);s.length>0?s.forEach(o=>e.add(o)):i.matched===!0&&e.add(Bh(n))}}function uy(t,e){if(!t)return;const n=Array.isArray(t)?t.flatMap(i=>ct(i)?Object.entries(i):[]):Object.entries(t);for(const[i,r]of n){if(!Ms(r))continue;const s=Bh(i),o=r?.raiFilterResult?.raiFilterTypeResults||(s==="rai"?r?.raiFilterTypeResults:null),a=ct(o)?Object.entries(o).filter(([,l])=>Ms(l)).map(([l])=>l):[];a.length>0?a.forEach(l=>e.add(l)):e.add(s)}}function dy(t){return Qu[t]?Qu[t]:String(t).replace(/([a-z])([A-Z])/g,"$1 $2").replace(/_/g," ").toLowerCase()}function ed(t){return t.length<=1?t[0]||"content that did not pass":t.length===2?`${t[0]} and ${t[1]}`:`${t.slice(0,-1).join(", ")}, and ${t.at(-1)}`}function fy(t){const e=Oh(t);if(!e)return null;const n=new Set(Array.isArray(e.matchedFilters)?e.matchedFilters:[]);cy(e.filterSummary,n),uy(e.filterResults,n);const i=e.blocked===!0||e.filterMatchState==="MATCH_FOUND"||n.size>0,r=e.invocationResult||null,s=Za(e.filterSummary||e.filterResults);return!i&&!s&&!["PARTIAL","FAILURE"].includes(r)?null:{kind:i?"blocked":"unavailable",invocationResult:r,matchedFilters:[...n]}}function hy(t,e){const n=fy(t);if(!n)return null;const i=[...new Set(n.matchedFilters.map(dy))],r=n.kind==="blocked",s=new Error(r?`Safety screening blocked this pipeline step for ${ed(i)}.`:"Safety screening could not be completed. Please try again.");return s.name="ModelArmorError",s.code=r?"MODEL_ARMOR_BLOCKED":"MODEL_ARMOR_UNAVAILABLE",s.isModelArmor=!0,s.pipelineStep=e,s.userTitle=r?"Request blocked for safety":"Safety check unavailable",s.userMessage=r?`The safety check detected ${ed(i)}. Edit your request to remove or rephrase the flagged content, then run the pipeline again.`:"The safety service did not finish all of its checks. Please wait a moment and run the pipeline again.",s.retryExplanation=r?"Trying another model would not change this safety decision.":"A fallback model was not attempted because safety screening must complete first.",s.matchedFilters=n.matchedFilters,s}function py(t){return String(t||"").replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/[^\n]*/g,"")}function td(t){const e=/^(import|export|part|library|class|enum|extension|typedef|mixin|abstract|const|final|var|late)\b/,n=[];for(const i of py(t).split(` +`)){if(!/^[A-Za-z_$]/.test(i)||e.test(i))continue;const r=i.match(/^[\w$<>,?\s[\]]+?\s([a-zA-Z_$][\w$]*)\s*\(/);r&&n.push(r[1])}return n}function Wl(t,e){const n=t.replace(/\.dart$/,"");if(e==="W")return n.replace(/(^|_)(\w)/g,(i,r,s)=>s.toUpperCase());if(e==="A"){const i=n.replace(/(^|_)(\w)/g,(r,s,o)=>o.toUpperCase());return i.charAt(0).toLowerCase()+i.slice(1)}return e==="F"?"CustomFunctions":e==="C"?t.endsWith(".dart")?t:`${t}.dart`:n}async function nd(t){const e=new TextEncoder().encode(String(t||"")),n=await globalThis.crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(n),i=>i.toString(16).padStart(2,"0")).join("")}async function gy(t,e=new Map){const n={},i=new Set;for(const[o,a]of t.entries()){if(a.type==="D"||a.type==="O")continue;const l=Wl(o,a.type),u={old_identifier_name:l,new_identifier_name:l,type:a.type,is_deleted:!1,current_checksum:await nd(a.content)},c=e.get(a.path);if(c!==void 0&&(u.original_checksum=await nd(c)),n[o]=u,a.type==="F"){const d=td(a.content);(d.length>0?d:[a.functionName].filter(Boolean)).forEach(p=>i.add(p))}}const r=new Set(td(e.get("lib/flutter_flow/custom_functions.dart")||"")),s={functions_to_rename:[],functions_to_delete:[],functions_to_add:Array.from(i).filter(o=>!r.has(o))};return{fileMapContents:JSON.stringify(n),functionsMapContents:JSON.stringify(s)}}const my=new Set(["CustomWidget","CustomAction","CustomFunction","CustomClass","CodeFile"]),id={CustomWidget:"custom_code/widgets/",CustomAction:"custom_code/actions/",CustomFunction:"flutter_flow/custom_functions.dart",CustomClass:"custom_code/",CodeFile:"custom_code/"},vy=new Set(["void","dynamic","String","int","double","num","bool","Color","DateTime","DateTimeRange","LatLng","FFPlace","FFUploadedFile","DocumentReference","List"]),yy=["Struct","Record"],_y=[{id:"required-public-param",severity:"error",message:"CustomWidget constructor uses `required` on a parameter FlutterFlow can leave unset. FlutterFlow omits unset Define Parameters fields from the constructor call, so the widget will not compile when placed. Make the parameter optional and nullable (`this.value` with `final double? value`), or give it a constructor default (`this.value = 0.0`).",detect:t=>aa(t).some(e=>/\brequired\s+this\.\w+/.test(e)),pos:"class W extends StatefulWidget { const W({required this.value}); final double value; }",neg:`class _P { const _P({required this.t}); final double t; } +class W extends StatefulWidget { const W({this.value}); final double? value; }`},{id:"non-nullable-public-field",severity:"error",message:"CustomWidget declares a non-nullable field with no constructor default. FlutterFlow omits unset Define Parameters fields, so the emitted call cannot supply it. Make the field nullable (`final double? value`) or give the parameter a default (`this.value = 0.0`).",detect:t=>aa(t).some(e=>{const n=/^\s*final\s+(?:double|int|String|bool|Color|num)\s+(\w+)\s*;/gm;let i;for(;(i=n.exec(e))!==null;){const r=i[1];if(!(new RegExp(`this\\.${r}\\s*=(?!=)`).test(e)||new RegExp(`[:,]\\s*${r}\\s*=(?!=)`).test(e)))return!0}return!1}),pos:`class W extends StatefulWidget { + const W({required this.value}); + final double value; +}`,neg:`class _P { + const _P({required this.t}); + final double t; +} +class W extends StatefulWidget { + const W({this.value = 1.0}); + final double value; +}`},{id:"asset-without-anchor",severity:"warning",message:'CustomWidget calls Image.asset with a path arriving as a String parameter. An asset reaches the build only when a FlutterFlow widget NODE references it - a filename passed as a parameter does not count, so the image renders as a broken-image icon on device. "Download Unused Project Assets" does not fix it (FlutterFlow issues 522, 2271, 3799). Keep something in the UI referencing the file, or load it over the network instead.',detect:t=>/Image\.asset\s*\(/.test(t)&&/final\s+String\??\s+\w*[Pp]ath\b/.test(t),pos:`class W extends StatefulWidget { final String? imagePath; } +var x = Image.asset(widget.imagePath);`,neg:`class W extends StatefulWidget { final String? imagePath; } +var x = Image.network(widget.imagePath);`},{id:"unsupported-param-type",severity:"error",message:"CustomWidget exposes a Flutter data type FlutterFlow cannot express as a Define Parameter: TextStyle, BoxShadow, FontWeight, FontStyle, TextDirection, TextAlign, EdgeInsets, Offset, Alignment/AlignmentGeometry, Border, BorderRadius, BoxDecoration, BoxConstraints, BorderSide, Gradient, or ThemeData. FlutterFlow's supported data types (docs.flutterflow.io/resources/data-representation/data-types) are only int, double, bool, string, Color, Image, DateTime, Json, LatLng, and the FF objects, so this parameter cannot be configured in the editor and the widget will not place or compile. Expose primitives instead (color, fontSize as double?, fontWeight via a custom enum, doubles for spacing).",detect:t=>aa(t).some(e=>/final\s+(TextStyle|BoxShadow|FontWeight|FontStyle|TextDirection|TextAlign|EdgeInsets|Offset|Alignment(?:Geometry)?|Border(?:Radius|Side)?|BoxDecoration|BoxConstraints|Gradient|LinearGradient|RadialGradient|ThemeData)\??\s+\w+\s*;/.test(e)),pos:`class W extends StatefulWidget { + const W({this.textStyle}); + final TextStyle? textStyle; + @override _S createState() => _S(); +} +class _S extends State { @override Widget build(BuildContext c) => const SizedBox(); }`,neg:`class W extends StatefulWidget { + const W({this.width}); + final double? width; + @override _S createState() => _S(); +} +class _S extends State { @override Widget build(BuildContext c) => Padding(padding: const EdgeInsets.all(8), child: const SizedBox()); }`}];function Tt(t,e,n){return{artifactId:t.id,artifactName:t.artifactName,artifactType:t.artifactType,severity:e,message:n}}function hr(t){let e="",n=0;for(;n"&&(n--,n===0))return{inner:t.slice(e+1,i),end:i+1};return null}function by(t,e){const n=new RegExp(`class\\s+${e}\\b[^{]*\\{`).exec(t);if(!n)return null;let i=0;for(let r=n.index+n[0].length-1;rEy(t).usable);function xy(t=""){const e=hr(t);return Sy.filter(n=>n.detect(e)).map(({id:n,severity:i,message:r})=>({id:n,severity:i,message:r}))}function Iy(t){const e=[],n=t.matchAll(/\bFuture\b/g);for(const i of n){let r=i.index+6,s=null;const o=r;for(;ro;if(t[r]==="<"){const u=wy(t,r);if(!u||(s=u.inner.replace(/\s+/g," ").trim(),r=u.end,!/\s/.test(t[r]||"")))continue;for(;rrd(o.functionName)===i);if(r)return r;const s=o=>!o.functionName.startsWith("_");return n.find(s)||n[0]}function Xs(t=""){return Array.from(hr(t).matchAll(/\b(?:class|enum)\s+([A-Za-z_]\w*)/g),e=>e[1])}function ky(t="",e=""){return ql(t,e)?.returnType||null}function sd(t){return String(t||"").replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").toLowerCase()}function Cy(t,e){const n=Xs(e);if(n.length===0)return null;const r=String(t||"").split("/").pop().replace(/\.dart$/,"");if(n.some(l=>sd(l)===r)||n.length>1)return null;const[o]=n,a=`${sd(o)}.dart`;return`File name "${t}" does not match declared class "${o}". FlutterFlow accepts this, but naming the file "${a}" keeps the Code File recognisable in the editor.`}function zl(t){return String(t||"").replace(/([A-Z])/g,"_$1").toLowerCase().replace(/^_/,"")}function Ay(t,e,n=""){const i=ql(e,n)?.functionName;if(!i)return null;const r=String(t||"").split("/").pop(),s=Wl(r,"A");if(s===i)return null;const o=`${zl(i)}.dart`;return`File name "${r}" does not match Action "${i}". FlutterFlow derives the action from the file name, so it looks for "${s}" and reports Action "${s}" declaration not found. Rename the file to "${o}" - FlutterFlow puts an underscore before every capital - or rename the function to "${s}".`}function Py(t="",e=""){return ql(t,e)!==null}function Fy(t,e=new Set){return(t?.match(/[A-Za-z_]\w*/g)||[]).filter(i=>vy.has(i)?!1:!yy.some(s=>i.endsWith(s))||e.has(i))}function Ry(t,{functionName:e="",declaredTypes:n=new Set}={}){const i=ky(t,e),r=Fy(i,n);if(r.length===0)return null;const[s]=r;let o;return n.has(s)?o=`uses Code File type "${s}", which FlutterFlow cannot process as an Action Return Value`:i===s?o="is not a FlutterFlow Action Return Value":o=`uses type "${s}", which is not a FlutterFlow Action Return Value`,`CustomAction return type "${i}" ${o}. Return JSON (Future) or an existing FlutterFlow Data Type (*Struct) instead.`}function Ty(t,e={}){const n=[],i=t.fileName||"",r=t.code||"";if(my.has(t.artifactType)||n.push(Tt(t,"error",`Unsupported artifact type "${t.artifactType}".`)),i.endsWith(".dart")||n.push(Tt(t,"error","FlutterFlow custom code artifacts must use .dart files.")),!r.trim())return n.push(Tt(t,"warning","Generated artifact has no Dart code yet.")),n;if(t.artifactType==="CustomWidget"){/class\s+\w+\s+extends\s+(StatelessWidget|StatefulWidget)/.test(r)||n.push(Tt(t,"warning","CustomWidget code should declare a widget class extending StatelessWidget or StatefulWidget."));for(const s of xy(r))n.push(Tt(t,s.severity,s.message))}if(t.artifactType==="CustomAction"&&!Py(r,t.artifactName)&&n.push(Tt(t,"warning","CustomAction code should expose an async Future function callable from FlutterFlow.")),t.artifactType==="CustomAction"){const s=e.declaredTypes||new Set(Xs(r)),o=Ry(r,{functionName:t.artifactName,declaredTypes:s});o&&n.push(Tt(t,"error",o));const a=Ay(i,r,t.artifactName);a&&n.push(Tt(t,"error",a))}if(t.artifactType==="CustomFunction"&&/class\s+\w+\s+extends\s+(StatelessWidget|StatefulWidget)/.test(r)&&n.push(Tt(t,"warning","CustomFunction should be a callable function, not a widget class.")),t.artifactType==="CustomClass"||t.artifactType==="CodeFile"){const s=Cy(i,r);s&&n.push(Tt(t,"info",s))}return n}function My(t){const e=Array.isArray(t?.artifacts)?t.artifacts:[],n=new Set(e.flatMap(s=>Xs(s.code||""))),i=e.flatMap(s=>Ty(s,{declaredTypes:n})),r=e.map(s=>({artifactId:s.id,fileName:s.fileName,pathHint:id[s.artifactType]||id.CodeFile}));return{valid:i.every(s=>s.severity!=="error"),findings:i,deployHints:r}}const od="// DO NOT REMOVE OR MODIFY THE CODE ABOVE!";function ad(t){return(/^\s*import\s+['"]([^'"]+)['"]/.exec(t)||[])[1]||null}function $y(t=""){const e=t.indexOf(od);return e===-1?t:t.slice(e+od.length).replace(/^\s*\n/,"")}const Ly=/^\s*import\s+['"][^'"]+['"]\s*;\s*(?:\/\/.*)?$/;function Ny(t="",e=""){const n=$y(t),i=new Set((e.match(/^\s*import .*$/gm)||[]).map(ad).filter(Boolean)),r=n.split(` +`).filter(s=>{const o=ad(s);return o===null||!i.has(o)?!0:!Ly.test(s)}).join(` +`).replace(/^\s*\/\/ Automatic FlutterFlow imports\s*$/m,"").replace(/^\s*\n+/,"");return e+r}const Oy=new Set(["flutter","flutter_test","flutter_driver","flutter_localizations","flutter_web_plugins","integration_test","sky_engine"]);function By(t){let e="",n=0;for(;n{const i=n.name||n.package;if(!i||i==="flutter")return e;const r=n.versionRequired||n.required;return e[i]=r&&n.version||"",e},{})}function zy(t){const e=new Map,n=new Map,i=[];for(const r of t)e.has(r.fileName)?i.push(`Duplicate deploy file name "${r.fileName}" for artifacts "${e.get(r.fileName)}" and "${r.artifactId}".`):e.set(r.fileName,r.artifactId),n.has(r.path)?i.push(`Duplicate deploy path "${r.path}" for artifacts "${n.get(r.path)}" and "${r.artifactId}".`):n.set(r.path,r.artifactId);return i}function Vy(t,e={}){const n=Array.isArray(t?.artifacts)?t.artifacts:[],r=(e.selectedArtifactIds||t?.deployOrder||n.map(p=>p.id)).map(p=>n.find(h=>h.id===p)).filter(Boolean),s=[...t?.warnings||[]];let o=[];r.forEach(p=>{const h=qy(p),g=p.fixedCode||p.code||"",m=p.codeType||Hy[p.artifactType]||ot.OTHER;g.trim()||s.push(`${p.artifactName||p.id} has no generated code.`),o.push({artifactId:p.id,artifactName:p.artifactName,artifactType:p.artifactType,fileName:h,content:g,type:m,path:p.deployPath||Wy(h,m),deployPath:p.deployPath||"",deployMode:"customCodeSync"})});const a="lib/flutter_flow/custom_functions.dart",l=o.map((p,h)=>({entry:p,index:h})).filter(({entry:p})=>p.type===ot.FUNCTION&&p.path===a);if(l.length>1){const p=l[0],h={...p.entry,artifactId:l.map(({entry:m})=>m.artifactId).join("+"),artifactName:p.entry.artifactName,content:l.map(({entry:m})=>`// ${m.artifactId} +${m.content}`).join(` + +`)},g=new Set(l.slice(1).map(({index:m})=>m));o=o.filter((m,v)=>!g.has(v)),o[p.index]=h}const u={...ld(t?.dependencies),...r.reduce((p,h)=>({...p,...ld(h.dependencies)}),{})},c={};r.forEach(p=>{Vl(p.fixedCode||p.code||"").forEach(h=>{h in u||(c[h]="")})});const d={...c,...u},f=zy(o);return{bundleId:t?.id||"bundle-current",title:t?.title||"Generated artifact bundle",fileEntries:o,dependencies:d,relationships:t?.relationships||[],warnings:s,errors:f}}function Gy(t){return String(t||"").match(/\bclass\s+([A-Z][A-Za-z0-9_]*)\b/)?.[1]}function Ky(t){return String(t||"").split("/").pop().replace(/\.dart$/,"").split(/[^A-Za-z0-9]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join("")}function Yy(t,e){const i=[Ky(t),Gy(e.content),e.artifactName].find(r=>/^[A-Z][A-Za-z0-9_]*$/.test(String(r||"")));if(!i)throw new Error(`Cannot derive a FlutterFlow custom class name for ${t}.`);return i}function Jy(t,e=new Map){const n=[];for(const[i,r]of t.entries())r.type!=="C"||e.has(r.path)||n.push({artifactId:r.artifactId||i,className:Yy(i,r),content:r.content,fileName:i,path:r.path});return n}function Zy(t,e){const n=new Set(e.map(i=>i.path));return new Map(Array.from(t.entries()).filter(([,i])=>!n.has(i.path)))}const cd={pass:0,warning:1,fail:2},Xy=["manualActions"];function ht(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}function sn(...t){for(const e of t){if(typeof e=="string"&&e.trim())return e.trim();if(Array.isArray(e)&&e.length>0){const n=e.filter(i=>typeof i=="string").join(` +`);if(n)return n}}return""}function $t(t){return t==null?[]:Array.isArray(t)?t:[t]}function Qy(t){const e=ht(t).value??t;if(e==null||typeof e=="string"&&e.trim()==="")return null;const n=Number(e);if(Number.isFinite(n))return ud(n);const i=String(t||"").match(/\bscore\b[^\d]{0,12}(\d{1,3})(?:\s*\/\s*100)?/i);return i?ud(Number(i[1])):null}function ud(t){return t>=0&&t<=100?t:null}function _t(t){return String(t||"").trim().replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function Gl(t){const e=String(t||"").toLowerCase();return/(fail|error|critical|block|reject|invalid)/.test(e)?"fail":/(warn|attention|manual|partial|incomplete|concern)/.test(e)?"warning":/(pass|success|ready|approve|valid|clean|info|notice)/.test(e)?"pass":null}function Xa(...t){return t.filter(Boolean).reduce((e,n)=>cd[n]>cd[e]?n:e,"pass")}function Hh(t,e="warning",n="review"){if(typeof t=="string")return{severity:e,message:t,suggestion:"",source:n};const i=ht(t),r=sn(i.message,i.title,i.issue,i.description,i.summary);return r?{severity:Gl(i.severity||i.status||i.level)||e,message:r,suggestion:sn(i.suggestion,i.fix,i.recommendation,i.action),source:i.source||n}:null}function Qa(t,e="review"){const n=ht(t);return[["findings","warning"],["issues","warning"],["criticalIssues","fail"],["errors","fail"],["warnings","warning"],["recommendations","warning"],["requiredFixes","fail"],["suggestions","warning"]].flatMap(([r,s])=>$t(n[r]).map(o=>Hh(o,s,e)).filter(Boolean))}function e_(t,e,n=null){if(typeof t=="string")return{id:`${n||"bundle"}-manual-${e+1}`,title:t,detail:"",location:"",timing:"unspecified",artifactId:n,source:"Code Review"};const i=ht(t),r=sn(i.title,i.action,i.step,i.message,i.name,i.description);return r?{id:i.id||`${n||"bundle"}-manual-${e+1}`,title:r,detail:sn(i.detail,i.instructions,i.description),location:sn(i.location,i.flutterFlowPath,i.path),timing:sn(i.timing,i.phase)||"unspecified",artifactId:n,source:sn(i.source)||"Code Review"}:null}function el(t,e=null){const n=ht(t);return Xy.flatMap(i=>$t(n[i])).map((i,r)=>e_(i,r,e)).filter(Boolean)}function t_(t){let e=typeof t=="string"?Ja(t):t;if(!e&&typeof t=="string")return{rawText:t,root:{}};const n=ht(e);typeof n.content=="string"&&(e=Ja(n.content)||e);const i=ht(e),r=ht(i.reviewResult||i.codeReview||i.result);return{rawText:"",root:Object.keys(r).length?r:i}}function n_(t,e){const n=[e.id,e.fileName,e.artifactName].map(_t);return t.find(i=>{const r=ht(i);return[r.id,r.fileName,r.artifactName,r.name].map(_t).some(s=>s&&n.includes(s))})||null}function i_(t,e){return $t(t?.metadata?.compatibility?.deployHints).find(r=>_t(r?.artifactId)===_t(e.id)||_t(r?.fileName)===_t(e.fileName))?.pathHint||""}function r_(t,e){return $t(t?.relationships).filter(n=>_t(n?.from)===_t(e.id)||_t(n?.to)===_t(e.id))}function s_(t,e){return $t(t?.metadata?.compatibility?.findings).filter(n=>!n?.artifactId||_t(n.artifactId)===_t(e.id)).map(n=>Hh(n,"warning","Compatibility check")).filter(Boolean)}function o_(t,e,n,i){const r=n_(e,n),s=ht(r?.review||r||n.review),o=Object.keys(s).length>0,a=[...Qa(s),...s_(t,n)],l=el(s,n.id),u=Gl(s.status||s.verdict||s.outcome||s.result),c=a.length?Xa(...a.map(f=>f.severity)):null,d=Xa(u,c,o?null:"warning");return{...n,index:i,status:d,statusReason:o?sn(s.summary,s.overview,s.assessment,s.conclusion)||(a.length?`${a.length} review finding${a.length===1?"":"s"}`:"No file-level findings"):"No file-level verdict was returned",reviewComplete:o,findings:a,manualSteps:l,fixedSource:typeof s.fixedSource=="string"&&s.fixedSource.trim()?s.fixedSource.trim():null,pathHint:i_(t,n),relationships:r_(t,n)}}function a_({status:t,score:e,artifactPresentations:n,manualSteps:i}){const r=n.length;if(r===0&&i.length===0)return e==null?"Code review returned no overall summary and no score.":`Reviewed bundle with score ${e}/100.`;const s=n.reduce((a,l)=>(a[l.status]+=1,a),{pass:0,warning:0,fail:0}),o=[];return t&&o.push(`Overall verdict: ${t}.`),r&&o.push(`${r} artifact${r===1?"":"s"}: ${s.pass} pass, ${s.warning} warn, ${s.fail} fail.`),i.length&&o.push(`Do before deploy: ${i.map(a=>a.title).join("; ")}.`),e==null&&o.push("No numeric score (0-100) was returned."),o.join(" ")}function l_({bundle:t,reviewResult:e}){const n=ht(t),i=$t(n.artifacts),{root:r,rawText:s}=t_(e),o=[r.bundleReview,r.overallReview,r.overall,r.bundleSummary,r.summaryReview,r.review].map(ht).find(E=>Object.keys(E).length)||{},a=$t(r.artifacts||r.files||r.reviews),l=i.map((E,y)=>o_(n,a,E,y)),u=Qa(r),d=[...Qa(o),...u],f=[...el(o),...el(r),...l.flatMap(E=>E.manualSteps)].filter((E,y,b)=>b.findIndex(I=>I.title===E.title&&I.artifactId===E.artifactId)===y),p=Gl(o.status||o.verdict||o.overallStatus||r.status||r.verdict||r.overallStatus||r.outcome),h=Xa(p,...d.map(E=>E.severity),...l.map(E=>E.status)),g=o.score??r.score??r.overallScore??s,m=Qy(g),v=sn(o.headline,o.summary,o.executiveSummary,o.overview,o.assessment,o.conclusion,r.overallSummary,r.headline,r.summary,r.executiveSummary,r.overview,r.assessment,r.conclusion,s)||a_({status:h,score:m,artifactPresentations:l,manualSteps:f}),x=l.reduce((E,y)=>(E[y.status]+=1,E),{pass:0,warning:0,fail:0});return{title:n.title||"Generated artifact bundle",description:n.description||"",status:h,score:m,summary:v,findings:d,manualSteps:f,artifacts:l,counts:x,reviewCoverage:{reviewed:l.filter(E=>E.reviewComplete).length,total:l.length},deployOrder:$t(n.deployOrder),relationships:$t(n.relationships),warnings:$t(n.warnings),compatibility:ht(n.metadata?.compatibility)}}const c_=/^\uFEFF/;function ji(t){let e=0,n=t.length;for(;ee&&!t[n-1].trim();)n--;return t.slice(e,n).join(` +`)}function u_(t){const e=String(t??"").replace(c_,"");if(!e.trim())return"";const n=e.split(` +`),i=c=>{const d=c.trim();return/^`{3,}[A-Za-z0-9+#_.-]*$/.test(d)?c.length-c.trimStart().length:-1};let r=0,s=-1;const o=[];{let c=0;for(let d=0;d=0&&(r++,s<0&&(s=d),o.push(c+f)),c+=n[d].length+1}}if(r===0)return ji(n);{const c=tl(e);if(!c.error&&o.every(f=>fd(f,c.commentAndStringRanges)))return ji(n)}if(r===1){const c=ji(n.slice(0,s)),d=ji(n.slice(s+1));return d.length>=c.length?d:c}const a=[];let l=null;for(let c=0;cc.length>0);return u.length===0?"":u.join(` + +`)}function d_(t){return String(t??"").replace(/\/\*[\s\S]*?\*\//g," ").replace(/\/\/[^\n]*/g,"").replace(/'''[\s\S]*?'''/g,'""').replace(/"""[\s\S]*?"""/g,'""').replace(/'(?:\\.|[^'\\\n])*'/g,'""').replace(/"(?:\\.|[^"\\\n])*"/g,'""')}function Wh(t){const e=d_(t);return Array.from(e.matchAll(/class\s+([A-Z]\w*)\s+extends\s+[A-Za-z_]\w*Widget\b/g),n=>n[1])}function qh(t){return`${zl(t)}.dart`}function f_(t){return Wl(t,"W")}const dd={"(":")","[":"]","{":"}"},h_={")":"(","]":"[","}":"{"},p_=/[A-Za-z0-9_]/;function tl(t){const e=[{kind:"code",opener:null,openedLine:0}],n=[];let i=1,r=0;const s=(c,d)=>{(c===` +`||c==="\r"&&d!==` +`)&&i++};let o=null;const a=()=>{for(const c of e)(c.kind==="string"||c.kind==="block-comment"||c.kind==="line-comment")&&n.push({start:c.startIndex,end:t.length})};for(;r0?t[r-1]:"",h=r>1?t[r-2]:"",g=(p==="r"||p==="R")&&!p_.test(h);e.push({kind:"string",quote:c,triple:f,raw:g,startIndex:r,openedLine:i}),r+=f?3:1;continue}if(dd[c]){e.push({kind:"code",opener:c,openedLine:i}),r++;continue}if(h_[c]){if(d.interpolation&&c==="}"){e.pop(),r++;continue}if(d.opener&&dd[d.opener]===c){e.pop(),r++;continue}return d.opener?(a(),{error:o??`line ${i}: "${c}" closes nothing - "${d.opener}" opened on line ${d.openedLine} is still open`,commentAndStringRanges:n}):(a(),{error:o??`line ${i}: unexpected "${c}" with no matching opener`,commentAndStringRanges:n})}s(c,t[r+1]),r++}a();let l=e.length-1;for(;l>0&&e[l].kind==="line-comment";)l--;let u=o;if(!u){const c=e[l];if(!(c.kind==="code"&&!c.opener&&!c.interpolation))if(c.kind==="string")u=`unclosed ${c.triple?"triple-quoted ":""}string starting on line ${c.openedLine} was never closed`;else if(c.kind==="block-comment")u=`unterminated /* comment starting on line ${c.openedLine}`;else if(c.interpolation){const d=e.findLast(p=>p.opener);u=`unclosed "\${" expression${d?` opened on line ${d.openedLine}`:""} was never closed`}else u=`"${c.opener}" opened on line ${c.openedLine} is never closed`}return{error:u,commentAndStringRanges:n}}function g_(t){return tl(String(t??"")).error}function fd(t,e){return e.some(({start:n,end:i})=>t>=n&&ttypeof n=="string"?n:n?.errorMessage).filter(Boolean);return e.length>0?e.join("; "):JSON.stringify(t)}return t&&typeof t=="object"?t.errorMessage||JSON.stringify(t):String(t??"")}const m_=["gmail.com","googlemail.com","outlook.com","hotmail.com","live.com","msn.com"],v_="MAGIC_LINK_SENT",y_="PLUS_ALIAS_REJECTED",__="Please enter your primary email address. Plus aliases (such as {email}) are not allowed for {domain} accounts.",Qs={allowlistedDomains:m_,successCode:v_,validationCode:y_,messageTemplate:__},w_=new Set(Qs.allowlistedDomains),b_=Qs.successCode,E_=Qs.validationCode;function eo(t){return typeof t=="string"?t.trim():""}function S_(t){const e=eo(t),n=e.lastIndexOf("@");if(n<=0||n===e.length-1)return!1;const i=e.slice(0,n),r=e.slice(n+1).toLowerCase();return w_.has(r)?i.includes("+"):!1}function x_(t,e){return Qs.messageTemplate.replaceAll("{email}",t).replaceAll("{domain}",e)}function zh(t){if(!S_(t))return null;const e=eo(t),n=e.lastIndexOf("@"),i=e.slice(n+1).toLowerCase();return x_(e,i)}function Yl(t){return!t||typeof t!="object"||Array.isArray(t)||t.success===!1||t.error?!1:t.code?t.code===b_:t.success===!0||typeof t.message=="string"}function Vh(t,e){return t?.code===E_?t.message||zh(e)||"Please enter your primary email address.":Yl(t)?`Check your email — we sent a link to ${eo(e)}`:t?.message||"Something went wrong. Please try again."}const I_="ccc_auth_session",k_="ccc_subscription",C_=Object.freeze(["hasSeenWalkthrough"]);function A_(t){const e=[];for(const n of C_)t.getItem(n)!==null&&(t.removeItem(n),e.push(n));return e}function P_(){return[I_,k_]}function F_({storage:t,onIdentityChanged:e,onPlanChanged:n}){for(const i of P_())t.removeItem(i);typeof e=="function"&&e(),typeof n=="function"&&n()}function R_(t){const e=t?.message||t?.error;return typeof e=="string"&&e.trim()?e.trim():"The server could not send the link."}function T_({sendLink:t,getEmail:e,onState:n}){let i=!1;return async function(){if(i)return{status:"busy"};i=!0;let s;try{n({status:"pending",error:null});const o=await t(e());if(!Yl(o))throw new Error(R_(o));return s={status:"sent",data:o},n({status:"sent",data:o}),s}catch(o){return s={status:"error",error:o},n({status:"error",error:o}),s}finally{i=!1}}}const M_=/^dependencies\s*:\s*(?:#.*)?$/,$_=/^(?:"([^"]+)"|'([^']+)'|([A-Za-z_][A-Za-z0-9_-]*))\s*:/;function Er(t){const e=t.match($_);return e?e[1]??e[2]??e[3]:null}function Sr(t){const e=t.trim();return e===""||e.startsWith("#")}function In(t){const e=t.match(/^(\s*)/);return e?e[1].length:0}function Jl(t,e){const n=t.findIndex(s=>e.test(s));if(n===-1)return null;let i=n,r=null;for(let s=n+1;sc&&/\s/.test(s[d-1]);)d-=1}return t[r]=s.slice(0,c)+Xl(n)+s.slice(d),!0}return!1}function hd(t,e,n){if(n&&typeof n=="object"&&n.sdk)return[`${t}${e}:`,`${t} sdk: ${n.sdk}`];const i=String(n||"").trim();return[`${t}${e}: ${i?Xl(i):">=0.0.0"}`]}function B_(t,e={}){const n=String(t||""),i=Object.entries(e).filter(([u])=>u&&u!=="flutter");if(i.length===0)return{yaml:n,added:[],alreadyPresent:[]};const r=n.split(` +`),s=new Set(Xh(n)),o=[],a=[];for(const[u,c]of i)s.has(u)?a.push(u):(o.push([u,c]),s.add(u));if(o.length===0)return{yaml:n,added:[],alreadyPresent:a};const l=Zl(r);if(l){const u=o.flatMap(([c,d])=>hd(l.childIndent,c,d));r.splice(l.endIndex,0,...u)}else r.length>0&&r[r.length-1].trim()!==""&&r.push(""),r.push("dependencies:"),o.forEach(([u,c])=>{r.push(...hd(" ",u,c))});return{yaml:r.join(` +`),added:o.map(([u])=>u),alreadyPresent:a}}function D_(t,e={}){const n=String(t||""),i=Object.entries(e).filter(([l])=>l&&l!=="flutter");if(i.length===0)return{yaml:n,overridden:[],skipped:[]};const r=n.split(` +`),s=to(n),o=[],a=[];for(const[l,u]of i){const c=s.get(l),d=c&&!c.isScalar&&c.sourceKey===null&&c.version!==null;if(!c||!c.isScalar&&!d||!String(u||"").trim()){a.push(l);continue}if(d){O_(r,c,String(u).trim())?o.push({name:l,from:c.version,to:u}):a.push(l);continue}const f=" ".repeat(In(r[c.lineIndex]));r[c.lineIndex]=`${f}${l}: ${Xl(String(u).trim())}${c.comment}`,o.push({name:l,from:c.constraint,to:u})}return{yaml:r.join(` +`),overridden:o,skipped:a}}function ep(t){const e=String(t||""),n=[];return e.trim()?(/^name:\s*\S+/m.test(e)||n.push("pubspec.yaml missing name field"),Zl(e.split(` +`))||n.push("pubspec.yaml missing dependencies section"),Xh(e).includes("flutter")||n.push("pubspec.yaml missing Flutter SDK dependency"),{valid:n.length===0,errors:n}):(n.push("pubspec.yaml is empty"),{valid:!1,errors:n})}const j_=">=3.0.0 <4.0.0";function nl(t){const e=String(t||"").trim(),n=e[0];return n!=="'"&&n!=='"'||e[e.length-1]!==n?e:e.slice(1,-1).replaceAll(`${n}${n}`,n)}function U_(t=""){const e=Uh(t).filter(n=>!n.startsWith("dart:")&&!n.startsWith("package:"));return{selfContained:e.length===0,unresolvableImports:e}}function pd(t,e,n){const i=[];for(const[r,s]of t){if(s.isScalar){e[r]=nl(s.constraint);continue}if(s.sourceKey==="sdk"){n.add(r);continue}if(s.sourceKey===null&&s.version){e[r]=nl(s.version);continue}i.push(r)}return i}function H_(t){const e=new Set,n=new Set,i={},r={},s=pd(to(t),i,e),o=pd(L_(t,"dependency_overrides"),r,n),a=[...s,...o],l=new Set([...Object.keys(i),...e]),{sdk:u}=Qh(t);return{sdkConstraint:nl(u)||j_,dependencies:i,dependencyOverrides:r,sdkPackages:[...e].sort(),sdkOverrides:[...n].sort(),availablePackages:l,unrepresentable:a,unrepresentableOverrides:o}}function W_(t,e,n){return e.length>0?`${t} imports ${e.join(", ")}, which FlutterFlow only generates once the app is built, so it could not be compiled before the deploy.`:`${t} imports ${n.join(", ")}, which your project's pubspec.yaml does not declare with a version constraint, so it could not be compiled before the deploy.`}function q_(t,e){const{sdkConstraint:n,dependencies:i,dependencyOverrides:r,sdkPackages:s,sdkOverrides:o,availablePackages:a,unrepresentable:l,unrepresentableOverrides:u}=H_(e),c={sdkConstraint:n,dependencies:i,dependencyOverrides:r,sdkPackages:s,sdkOverrides:o},d=[],f=[],p=[];for(const h of t){const{className:g,content:m}=h,v=Vl(m),x=Uh(m).some(b=>b.startsWith("package:"));if(l.length>0&&x){const b=v.filter(T=>l.includes(T));let I;if(b.length>0)I=`${g} was not compiled before deploying: it imports or exports ${b.join(", ")}, which your project declares from a source that cannot be reproduced outside it, so package resolution could not be matched exactly.`;else{const T=l.filter(C=>!u.includes(C)),S=[T.length>0?`your project's pubspec.yaml declares ${T.join(", ")} from a source that cannot be reproduced outside it`:null,u.length>0?`your project's dependency_overrides redirects ${u.join(", ")} to a source that cannot be reproduced outside it`:null].filter(Boolean).join(", and ");I=`${g} was not compiled before deploying: ${S}, and an entry like that can change what every package depending on it resolves to - including packages this class reaches transitively - so package resolution could not be matched exactly.`}f.push({className:g,reason:I});continue}const{unresolvableImports:E}=U_(m),y=v.filter(b=>!a.has(b));if(E.length>0||y.length>0){f.push({className:g,reason:W_(g,E,y)});continue}d.push({fileName:`${zl(g)}.dart`,content:m})}return{manifest:c,sources:d,skipped:f,approximate:p}}function gd(t,e){const n=`${t}${e}`.split(` +`),i=n.pop()??"",r=[];for(const s of n){const o=tp(s);o&&r.push(o)}return{events:r,buffer:i}}function z_(t){const e=tp(t);return e?[e]:[]}function tp(t){const e=t.trim();if(!e)return null;try{const n=JSON.parse(e);return n&&typeof n=="object"&&!Array.isArray(n)?n:null}catch{return null}}const Oe=Object.freeze({COMMITTED:"committed",PARTIAL:"partial",FAILED:"failed",UNCONFIRMED:"unconfirmed"}),np=12e4,ip=1e4;function rp(t){return t?.unconfirmed===!0||t?.outcome===Oe.UNCONFIRMED?Oe.UNCONFIRMED:t?.partial===!0||t?.outcome===Oe.PARTIAL?Oe.PARTIAL:t?.success===!0?Oe.COMMITTED:Oe.FAILED}class at extends Error{constructor(e){super(e),this.name="UnconfirmedDeployError",this.outcome=Oe.UNCONFIRMED}}function md({httpStatus:t}={}){return new at(`Every FlutterFlow sync endpoint lost its response or ended in a server error${t?` (last: HTTP ${t})`:""} — neither can prove the push was refused, so it may already have been applied. Open the FlutterFlow project to reconcile before retrying.`)}async function V_(t,e={}){const{onPhase:n,onLog:i}=e;let r=null,s=null,o="";const a=u=>{if(u.event==="phase"){u.phase&&(s=u.phase),u.message&&n&&n(u.message);return}if(u.event==="log"){u.message&&i&&i(u.message);return}if(u.event==="result"){r=u;return}u.event===void 0&&typeof u.success=="boolean"&&(r=u)};let l=null;try{if(t.body?.getReader){const u=t.body.getReader(),c=new TextDecoder;for(;;){const{done:d,value:f}=await u.read();if(d)break;const p=gd(o,c.decode(f,{stream:!0}));o=p.buffer,p.events.forEach(a)}}else{const u=gd("",await t.text());o=u.buffer,u.events.forEach(a)}}catch(u){l=u}return z_(o).forEach(a),r?{...r,success:r.success===!0||r.success===void 0&&t.ok,finalResultReceived:!0,runnerPhase:s,httpStatus:t.status}:{success:!1,finalResultReceived:!1,httpRejected:!t.ok,httpStatus:t.status,runnerPhase:s,error:t.ok?l?"The connection to the FlutterFlow deploy runner dropped before it reported a result.":"The FlutterFlow deploy runner closed the connection before it finished.":`FlutterFlow custom class provisioning failed (HTTP ${t.status}).`}}const G_=new Set(["connected","workspace_init","workspace_ready","verifying"]);function sp(t){return t?.preWrite===!0||Array.isArray(t?.analyzerErrors)&&t.analyzerErrors.length>0?!0:typeof t?.runnerPhase=="string"?G_.has(t.runnerPhase):typeof t?.httpStatus=="number"?t.httpStatus>=400&&t.httpStatus<500:!1}function vd(t){if(t?.finalResultReceived){const e=rp(t);return e===Oe.FAILED&&!sp(t)?Oe.UNCONFIRMED:e}return t?.httpRejected&&typeof t.httpStatus=="number"&&t.httpStatus>=400&&t.httpStatus<500?Oe.FAILED:Oe.UNCONFIRMED}function K_(){let t=document.getElementById("fx-grid");if(!t)return null;const e=window.matchMedia("(prefers-reduced-motion: reduce)"),n=window.matchMedia("(pointer: none)");let i=t.getContext("webgl2",{alpha:!0,antialias:!1,depth:!1,stencil:!1,premultipliedAlpha:!0,powerPreference:"low-power"}),r=i?null:t.getContext("2d");if(!i&&!r)return null;const s='',o=`#version 300 es +in vec2 p; void main(){ gl_Position = vec4(p, 0.0, 1.0); }`;function a(){return["#version 300 es","precision highp float;","out vec4 o;","uniform vec2 res;","uniform vec2 design;","uniform vec2 mouse;","uniform float energy;","uniform float parallax;","uniform float t;","uniform vec3 ink;","uniform sampler2D mark;","uniform vec2 rot;","const float WARP_A = 0.0032;","void main(){"," vec2 px = gl_FragCoord.xy * (design / res);"," vec2 p = vec2(px.x, design.y - px.y);"," vec2 off = vec2(0.0, -parallax) + vec2(sin(t * 0.11), cos(t * 0.09)) * 7.0;"," vec2 g = p + off;"," vec2 gm = mouse + off;"," float base = min(design.x, design.y);"," float spacing = clamp(base / 10.0, 64.0, 118.0);"," vec2 rel = g - gm;"," float rho = length(rel) + 1e-5;"," vec2 dir = rel / rho;"," vec2 pw = gm + dir * (rho + WARP_A * rho * rho);"," vec2 cell = floor(pw / spacing);"," vec2 cw = (cell + 0.5) * spacing - gm;"," float Rc = length(cw) + 1e-5;"," float rhoC = (-1.0 + sqrt(1.0 + 4.0 * WARP_A * Rc)) / (2.0 * WARP_A);"," vec2 c = gm + (cw / Rc) * rhoC;"," float cellSize = spacing / (1.0 + 2.0 * WARP_A * rhoC);"," float sigma = spacing * 2.9;"," float f = exp(-(rhoC * rhoC) / (2.0 * sigma * sigma));"," float scale = mix(0.32, 1.42, f);"," float weight = smoothstep(0.06, 0.80, f);"," float hs = cellSize * 0.26 * scale;"," vec2 uv = (g - c) / hs;"," vec2 ruv = mat2(rot.x, rot.y, -rot.y, rot.x) * uv;"," float cov = 0.0;"," if (abs(ruv.x) <= 1.0 && abs(ruv.y) <= 1.0) cov = texture(mark, ruv * 0.5 + 0.5).a;"," float s = cov * weight * energy * 0.26;"," o = vec4(ink * s, s);","}"].join(` +`)}let l=null,u,c,d,f,p,h,g,m,v;function x(V,z){if(!i)return null;const D=i.createShader(V);return i.shaderSource(D,z),i.compileShader(D),i.getShaderParameter(D,i.COMPILE_STATUS)?D:(window.console&&console.warn("fx-grid shader: "+i.getShaderInfoLog(D)),null)}if(i){const V=x(i.VERTEX_SHADER,o),z=x(i.FRAGMENT_SHADER,a());if(V&&z&&(l=i.createProgram(),i.attachShader(l,V),i.attachShader(l,z),i.linkProgram(l),i.getProgramParameter(l,i.LINK_STATUS)||(window.console&&console.warn("fx-grid link: "+i.getProgramInfoLog(l)),l=null)),l){i.useProgram(l),i.bindBuffer(i.ARRAY_BUFFER,i.createBuffer()),i.bufferData(i.ARRAY_BUFFER,new Float32Array([-1,-1,3,-1,-1,3]),i.STATIC_DRAW);const D=i.getAttribLocation(l,"p");i.enableVertexAttribArray(D),i.vertexAttribPointer(D,2,i.FLOAT,!1,0,0),u=i.getUniformLocation(l,"res"),c=i.getUniformLocation(l,"design"),d=i.getUniformLocation(l,"mouse"),f=i.getUniformLocation(l,"energy"),p=i.getUniformLocation(l,"parallax"),h=i.getUniformLocation(l,"t"),g=i.getUniformLocation(l,"ink"),m=i.getUniformLocation(l,"mark"),v=i.getUniformLocation(l,"rot"),i.enable(i.BLEND),i.blendFunc(i.ONE,i.ONE_MINUS_SRC_ALPHA),i.clearColor(0,0,0,0)}else{i=null;const D=t.cloneNode(!1);if(t.parentNode.replaceChild(D,t),t=D,r=t.getContext("2d"),!r)return null}}function E(V){if(!V)return null;const z=/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(V);if(z){let D=z[1];return D.length===3&&(D=D[0]+D[0]+D[1]+D[1]+D[2]+D[2]),[parseInt(D.slice(0,2),16)/255,parseInt(D.slice(2,4),16)/255,parseInt(D.slice(4,6),16)/255]}try{const D=document.createElement("canvas");D.width=1,D.height=1;const ge=D.getContext("2d");ge.fillStyle="rgb(9, 8, 7)";const Pe=String(ge.fillStyle);ge.fillStyle=V;const $e=String(ge.fillStyle);if($e===Pe)return null;const Et=/^#([0-9a-f]{6})$/i.exec($e);if(Et){const St=Et[1];return[parseInt(St.slice(0,2),16)/255,parseInt(St.slice(2,4),16)/255,parseInt(St.slice(4,6),16)/255]}const Vt=/rgba?\(\s*([\d.]+)[,\s]+([\d.]+)[,\s]+([\d.]+)/i.exec($e);if(Vt)return[Number(Vt[1])/255,Number(Vt[2])/255,Number(Vt[3])/255]}catch{}return null}function y(){let V="";try{const z=getComputedStyle(document.documentElement);V=(z.getPropertyValue("--fx-ink")||"").trim()||(z.getPropertyValue("--fg")||"").trim()}catch{}return E(V)||[.56,.68,.88]}const b=y();let I=1920,T=1080,S=960,C=540,R=960,O=540,L=.66,N=0,J=-1e9,G=!1,M=0,K=0,ie=null,ue=!1,we=!1,be=!1;const Re=64,Q=15.2;let de=0,pe=0;const Ne=.0032,pt=0,re=.56,We=.26,Je=.32,Pt=.16,$=.349;let ee=pt;function Be(){const V=t.getBoundingClientRect(),z=t.clientWidth,D=t.clientHeight;if(!V.width||!z||!D)return;const ge=Math.min(window.devicePixelRatio||1,2),Pe=Math.max(.2,Math.min(2,V.width/z*ge)),$e=Math.max(2,Math.round(z*Pe)),Et=Math.max(2,Math.round(D*Pe));($e!==t.width||Et!==t.height)&&(t.width=$e,t.height=Et,i&&i.viewport(0,0,$e,Et)),I=z,T=D,G||(S=R=I/2,C=O=T/2,G=!0)}function Ze(V){!l||!ue||!i||(i.uniform2f(u,t.width,t.height),i.uniform2f(c,I,T),i.uniform2f(d,S,C),i.uniform1f(f,L),i.uniform1f(p,N),i.uniform2f(v,Math.cos(ee),Math.sin(ee)),i.uniform1f(h,V),i.uniform3f(g,b[0],b[1],b[2]),i.clear(i.COLOR_BUFFER_BIT),i.drawArrays(i.TRIANGLES,0,3))}function Te(V,z,D){const ge=Math.max(0,Math.min(1,(D-V)/(z-V)));return ge*ge*(3-2*ge)}function qt(V){if(!ie||!r)return;const z=r;z.setTransform(1,0,0,1,0,0),z.clearRect(0,0,t.width,t.height);const D=t.width/I;z.setTransform(D,0,0,D,0,0),z.globalAlpha=1;const ge=Math.min(I,T),Pe=Math.max(64,Math.min(118,ge/10)),$e=Pe*2.9,Et=2*$e*$e,Vt=Math.sin(V*.11)*7,St=Math.cos(V*.09)*7-N,Rr=S+Vt,Tr=C+St,xo=$e*Math.sqrt(2*Math.log(1/.06)),Pi=xo+Ne*xo*xo+Pe,vg=Math.floor((Rr-Pi)/Pe)-1,yg=Math.ceil((Rr+Pi)/Pe)+1,_g=Math.floor((Tr-Pi)/Pe)-1,wg=Math.ceil((Tr+Pi)/Pe)+1;for(let Io=_g;Io<=wg;Io++){const bg=(Io+.5)*Pe;for(let ko=vg;ko<=yg;ko++){const Co=(ko+.5)*Pe-Rr,Ao=bg-Tr,Po=Math.sqrt(Co*Co+Ao*Ao)+1e-5;if(Po>Pi)continue;const Mr=(-1+Math.sqrt(1+4*Ne*Po))/(2*Ne),Oc=Math.exp(-(Mr*Mr)/Et),Bc=Te(.06,.8,Oc)*L*.26;if(Bc<.004)continue;const yn=Pe/(1+2*Ne*Mr)*.26*(.32+1.1*Oc),Dc=Mr/Po,Fo=Rr+Co*Dc,Ro=Tr+Ao*Dc;Fo<-yn*1.6||Fo>I+yn*1.6||Ro<-yn*1.6||Ro>T+yn*1.6||(z.globalAlpha=Bc,z.save(),z.translate(Fo,Ro),z.rotate(ee),z.drawImage(ie,-yn,-yn,yn*2,yn*2),z.restore())}}z.globalAlpha=1}function gt(V){if(!we)return;const z=K?Math.min(.05,(V-K)/1e3):.016;K=V;const ge=V-J>2400?.6:1;L+=(ge-L)*Math.min(1,z*3.2);const Pe=Math.min(.05,z);de+=((R-S)*Re-de*Q)*Pe,pe+=((O-C)*Re-pe*Q)*Pe,S+=de*Pe,C+=pe*Pe,N=(window.scrollY||window.pageYOffset||0)*.55;const $e=V/1e3,Et=S/(I||1)-.5,Vt=C/(T||1)-.5;let St=Et*(Et>=0?re:We)+Vt*(Vt>=0?Je:Pt);St>$?St=$:St<-$&&(St=-$),ee=pt+St-N*6e-4,Be(),i?Ze($e):qt($e),M=requestAnimationFrame(gt)}function rt(V){if(!we)return;const z=t.getBoundingClientRect();!z.width||!I||!T||(R=(V.clientX-z.left)/z.width*I,O=(V.clientY-z.top)/z.height*T,J=performance.now())}function mt(){we||So||e.matches||n.matches||!be||document.hidden||(we=!0,K=0,M=requestAnimationFrame(gt))}function zt(){we=!1,M&&(cancelAnimationFrame(M),M=0),K=0}function Ai(){e.matches?(zt(),t.classList.remove("is-ready")):be&&mt()}function Zn(){n.matches?zt():be&&mt()}function $c(){document.hidden?zt():be&&mt()}const Lc=new IntersectionObserver(V=>{be=V[0]?.isIntersecting||!1,be?mt():zt()},{threshold:0});Lc.observe(t),window.addEventListener("pointermove",rt,{passive:!0,capture:!0}),window.addEventListener("resize",Be),e.addEventListener("change",Ai),n.addEventListener("change",Zn),document.addEventListener("visibilitychange",$c);function mg(){const V=(s.match(/\sd="([^"]+)"/)||[])[1],z=document.createElement("canvas");z.width=256,z.height=256;const D=z.getContext("2d");if(V&&window.Path2D){const ge=Math.min(8.533333333333333,8.421052631578947);D.setTransform(ge,0,0,ge,ge+(256-30*ge)/2,-6.4*ge),D.fillStyle="rgb(255,255,255)",D.fill(new Path2D(V),"evenodd"),D.setTransform(1,0,0,1,0,0)}try{const ge=D.getImageData(0,0,256,256),Pe=ge.data;for(let $e=3;$e{V.persisted?zt():Nc()}),window.addEventListener("pageshow",V=>{V.persisted&&mt()}),{dispose:Nc,isRunning:()=>we}}const Y_=120;function J_(t,e,n){return tn?n:t}function me(t,e,n){return J_((t-e)/(n-e),0,1)}function Z_(t){return t<.5?2*t*t:1-Math.pow(-2*t+2,2)/2}function la(t){return 1-Math.pow(1-t,3)}function Xe(t,e){return e=e===void 0?1.7:e,1+(e+1)*Math.pow(t-1,3)+e*Math.pow(t-1,2)}function yd(t){return 1-Math.pow(2,-9*t)*Math.cos(t*15)}function se(t,e){if(t<=e[0].t)return e[0].v;for(let n=1;n8.2&&y<9.4&&(s*=1-.07*Math.sin(me(y,8.2,9.4)*Math.PI))}else if(t<53){const y=t-42;g=se(y,[{t:0,v:1},{t:2,v:0},{t:4.2,v:0},{t:4.6,v:1},{t:6.8,v:1},{t:7.4,v:0},{t:9.4,v:0},{t:10.6,v:1}]),h=se(y,[{t:0,v:1},{t:2,v:.3},{t:4.6,v:1,e:Xe}]),d=se(y,[{t:0,v:0},{t:2,v:.3},{t:4.6,v:.16,e:Xe},{t:10.6,v:0}]),p=se(y,[{t:0,v:0},{t:2,v:-40},{t:4.6,v:0,e:Xe}]),o=se(y,[{t:0,v:0},{t:4.6,v:-.12},{t:10.6,v:0}])}else if(t<60){const y=t-53;c=se(y,[{t:0,v:1},{t:.35,v:0},{t:.45,v:0},{t:.7,v:1}]);const b=me(y,.45,2.2);a=b>0?-2.6*(1-yd(b)):0,g=se(y,[{t:0,v:1},{t:.57,v:0},{t:.67,v:0},{t:.92,v:1}]);const I=me(y,.67,2.42);f=I>0?-2.6*(1-yd(I)):0,s=1-.05*(Math.sin(me(y,1.9,2.5)*Math.PI)+Math.sin(me(y,2.5,3.1)*Math.PI))}else if(t<74){let b=function(C){return[se(C,[{t:0,v:0},{t:.25,v:1},{t:.5,v:1},{t:.72,v:.14},{t:.82,v:.14},{t:1,v:0}]),se(C,[{t:0,v:0},{t:.08,v:-.62},{t:.25,v:-.62},{t:.33,v:.62},{t:.7,v:.62},{t:.82,v:-.62},{t:1,v:-.62}])]};var E=b;const y=t-60,I=1-me(y,12,14),T=b(me(y,0,12)),S=b(me(y-.5,0,12));n=T[0]*I,i=(T[1]+.05*Math.sin(y*7))*I,o=(S[0]-T[0])*.6*I,a=(S[1]-T[1])*.6*I,p=(S[0]-T[0])*30*I,x=me(y,0,.4)*I}else if(t<85.4){const y=t-74,b=se(y,[{t:0,v:0},{t:4,v:1},{t:8,v:.24},{t:9.6,v:1,e:Xe},{t:11.4,v:0}]);o=b*.5,d=-b*.5,l=se(y,[{t:0,v:0},{t:4,v:6},{t:8,v:20},{t:9.6,v:38,e:Xe},{t:11.4,v:0}]),p=-l*.7,a=se(y,[{t:0,v:0},{t:8,v:0},{t:9.6,v:.4},{t:11.4,v:0}])}else if(t<96.4){const y=t-85.4,b=me(y,0,5.6),I=me(y,5.6,7.6),T=.72*Math.min(1,y/.6)*(1-I);d=Math.cos(b*Math.PI*2)*T,f=Math.sin(b*Math.PI*2)*T*.55,p=b*360*(1-I);const S=se(y,[{t:0,v:0},{t:7.6,v:0},{t:8.2,v:1,e:la},{t:8.6,v:.55},{t:9.4,v:0}]);o=-.16*S,d+=.16*S,l=-6*S,p+=6*S,s=1+.05*S,m=1+.9*S}else if(t<108.6){const y=t-96.4,b=me(y,9.6,12.2);n=se(y,[{t:0,v:0},{t:2.1,v:1},{t:4.8,v:.08},{t:7.5,v:1},{t:9.6,v:0}])*(1-b),i=-.35*Math.abs(Math.sin(me(y,0,9.6)*Math.PI*3))*(1-b);const I=Math.sin(y*6.2)*(1-b);u=1+.12*I,h=1-.12*I,l=I*8,p=-I*8,o=.06*I,d=-.06*I,x=me(y,0,.4)*(1-b)}else{const y=t-108.6,b=Math.sin(me(y,0,8)*Math.PI),I=1-me(y,8,11.4);s=1+.04*b*I,i=-.1*b*I,r=2*b*I,m=1+.5*Math.sin(me(y,0,6)*Math.PI),v=1+.1*Math.sin(me(y,0,6)*Math.PI)}return e.x=n,e.y=i,e.rot=r,e.scale=s,e.ax=o,e.ay=a,e.ar=l,e.asc=u,e.afade=c,e.bx=d,e.by=f,e.br=p,e.bsc=h,e.bfade=g,e.hfade=m,e.hsc=v,e.shd=x,e}function X_(t={}){const e=t.arena||document.querySelector(".pipeline-glyph.logo-loop");if(!e)return null;const n=e.querySelector(".loop-mark"),i=e.querySelector(".loop-piece-a"),r=e.querySelector(".loop-piece-b"),s=e.querySelector(".loop-halo"),o=e.querySelector(".loop-shadow");if(!n||!i||!r||!s||!o)return null;const a=t.reducedMotion||window.matchMedia("(prefers-reduced-motion: reduce)"),l=Y_;let u=34,c=0,d=0;function f(){u=n.offsetWidth||34,c=Math.max(0,e.offsetWidth-u-4),d=Math.max(0,(e.offsetHeight-u)/2-2),e.style.setProperty("--mark-c",u/2+"px")}function p(M){const K=Math.min(1,Math.max(0,M.x))*c,ie=M.y*d;n.style.transform="translate3d("+K.toFixed(2)+"px,"+ie.toFixed(2)+"px,0) rotate("+M.rot.toFixed(2)+"deg) scale("+M.scale.toFixed(3)+")",i.style.transform="translate3d("+(M.ax*u).toFixed(2)+"px,"+(M.ay*u).toFixed(2)+"px,0) rotate("+M.ar.toFixed(2)+"deg) scale("+M.asc.toFixed(3)+")",i.style.opacity=M.afade.toFixed(3),r.style.transform="translate3d("+(M.bx*u).toFixed(2)+"px,"+(M.by*u).toFixed(2)+"px,0) rotate("+M.br.toFixed(2)+"deg) scale("+M.bsc.toFixed(3)+")",r.style.opacity=M.bfade.toFixed(3),s.style.transform="scale("+M.hsc.toFixed(3)+")",s.style.opacity=(.09*M.hfade).toFixed(3),o.style.transform="translateX("+K.toFixed(2)+"px) scaleX("+(.75+.4*Math.abs(M.x)).toFixed(3)+")",o.style.opacity=(M.shd*.5).toFixed(3)}let h=0,g=0,m=0,v=!1,x=!1,E=!1,y=0;function b(){return E||a.matches||document.hidden||!e.offsetParent?!1:x}function I(M){if(!v)return;if(m=requestAnimationFrame(I),!b()){S();return}const K=g?(M-g)/1e3:0;g=M,h=(h+Math.min(K,.1))%l,y+=1,p(Ui(h))}function T(){v||E||b()&&(v=!0,g=0,m=requestAnimationFrame(I))}function S(){v=!1,m&&(cancelAnimationFrame(m),m=0),g=0}function C(){b()?T():S()}function R(){a.matches?(S(),p(Ui(0))):C()}function O(){f(),v&&p(Ui(h))}function L(){g=0,C()}const N=new IntersectionObserver(M=>{x=M[0]?M[0].isIntersecting:!1,C()},{threshold:0});N.observe(e),window.addEventListener("resize",O),a.addEventListener("change",R),document.addEventListener("visibilitychange",L);function J(){E||(E=!0,S(),N.disconnect(),window.removeEventListener("resize",O),a.removeEventListener("change",R),document.removeEventListener("visibilitychange",L))}window.addEventListener("pagehide",M=>{M.persisted?S():J()}),window.addEventListener("pageshow",M=>{M.persisted&&C()});function G(M){h=(M%l+l)%l,p(Ui(h))}return f(),p(Ui(0)),C(),{isRunning:()=>v,currentTime:()=>h,frameCount:()=>y,seek:G,dispose:J}}const Q_=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;function dn(t){const e=String(t||"").trim().match(Q_);return e?{major:Number(e[1]),minor:Number(e[2]),patch:Number(e[3]),prerelease:e[4]?e[4].split("."):[]}:null}function e0(t,e){if(t.length===0&&e.length===0)return 0;if(t.length===0)return 1;if(e.length===0)return-1;for(let n=0;n0)}function n0(t){const e=dn(t);return e?e.major>0?`${e.major+1}.0.0`:`0.${e.minor+1}.0`:null}function Ql(t){let e=String(t??"").trim();if((e.startsWith("'")||e.startsWith('"'))&&(e=e.slice(1,-1).trim()),e===""||e==="any"||e==="*")return{min:null,minInclusive:!1,max:null,maxInclusive:!1};if(e.startsWith("^")){const o=e.slice(1).trim();return dn(o)?{min:o,minInclusive:!0,max:n0(o),maxInclusive:!1}:null}if(dn(e))return{min:e,minInclusive:!0,max:e,maxInclusive:!0};const n={min:null,minInclusive:!1,max:null,maxInclusive:!1},i=/(>=|<=|>|<)\s*([0-9][0-9A-Za-z.+-]*)/g;let r=!1,s;for(;(s=i.exec(e))!==null;){const[,o,a]=s;if(!dn(a))return null;r=!0,o===">="||o===">"?(n.min=a,n.minInclusive=o===">="):(n.max=a,n.maxInclusive=o==="<=")}return r?n:null}function _d(t,e){const n=Ql(t);if(!n||!dn(e))return!1;if(n.min!==null){const i=$s(e,n.min);if(i<0||i===0&&!n.minInclusive)return!1}if(n.max!==null){const i=$s(e,n.max);if(i>0||i===0&&!n.maxInclusive)return!1}return!0}function i0(t,e){const n=Ql(t);if(!n||!dn(e))return!1;if(n.max===null)return!0;const i=$s(n.max,e);return i>0?!0:i===0&&n.maxInclusive}function ni(t){const e=Ql(t);return e?e.min:null}const r0="https://pub.dev/api/packages/",s0=8e3;function o0(t,e={}){const{dartSdkFloor:n=null,flutterSdkFloor:i=null}=e,r=Array.isArray(t?.versions)?t.versions:[];let s=null;for(const o of r){const a=o?.version;if(!a||o.retracted||t0(a))continue;const l=o.pubspec?.environment||{};n&&l.sdk&&!_d(l.sdk,n)||i&&l.flutter&&!_d(l.flutter,i)||(!s||$s(a,s)>0)&&(s=a)}return s?{version:s,constraint:`^${s}`}:null}async function a0(t,e={}){const{dartSdkFloor:n=null,flutterSdkFloor:i=null,fetchImpl:r=fetch}=e;let s;try{const a=await r(`${r0}${encodeURIComponent(t)}`,{signal:AbortSignal.timeout(s0)});if(!a.ok)return{name:t,constraint:null,version:null,error:a.status===404?`"${t}" was not found on pub.dev`:`pub.dev returned ${a.status} for "${t}"`};s=await a.json()}catch(a){return{name:t,constraint:null,version:null,error:`could not reach pub.dev for "${t}" (${a.message})`}}const o=o0(s,{dartSdkFloor:n,flutterSdkFloor:i});return o?{name:t,...o,error:null}:{name:t,constraint:null,version:null,error:n?`no published "${t}" release supports Dart ${n}`:`no published "${t}" release could be read`}}async function l0(t,e={}){const n=await Promise.all(t.map(i=>a0(i,e)));return new Map(n.map(({name:i,...r})=>[i,r]))}async function c0(t,e={},n={}){const{resolveVersions:i=l0}=n,r=Object.entries(e).filter(([d])=>d&&d!=="flutter"),s=Qh(t),o={dartSdkFloor:ni(s.sdk),flutterSdkFloor:ni(s.flutter)},a={additions:{},overrides:{},kept:[],warnings:[],sdk:o};if(r.length===0)return a;const l=to(t),u=[],c=[];for(const[d,f]of r){const p=l.get(d);if(!p){(Oy.has(d)?c:u).push(d);continue}const h=ni(f);if(!h){a.kept.push({name:d,constraint:p.constraint});continue}const g=p.isScalar?p.constraint:p.sourceKey===null?p.version:null;if(g===null){a.warnings.push(`"${d}" is declared in your project from a git, path, or SDK source, but the generated code needs at least ${h}. Left as-is — update it yourself if the build fails.`),a.kept.push({name:d,constraint:p.constraint});continue}if(i0(g,h)){a.kept.push({name:d,constraint:g});continue}a.overrides[d]=`^${h}`,a.warnings.push(`"${d}" was pinned to ${g} in your project, which cannot resolve the ${h} the generated code needs. Raising it to ^${h} — this changes a dependency the rest of your app also uses.`)}for(const d of c)a.additions[d]={sdk:"flutter"};if(u.length>0){const d=await i(u,o);for(const f of u){const p=d.get(f);if(p?.constraint){a.additions[f]=p.constraint;continue}const h=e[f]||"";if(ni(h)){a.additions[f]=`^${ni(h)}`,a.warnings.push(`Could not confirm "${f}" version on pub.dev (${p?.error||"lookup failed"}). Using ^${ni(h)} from the AI's recommendation — verify this is current.`);continue}a.additions[f]=">=0.0.0",a.warnings.push(`Could not determine a version for "${f}" (${p?.error||"lookup failed"}) and the AI supplied none. Added with a wide-open >=0.0.0 constraint — pin a concrete version in FlutterFlow before deploying.`)}}return a}const u0={"&":"&","<":"<",">":">",'"':""","'":"'"};function fn(t){return String(t??"").replace(/[&<>"']/g,e=>u0[e])}function W(t){return t?fn(t).replace(/\n/g,"
    "):""}function cn(t){return fn(t).replace(/\r?\n/g," ")}function no(t,e={}){const n=t?.pipelineStep;if(n!=null&&e[n]!=null)return e[n];const i=t?.message||"";return i.includes("Code Generator")?2:i.includes("Code Review")?3:1}function ap(t){if(!t)return{kind:"generic",title:"Generation failed",message:"An unknown error occurred. Please try again.",detail:"",canRetry:!0,canEdit:!0,canUpgrade:!1};if(t.isModelArmor){const n=t.code==="MODEL_ARMOR_BLOCKED";return{kind:"safety",title:t.userTitle||"Request blocked for safety",message:t.userMessage||t.message,detail:t.retryExplanation||"",canRetry:!n,canEdit:!0,canUpgrade:!1}}if(t.isUsageLimit)return{kind:"quota",title:"Monthly limit reached",message:t.message||"You've used all your generations for this period.",detail:"",canRetry:!1,canEdit:!1,canUpgrade:!0};const e=t.message||"";return/timed out after/i.test(e)?{kind:"timeout",title:"Request timed out",message:"The generation service took too long to respond.",detail:e,canRetry:!0,canEdit:!0,canUpgrade:!1}:/unreachable|failed to fetch|load failed|cors/i.test(e)?{kind:"network",title:"Connection problem",message:"We couldn't reach the generation service. Check your connection and try again.",detail:e,canRetry:!0,canEdit:!0,canUpgrade:!1}:{kind:"generic",title:"Generation failed",message:e||"An unexpected error occurred.",detail:"",canRetry:!0,canEdit:!0,canUpgrade:!1}}function d0(t){const e={"Integration Audit Report":"📋","Critical Issues":"❌",Warnings:"⚠️",Recommendations:"✅","Overall Score":"📊"};for(const[n,i]of Object.entries(e))if(t.toLowerCase().includes(n.toLowerCase()))return i;return"📄"}function f0(t){const e={critical:"❌",warning:"⚠️",recommendation:"✅",score:"📊",issue:"🔍",fix:"🔧"};for(const[n,i]of Object.entries(e))if(t.toLowerCase().includes(n.toLowerCase()))return i;return"📝"}function h0(t){return t.includes("class ")&&t.includes("extends ")||t.includes("StatelessWidget")||t.includes("StatefulWidget")||t.includes("import 'package:flutter/")?"dart":t.includes("def ")||t.includes("import ")||t.includes("print(")?"python":t.includes("function ")||t.includes("const ")||t.includes("console.")?"javascript":"dart"}function bi(t){if(!t)return"";if(typeof t!="string")return String(t);const e=/```(?:\w+)?\n?([\s\S]*?)```/,n=t.match(e);return n?n[1].trim():t.trim()}function wd(t){return t=fn(t),t=t.replace(/\*\*(.*?)\*\*/g,'$1'),t=t.replace(/\*(.*?)\*/g,'$1'),t=t.replace(/`(.*?)`/g,'$1'),t=t.replace(/\b(FAIL|ERROR|CRITICAL)\b/g,'$1'),t=t.replace(/\b(WARN|WARNING)\b/g,'$1'),t=t.replace(/\b(PASS|SUCCESS|OK)\b/g,'$1'),t}function lp(t,e="dart",n=globalThis.hljs){if(!t)return"";const i=bi(t);try{return n.highlight(i,{language:e}).value}catch(r){console.warn("Syntax highlighting failed:",r);try{return n.highlight(i,{language:"json"}).value}catch{return fn(i)}}}function io(t,e={}){const{highlighter:n=globalThis.hljs}=e;let i='
    ';const r=String(t??"").split(` +`);let s=!1,o="";for(const a of r){if(a.startsWith("```")){if(s){const l=h0(o),u=lp(o.trim(),l,n);i+=`
    +
    ${u}
    +
    `,o="",s=!1}else s=!0;continue}if(s){o+=a+` +`;continue}if(a.startsWith("# ")){const l=a.substring(2).trim();i+=`
    +

    + ${d0(l)} + ${fn(l)} +

    +
    `;continue}if(a.startsWith("## ")){const l=a.substring(3).trim();i+=`
    +

    + ${f0(l)} + ${fn(l)} +

    +
    `;continue}if(/^[-*+]\s+/.test(a)||/^\d+\.\s+/.test(a)){const l=a.replace(/^([-*+]|\d+\.)\s+/,"").trim();i+=`
    + • + ${wd(l)} +
    `;continue}a.trim()!==""&&(i+=`

    ${wd(a)}

    `)}return i+="
    ",` +
    +
    +
    + Live Audit Report +
    + ${i} +
    + `}const p0=[[/gradient stroke\s*$/i," and an animated percentage label"],[/gauge\s*$/i," with a gradient stroke and animated fill"],[/rating\s*(bar|widget)?\s*$/i," with half-star support and haptic feedback"],[/list\s*$/i," with swipe-to-delete and an undo snackbar"],[/pad\s*$/i," that exports a transparent PNG"],[/carousel\s*$/i," with parallax cards and page indicators"],[/(button|cta)\s*$/i," with a loading spinner and success state"],[/(chart|graph)\s*$/i," that animates from a Firestore stream"],[/action\s*(that|to)?\s*$/i," uploads an image to Firebase Storage and returns the URL"],[/timer\s*$/i," with pause, resume and a completion callback"],[/map\s*$/i," with clustered markers and a custom info window"],[/^a\s+\w*$/i," widget that"],[/(picker|selector)\s*$/i," with search and multi-select"]],g0=220,m0=6,v0=5200,y0=73,ca=new WeakMap;function bd(t,e){return!!(t&&t.trim())&&!e}function _0(t,e=""){if(typeof t!="string"||!t||t===e||t.trim().lengthi.test(t));return n?n[1]:null}function w0(){let t="",e="";return{get active(){return t},resolve(n){return t=_0(n,e)??"",t},dismiss(){t=""},accept(n){if(!t)return null;const i=n+t;return e=i,t="",i}}}function b0({onSubmit:t}){const e=document.getElementById("composer"),n=document.getElementById("pipeline-input"),i=document.getElementById("hero-send");if(!e||!n||!i||typeof t!="function")return;const r=e.querySelector(".ghost .typed"),s=e.querySelector(".ghost .suggest"),o=document.getElementById("tab-hint"),a=document.getElementById("suggest-status"),l=Array.from(document.querySelectorAll("#example-chips .chip")),u=document.getElementById("btn-add-images"),c=document.getElementById("prompt-image-input"),d=window.matchMedia("(prefers-reduced-motion: reduce)"),f=w0();let p=!1,h=!1,g=!1,m=!1,v=!1,x=!1,E=!1,y=null,b=null,I=null;const T=n.value;function S(){return h||g||m||v||E}function C(){i.disabled=!bd(n.value,S())}function R(){r&&(r.textContent=n.value)}function O(){s&&(s.textContent=""),R(),e.classList.remove("has-suggest"),o&&(o.hidden=!0,o.tabIndex=-1),a&&(a.textContent="")}function L($){s&&(s.textContent=$),R(),e.classList.add("has-suggest"),o&&(o.hidden=!1,o.tabIndex=0,o.setAttribute("aria-label","Accept suggestion: "+$.trim())),a&&(a.textContent="Suggestion: "+$+". Press Tab to accept.")}function N(){f.dismiss(),O()}function J(){if(p||h)return;const $=f.resolve(n.value);$&&L($)}function G(){clearTimeout(y),!p&&(y=setTimeout(J,g0))}function M(){const $=f.accept(n.value);return $===null?!1:(n.value=$,O(),C(),!0)}function K($){h=$,e.classList.toggle("is-busy",$),i.classList.toggle("is-busy",$),i.setAttribute("aria-label",$?"Generating":"Generate"),n.readOnly=$,l.forEach(ee=>{ee.disabled=$}),u&&(u.disabled=$),c&&(c.disabled=$),C()}async function ie(){if(bd(n.value,S())){N(),K(!0);try{await t()}finally{K(!1)}}}function ue(){m&&(m=!1,I&&(clearTimeout(I),I=null),e.classList.remove("is-demo-typing"),e.classList.remove("is-demo-streaming"),n.placeholder="Describe the widget or action you need",C())}function we(){if(d.matches||!T.trim())return;const $=window.location.hash.replace(/^#/,"");if($&&$!=="home")return;m=!0,x=!0,n.placeholder="",n.value="",R(),C(),e.classList.add("is-demo-typing");let ee=0;const Be=()=>{m&&(ee+=1,n.value=T.slice(0,ee),R(),ee>=T.length?(e.classList.remove("is-demo-typing"),I=setTimeout(()=>{const Ze=f.resolve(n.value);if(!Ze){x=!1,ue();return}L(Ze),e.classList.add("is-demo-streaming"),s.textContent="";const Te=Ze.split(/(?=\s)/).filter(Boolean);let qt=0;const gt=()=>{if(!m)return;const rt=document.createElement("span");rt.textContent=Te[qt++],s.appendChild(rt),rt.animate?.([{opacity:0},{opacity:1}],{duration:240,easing:"cubic-bezier(0.4,0,0.2,1)"}),qt$.classList.contains("is-active"))?.dataset.prompt||n.value,R(),Q())}function pe(){l.forEach($=>{$.classList.remove("is-active"),$.setAttribute("aria-pressed","false")})}function Ne(){try{n.focus({preventScroll:!0}),n.setSelectionRange(n.value.length,n.value.length)}catch{}}function pt($){v=!1,x=!1;const ee=$.dataset.prompt||"";if(ue(),Q(),clearTimeout(y),y=null,N(),l.forEach(Ze=>{const Te=Ze===$;Ze.classList.toggle("is-active",Te),Ze.setAttribute("aria-pressed",String(Te))}),d.matches||!ee){n.value=ee,R(),C(),Ne();return}n.value="",R(),g=!0,C(),e.classList.add("is-demo-typing");let Be=0;b=setInterval(()=>{Be+=1,n.value=ee.slice(0,Be),R(),Be>=ee.length?(Q(),Ne()):C()},22)}l.forEach($=>{$.setAttribute("aria-pressed","false"),$.addEventListener("click",()=>pt($))}),n.addEventListener("keydown",$=>{if((m||g||v)&&$.key==="Enter"&&!$.shiftKey&&!$.isComposing&&!p){$.preventDefault();return}be(),de(),$.key==="Tab"&&!$.shiftKey&&f.active?($.preventDefault(),M()):$.key==="Escape"?(clearTimeout(y),y=null,N()):$.key==="Enter"&&!$.shiftKey&&!$.isComposing&&!p&&($.preventDefault(),ie())}),n.addEventListener("beforeinput",()=>{x&&(x=!1,v=!1,n.value="",R(),ue())}),n.addEventListener("input",()=>{x=!1,v=!1,ue(),Q(),pe(),N(),C(),G()}),n.addEventListener("compositionstart",()=>{p=!0}),n.addEventListener("compositionend",()=>{p=!1,N(),C(),G()}),n.addEventListener("scroll",()=>{r&&r.parentNode&&(r.parentNode.scrollTop=n.scrollTop)}),o&&o.addEventListener("click",()=>{M(),n.focus({preventScroll:!0})}),i.addEventListener("click",ie),n.addEventListener("pointerdown",()=>{be(!0),de(),pe()}),n.addEventListener("focus",()=>be());const re=ca.get(e);re&&re.mql.removeEventListener("change",re.handler),d.addEventListener("change",Re),ca.set(e,{mql:d,handler:Re});function We(){Je(),d.removeEventListener("change",Re),ca.delete(e),document.removeEventListener("visibilitychange",Pt)}function Je(){m&&(n.value=T,R(),N(),x=!1,ue()),de(),clearTimeout(y)}function Pt(){document.hidden&&Je()}return document.addEventListener("visibilitychange",Pt),R(),C(),we(),{setAttachmentsPending($){E=!!$,C()},dispose:We,cancelTyping:Je}}const pr=window.matchMedia("(prefers-reduced-motion: reduce)");let ui=null,Qt=null;const Ls=new Map;function cp(){for(const[t,e]of Ls)t.removeEventListener("animationend",e),t.classList.remove("panel-in"),t.style.animationDelay="";Ls.clear(),document.querySelectorAll(".code-line.is-in").forEach(t=>t.classList.remove("is-in"))}function Gn(){if(cp(),ui){const t=ui;ui=null,t.animation?.cancel(),t.ghost.remove(),t.panel.style.visibility="",delete t.panel.dataset.morphing,t.panel.inert=!1}Qt&&(Qt.animation.cancel(),Qt.hero.classList.remove("is-exiting"),Qt.hero.style.cssText=Qt.style,Qt=null)}function E0(t){return(ui?.ghost||t)?.getBoundingClientRect()}function S0(t){cp(),t.filter(Boolean).forEach((e,n)=>{if(e.classList.remove("panel-in"),e.style.animationDelay="",pr.matches||document.hidden)return;e.offsetWidth,e.style.animationDelay=`${n*80}ms`,e.classList.add("panel-in");function i(r){r.target===e&&(e.classList.remove("panel-in"),e.style.animationDelay="",e.removeEventListener("animationend",i),Ls.delete(e))}Ls.set(e,i),e.addEventListener("animationend",i)})}function x0(t,e){if(!t||!e||pr.matches||document.hidden||!t.animate)return;const n=t.style.cssText;t.classList.add("is-exiting"),innerWidth<=920&&(t.style.cssText=`position:absolute;left:0;top:64px;width:${e.width}px;height:${e.height}px;transform:none;`);const i=t.animate([{opacity:1},{opacity:0}],{duration:460,easing:"cubic-bezier(0.4,0,0.2,1)",fill:"both"});Qt={hero:t,animation:i,style:n},i.onfinish=()=>{Qt?.animation===i&&(t.classList.remove("is-exiting"),t.style.cssText=n,i.cancel(),Qt=null)}}function up(t,e,n,{results:i=!1}={}){if(Gn(),!e)return;const r=e.getBoundingClientRect(),s=()=>{e.style.visibility="",delete e.dataset.morphing,e.inert=!1,S0(n),(document.activeElement===document.body||document.getElementById("hero")?.contains(document.activeElement))&&e.querySelector(i?"#results-summary-tab":"#pipeline-edit-prompt")?.focus({preventScroll:!0})};if(pr.matches||document.hidden||!e.animate||!t?.width||!r.width||i&&innerWidth<=920){s();return}e.style.visibility="hidden",e.dataset.morphing="true",e.inert=!0;const o=document.createElement("div");o.className="composer-morph",o.setAttribute("aria-hidden","true");const a=innerWidth>920?Math.min(1,innerWidth/1920):1;o.style.cssText=`left:${r.left}px;top:${r.top}px;width:${r.width}px;height:${r.height}px;border-width:${2*a}px;border-radius:${20*a}px;`,document.body.appendChild(o);const l=t.left+t.width/2-r.left-r.width/2,u=t.top+t.height/2-r.top-r.height/2,c=t.width/r.width,d=t.height/r.height,f=`translate(${l}px,${u}px) scale(${c},${d})`,p=o.animate([{transform:f,opacity:0,offset:0,easing:"cubic-bezier(.2,0,0,1)"},{transform:f,opacity:1,offset:.14,easing:"cubic-bezier(.4,0,.2,1)"},{transform:`translate(${l}px,${u}px) scale(${c*.93},${d*.93})`,opacity:1,offset:.28,easing:"cubic-bezier(.32,1.38,.5,1)"},{transform:"translate(0px,0px) scale(1,1)",opacity:1,offset:1}],{duration:1120,fill:"both"}),h={panel:e,ghost:o,animation:p};ui=h,p.onfinish=()=>{ui===h&&(Gn(),s())}}window.addEventListener("resize",Gn);window.addEventListener("pagehide",Gn);document.addEventListener("visibilitychange",()=>{document.hidden&&Gn()});pr.addEventListener("change",()=>{pr.matches&&Gn()});const I0="https://ccc-ffai-runner-y5cyj3473a-uw.a.run.app/deployCustomClasses";const At="https://4tgke4.buildship.run",dp={professional:"price_1T2ldCKszA2slvDXatdeCpbI",power:"price_1T2le9KszA2slvDXR4mPvw7M"},Ns="ccc_auth_session",il="ccc_signin_return",k0=1800*1e3,Ed=new WeakSet;let H={email:null,sessionToken:null,isVerified:!1};function Kn(t={}){return{tier:"free",status:"none",periodEnd:null,isLoading:!1,isResolved:!1,error:null,...t}}let he=Kn({isResolved:!0}),rl=Promise.resolve();const C0=`${At}/service/runpipeline`,A0="bs_user_id",P0="bs_identity_token",F0=`${At}/authUserCheck`;let xt={userId:null,token:null,status:null,resolved:!1};const Os=Xv,Bs="ccc_subscription",Sd=3,R0=new Set(["active","trialing","paid"]),Ds="google/gemini-3.7-flash",ns=["anthropic/claude-opus-5","openai/gpt-5.6-sol","z-ai/glm-5.2","moonshotai/kimi-k3","openrouter/auto-beta","openrouter/free","openrouter/deepseek/deepseek-v4-pro"],T0={"google/gemini-3.7-flash":"Gemini 3.7 Flash","anthropic/claude-opus-5":"Claude Opus 5","openai/gpt-5.6-sol":"GPT-5.6 Sol","z-ai/glm-5.2":"GLM 5.2","moonshotai/kimi-k3":"Kimi K3","openrouter/auto-beta":"OpenRouter: Auto Router","openrouter/free":"OpenRouter: Free Models","openrouter/deepseek/deepseek-v4-pro":"DeepSeek v4 Pro"};function on(t){return T0[t]||t}const M0=new Set(["google/gemini-3.7-flash","anthropic/claude-opus-5","openai/gpt-5.6-sol","z-ai/glm-5.2","moonshotai/kimi-k3","openrouter/auto-beta"]);function fp(t){return M0.has(t)}const sl=4,ua=8*1024*1024,$0="https://4tgke4.buildship.run/service/runpipeline-image";let Ue=[];const kn=[],L0=3e4;let ec=null;function N0(t,e){return new Promise(n=>{const i=new FileReader,r=o=>{e?.removeEventListener("abort",s),n(o)},s=()=>{i.abort(),r(null)};if(i.onload=()=>r(i.result),i.onerror=()=>r(null),e){if(e.aborted){n(null);return}e.addEventListener("abort",s,{once:!0})}i.readAsDataURL(t)})}async function O0(t,e){const n=new FormData;return n.append("file",t),(await fetch($0,{method:"POST",body:n,signal:e})).json()}function B0(t){if(Array.isArray(t)){const e=t[0];if(e&&typeof e=="object")for(const n of Object.keys(e)){if(n==="item"||n==="index")continue;const i=e[n];if(i&&typeof i=="object"){if(typeof i.file=="string")return i.file;if(typeof i.url=="string")return i.url}if(typeof i=="string")return i}return""}return typeof t=="string"?t:t&&typeof t=="object"&&(t.url||t.fileUrl||t.file_url||t.downloadUrl||t.imageUrl||t.image_url||t.file)||""}async function D0(t,e,n){const i=await N0(t,n);i&&Ue.includes(e)&&(e.dataUrl=i,bn());let r="";if(i)try{r=B0(await O0(t,n))}catch{r=""}return Ue.includes(e)?!i||!r?(Ue.splice(Ue.indexOf(e),1),bn(),"failed"):(e.url=r,bn(),"added"):"dropped"}function hp(t){const e=kn.indexOf(t);e>=0&&kn.splice(e,1),gp()}function pp(t){t.controller.abort(),hp(t);const e=Ue.indexOf(t.slot);e>=0&&(Ue.splice(e,1),bn())}function gp(){ec?.setAttachmentsPending(kn.length>0)}async function j0(t){const e=Array.from(t.target.files||[]);if(!e.length)return;if(t.target.value="",_.isRunning){Ie("Wait for the current generation to finish before attaching images.","info");return}const n=e.filter(u=>u.size>ua);n.length&&Ie(`Skipped ${n.length} image(s) over the ${(ua/1024/1024).toFixed(0)} MB limit.`,"warning");const i=e.filter(u=>u.size<=ua);if(!i.length)return;const r=sl-Ue.length,s=i.slice(0,r);if(i.length>r&&Ie(`You can attach up to ${sl} images.`,"info"),!s.length)return;const o=s.map(u=>{const c={dataUrl:null,name:u.name,url:null};Ue.push(c);const d={slot:c,controller:new AbortController},f=setTimeout(()=>d.controller.abort(),L0);return d.job=D0(u,c,d.controller.signal),kn.push(d),d.job.finally(()=>{clearTimeout(f),hp(d)}),d.job});bn(),gp();const l=(await Promise.all(o)).filter(u=>u==="failed").length;l&&Ie(`${l} image(s) could not be uploaded and were not attached.`,"error")}function U0(t){if(_.isRunning){Ie("Wait for the current generation to finish before removing images.","info");return}const e=Ue[t],n=kn.find(i=>i.slot===e);if(n){pp(n);return}Ue.splice(t,1),bn()}function bn(){const t=document.getElementById("prompt-image-thumbnails"),e=document.getElementById("prompt-image-btn-label");t&&(t.innerHTML="",Ue.forEach((n,i)=>{const r=document.createElement("div");r.className="prompt-img-thumb"+(n.url?"":" is-pending"),r.innerHTML=(n.dataUrl?`Prompt image`:"")+``,t.appendChild(r)}),e&&(e.textContent=Ue.length>=sl?"Image limit reached":"Add images"))}function tc(){const t=document.getElementById("prompt-image-upload");if(!t)return;const e=document.getElementById("code-generator-model"),n=fp(e?.value);t.classList.toggle("hidden",!n),!n&&Ue.length&&!_.isRunning&&(kn.slice().forEach(pp),Ue=[],bn())}const Wn="ccc_usage",mp="google/gemini-3.7-flash",vp="google/gemini-3.7-flash",Vr="google/gemini-3.7-flash",Yi={professional:11,power:49},ol={en_US:"USD",en_GB:"GBP",en_AU:"AUD",en_NZ:"NZD",en_CA:"CAD",en_IN:"INR",en_SG:"SGD",en_HK:"HKD",en_PH:"PHP",en_ZA:"ZAR",en:"USD",de:"EUR",fr:"EUR",es:"EUR",it:"EUR",nl:"EUR",pt_PT:"EUR",pt_BR:"BRL",pt:"BRL",ja:"JPY",ko:"KRW",zh_CN:"CNY",zh_TW:"TWD",zh:"CNY",th:"THB",vi:"VND",id:"IDR",ms_MY:"MYR",ms:"MYR",sv:"SEK",nb:"NOK",da:"DKK",pl:"PLN",cs:"CZK",hu:"HUF",ro:"RON",tr:"TRY",ar:"AED",he:"ILS",ru:"RUB",uk:"UAH"},is={AUD:1,USD:.65,EUR:.6,GBP:.52,CAD:.88,NZD:1.08,JPY:97,KRW:870,INR:54,SGD:.87,HKD:5.08,BRL:3.18,CNY:4.7,TWD:20.5,THB:22.5,VND:16200,IDR:10200,MYR:2.88,SEK:6.8,NOK:6.95,DKK:4.48,PLN:2.6,CZK:15.2,HUF:238,RON:2.98,TRY:20.9,AED:2.39,ILS:2.38,PHP:36.4,ZAR:11.8,RUB:58,UAH:26.8,CHF:.57,MXN:11.1,ARS:580,CLP:610,COP:2700,PEN:2.44};let rs={...is};async function H0(){const t=new AbortController,e=setTimeout(()=>t.abort(),5e3);try{const n=await fetch("https://open.er-api.com/v6/latest/AUD",{signal:t.signal});if(!n.ok)return;const i=await n.json();if(i.result!=="success"||!i.rates)return;const r=i.rates,s={AUD:1},o=new Set([...Object.keys(is),...Object.values(al),...Object.values(ol)]);for(const a of o)a!=="AUD"&&(typeof r[a]=="number"&&r[a]>0?s[a]=r[a]:is[a]&&(s[a]=is[a]));rs=s}catch{}finally{clearTimeout(e)}}const al={"America/Sao_Paulo":"BRL","America/Fortaleza":"BRL","America/Recife":"BRL","America/Bahia":"BRL","America/Belem":"BRL","America/Manaus":"BRL","America/Cuiaba":"BRL","America/Campo_Grande":"BRL","America/Araguaina":"BRL","America/Noronha":"BRL","America/Rio_Branco":"BRL","America/Porto_Velho":"BRL","America/Boa_Vista":"BRL","America/Maceio":"BRL","America/Santarem":"BRL","America/Eirunepe":"BRL","Europe/London":"GBP","Europe/Paris":"EUR","Europe/Berlin":"EUR","Europe/Madrid":"EUR","Europe/Rome":"EUR","Europe/Amsterdam":"EUR","Europe/Brussels":"EUR","Europe/Vienna":"EUR","Europe/Lisbon":"EUR","Europe/Dublin":"EUR","Europe/Helsinki":"EUR","Europe/Athens":"EUR","Europe/Bucharest":"RON","Europe/Budapest":"HUF","Europe/Warsaw":"PLN","Europe/Prague":"CZK","Europe/Copenhagen":"DKK","Europe/Stockholm":"SEK","Europe/Oslo":"NOK","Europe/Zurich":"CHF","Europe/Istanbul":"TRY","Europe/Moscow":"RUB","Europe/Kiev":"UAH","Europe/Kyiv":"UAH","Asia/Tokyo":"JPY","Asia/Seoul":"KRW","Asia/Shanghai":"CNY","Asia/Taipei":"TWD","Asia/Hong_Kong":"HKD","Asia/Singapore":"SGD","Asia/Kolkata":"INR","Asia/Calcutta":"INR","Asia/Bangkok":"THB","Asia/Ho_Chi_Minh":"VND","Asia/Jakarta":"IDR","Asia/Kuala_Lumpur":"MYR","Asia/Dubai":"AED","Asia/Jerusalem":"ILS","Asia/Tel_Aviv":"ILS","Asia/Manila":"PHP","Pacific/Auckland":"NZD","Australia/Sydney":"AUD","Australia/Melbourne":"AUD","Australia/Brisbane":"AUD","Australia/Perth":"AUD","Australia/Adelaide":"AUD","Australia/Hobart":"AUD","Australia/Darwin":"AUD","Australia/Lord_Howe":"AUD","America/Toronto":"CAD","America/Vancouver":"CAD","America/Edmonton":"CAD","America/Winnipeg":"CAD","America/Halifax":"CAD","America/St_Johns":"CAD","America/Regina":"CAD","America/New_York":"USD","America/Chicago":"USD","America/Denver":"USD","America/Los_Angeles":"USD","America/Phoenix":"USD","America/Anchorage":"USD","Pacific/Honolulu":"USD","America/Mexico_City":"MXN","America/Cancun":"MXN","America/Tijuana":"MXN","America/Argentina/Buenos_Aires":"ARS","America/Santiago":"CLP","America/Bogota":"COP","America/Lima":"PEN","Africa/Johannesburg":"ZAR"};function nc(){try{const s=Intl.DateTimeFormat().resolvedOptions().timeZone;if(s&&al[s])return al[s]}catch{}const e=(navigator.language||"en-US").replace("-","_"),n=ol[e];if(n)return n;const i=e.split("_")[0],r=ol[i];return r||"USD"}function Ji(t,e){const n=rs[e]??rs.USD,i=t*n,r=Math.round(i*100)/100;try{return new Intl.NumberFormat("en-US",{style:"currency",currency:e,minimumFractionDigits:0,maximumFractionDigits:r>=100||r%1===0?0:2}).format(r)}catch{return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:0,maximumFractionDigits:2}).format(t*rs.USD)}}const It="ccc_api_key_",Ot="ccc_session_api_key_",Ut="ccc_encryption_key",gr="ccc_encryption_key_scope",W0="ccc_keystore",js="keys",mr="ccc_encryption_key_version";let ll=null,Us=null,vr=!1,Hs=!1,xd=!1;class Ws extends Error{constructor(){super("Secure browser key storage is unavailable."),this.name="CredentialStorageUnavailableError"}}function Id(){if(xd)return;xd=!0;const t="Secure browser key storage is unavailable. Existing credentials were left untouched; new credentials will be available only in this tab session.";console.warn(t),document.body&&Ie(t,"warning")}function yp(){return localStorage.getItem(mr)||""}function cl(){return crypto.randomUUID?.()||wp(crypto.getRandomValues(new Uint8Array(16)))}function q0(){const t=yp();if(t)return t;const e=cl();return localStorage.setItem(mr,e),e}function Ei(){ll=null,Us=null,vr=!1,Hs=!1}window.addEventListener("storage",t=>{t.key===mr&&Ei()});function z0(){return new Promise((t,e)=>{const n=indexedDB.open(W0,1);n.onupgradeneeded=()=>{const i=n.result;i.objectStoreNames.contains(js)||i.createObjectStore(js)},n.onsuccess=()=>t(n.result),n.onerror=()=>e(n.error)})}async function ic(t,e){const n=await z0();return new Promise((i,r)=>{const s=n.transaction(js,t);let o;try{o=e(s.objectStore(js))}catch(l){n.close(),r(l);return}let a;o.onsuccess=()=>{a=o.result},o.onerror=()=>r(o.error),s.oncomplete=()=>{n.close(),i(a)},s.onerror=()=>{n.close(),r(s.error||new Error("Encryption key transaction failed."))},s.onabort=()=>{n.close(),r(s.error||new Error("Encryption key transaction aborted."))}})}function V0(t){return t instanceof CryptoKey&&t.algorithm?.name==="AES-GCM"&&t.extractable===!1&&t.usages.includes("encrypt")&&t.usages.includes("decrypt")}async function G0(){const t=await ic("readonly",e=>e.get(Ut));return V0(t)?t:null}async function _p(t){await ic("readwrite",e=>e.put(t,Ut))}async function K0(){Ei();try{await ic("readwrite",t=>t.delete(Ut))}catch(t){console.warn("Could not delete the stored encryption key:",t)}}async function Y0(){const t=sessionStorage.getItem(Ut);if(!t)return null;const e=await crypto.subtle.importKey("jwk",JSON.parse(t),{name:"AES-GCM",length:256},!1,["encrypt","decrypt"]);return await _p(e),sessionStorage.removeItem(Ut),sessionStorage.removeItem(gr),localStorage.removeItem(It+"salt"),e}async function kd(t){const e=sessionStorage.getItem(Ut);if(e)return Hs=sessionStorage.getItem(gr)!=="session",crypto.subtle.importKey("jwk",JSON.parse(e),{name:"AES-GCM",length:256},!1,["encrypt","decrypt"]);if(!t)throw new Ws;const n=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),i=await crypto.subtle.exportKey("jwk",n);return sessionStorage.setItem(Ut,JSON.stringify(i)),sessionStorage.setItem(gr,"session"),Hs=!1,crypto.subtle.importKey("jwk",i,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async function J0(t){if(sessionStorage.getItem(gr)==="session"&&sessionStorage.getItem(Ut))return Id(),vr=!0,kd(t);try{const e=await G0();if(e)return e;const n=await Y0();if(n)return n;const i=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!1,["encrypt","decrypt"]);return await _p(i),i}catch(e){return console.warn("IndexedDB encryption-key storage failed:",e),Id(),vr=!0,kd(t)}}async function rc(t={}){const{allowSessionFallbackCreation:e=!0}=t,n=q0();Us!==n&&Ei();const i=ll||J0(e);ll=i,Us=n;try{return await i}catch(r){throw Ei(),r}}async function Z0(t){const e=await rc(),n=Us,i=new TextEncoder,r=crypto.getRandomValues(new Uint8Array(12)),s=await crypto.subtle.encrypt({name:"AES-GCM",iv:r},e,i.encode(t)),o=new Uint8Array(r.length+s.byteLength);return o.set(r),o.set(new Uint8Array(s),r.length),{ciphertext:wp(o),keyVersion:n,sessionFallback:vr}}async function X0(t,e={}){const{isSessionCredential:n=!1}=e;try{const i=await rc({allowSessionFallbackCreation:!1});if(vr&&!n&&!Hs)throw new Ws;const r=Q0(t),s=r.slice(0,12),o=r.slice(12),a=await crypto.subtle.decrypt({name:"AES-GCM",iv:s},i,o);return new TextDecoder().decode(a)}catch(i){if(i instanceof Ws)throw i;return console.error("Decryption failed:",i),null}}function wp(t){const e=new Uint8Array(t);let n="";for(let i=0;i0}let Ae="",Bt="",ir=null,Ad=0,ut="not-configured",bt=0,ul=0,dl=0,ro=0,en=0,hn=0,tt=null,Dt=null,yr=null;function tw(){return ul+=1,ul}function nw(){return dl+=1,dl}function _r(t,e,n){tt=t?{projectId:t,key:e,generation:n}:null}function fl(t,e=Ae){if(!t)return!1;const n=tt;return n?n.projectId===t&&n.key===e&&n.generation===bt:!1}function sc(t,e,n){if(!Bt||tt&&tt.projectId!==Bt)return;(t||[]).some(r=>(r.id||r.projectId)===Bt)?_r(Bt,e,n):tt&&_r("",null,null)}function bp({seq:t,currentSeq:e,generation:n,storedKeyAtStart:i,requestKey:r}){return t!==e||n!==bt?!1:i===Ae||r===Ae}async function oc(){sessionStorage.getItem(Ut)&&await rc(),Ae=await Le("flutterflow"),Bt=await Le("flutterflow_project_id"),lw(),vn(),Ae?uc():(ut="not-configured",Ct())}let wr=!1;function Ep(){const t=document.getElementById("api-keys-modal");Ke(t),cc(),Ae&&ao(Ae)}function ac(){wr=!1,Ep()}function iw(){wr=!0;const t=document.getElementById("walkthrough-modal");t&&Ye(t),Ep()}let Pd=!1;function Fd(){const t=document.getElementById("code-generator-model"),e=document.getElementById("composer-settings-model");if(!t||!e)return;e.value=t.value;const n=Array.from(t.options);Array.from(e.options).forEach((r,s)=>{const o=n[s];o&&(r.textContent=o.textContent)});const i=document.getElementById("composer-settings-free-notice");i&&(document.getElementById("model-selector-free-notice")?(i.hidden=!1,i.innerHTML='Free plan — Gemini only. '):i.hidden=!0)}function Rd(){const t=document.getElementById("code-generator-model"),e=document.getElementById("composer-image-capability"),n=document.getElementById("composer-image-capability-note");if(!t)return;const i=on(t.value),r=fp(t.value);e&&(e.textContent=r?"Supported":"Not supported"),n&&(n.textContent=r?`${i} accepts reference images you attach to the prompt.`:`Images can't be attached with ${i}. Attached images are removed when you switch to it.`),tc()}function Sp(){if(wr=!1,Fd(),Rd(),!Pd){const e=document.getElementById("composer-settings-model");e&&e.addEventListener("change",()=>{const n=document.getElementById("code-generator-model");n.value=e.value,n.dispatchEvent(new Event("change")),Fd(),Rd()}),Pd=!0}const t=document.querySelector('.composer [aria-label="Generation settings"]');Ke("composer-settings-modal",{trigger:t})}function rw(t){t&&t.target!==t.currentTarget||Ye("composer-settings-modal")}function xp(t){if(t&&t.target!==t.currentTarget)return;const e=document.getElementById("api-keys-modal");e&&Ye(e);const n=wr;if(wr=!1,n){const i=document.getElementById("walkthrough-modal");i&&(ut==="connected"&&lc(),Ke(i))}}let pn=1;function Ip(){const t=document.querySelector(".wt-steps");return t?Array.from(t.querySelectorAll(".wt-step-card")):[]}function so(){const t=Ip();t.length&&t.forEach((e,n)=>{const i=n+1;e.classList.remove("wt-current","wt-done","wt-pending");const r=e.querySelector(".wt-step-num");i===pn?(e.classList.add("wt-current"),r&&(r.textContent=i)):i0&&pn<=t&&(pn++,so())}function sw(){const t=document.getElementById("walkthrough-modal");t&&(pn=1,so(),Ke(t))}function ow(t){if(t&&t.target!==t.currentTarget)return;const e=document.getElementById("walkthrough-modal");e&&Ye(e);const n=document.getElementById("walkthrough-dont-show");n&&n.checked&&localStorage.setItem("hasSeenWalkthrough","true")}function kp(){if(H.isVerified&&Ht()&&he.tier!=="free")return;if(!localStorage.getItem("hasSeenWalkthrough")){const e=document.getElementById("walkthrough-modal");e&&(pn=1,so(),Ke(e))}}async function cc(){const t=document.getElementById("flutterflow-api-key-input");Ae?(t.value="",t.placeholder="Key saved (enter new to replace)"):t.placeholder="Enter your FlutterFlow API key",aw()}function aw(){Td("flutterflow","flutterflow-key-status"),Td("flutterflow_project_id","flutterflow-project-status")}function Td(t,e){const n=document.getElementById(e);if(!n)return;const i=n.querySelector(".key-status-dot"),r=n.querySelector("span");Lt(t)?(i.className="key-status-dot configured",r.className="text-green-600",r.textContent="User key configured"):(i.className="key-status-dot missing",r.className="text-gray-500",r.textContent="Not configured")}function vn(){const t=_.step2Result&&_.step2Result.length>0,e=document.getElementById("btn-deploy-to-ff");e&&e.classList.toggle("hidden",!t)}function lw(){const t=document.getElementById("api-keys-status");if(!t)return;const e=t.querySelectorAll(".key-status-dot"),n=["flutterflow"];e.forEach((i,r)=>{const s=n[r];s==="flutterflow"?Lt("flutterflow")&&Lt("flutterflow_project_id")?(i.className="key-status-dot configured",i.title="FlutterFlow (Fully configured)"):Lt("flutterflow")||Lt("flutterflow_project_id")?(i.className="key-status-dot env",i.title="FlutterFlow (Partially configured)"):(i.className="key-status-dot missing",i.title="FlutterFlow (Not configured)"):Lt(s)?(i.className="key-status-dot configured",i.title=s.charAt(0).toUpperCase()+s.slice(1)+" (User key)"):(i.className="key-status-dot missing",i.title=s.charAt(0).toUpperCase()+s.slice(1)+" (Not configured)")}),vn()}async function cw(){const t=document.getElementById("flutterflow-api-key-input"),e=document.getElementById("flutterflow-projects-select"),n=t.value.trim(),i=!!n&&n!==Ae,r=e?.value.trim()||"";if(n){const l=await Le("flutterflow").catch(()=>"");await Cd("flutterflow",n),n!==l&&!r&&ss()}const s=n||Ae;if(r){if(!oo(r)){Ie("The selected FlutterFlow project has an unexpected ID format.","error"),e.focus();return}fl(r,s)?await Cd("flutterflow_project_id",r):(i?ss():tt=null,e.value="",s&&!(Dt&&Dt.key===s&&Dt.generation===bt)&&ao(s))}else i&&ss();await oc(),n&&await uc(),cc();const o=document.querySelector("#api-keys-modal .bg-blue-500"),a=o.textContent;o.textContent="Saved!",o.classList.remove("bg-blue-500","hover:bg-blue-600"),o.classList.add("bg-green-500"),setTimeout(()=>{o.textContent=a,o.classList.remove("bg-green-500"),o.classList.add("bg-blue-500","hover:bg-blue-600"),xp()},1e3)}async function uw(){if(!confirm("Are you sure you want to clear all stored API keys?"))return;localStorage.setItem(mr,cl()),Ei(),localStorage.removeItem(It+"flutterflow"),localStorage.removeItem(It+"flutterflow_project_id"),sessionStorage.removeItem(Ot+"flutterflow"),sessionStorage.removeItem(Ot+"flutterflow_project_id"),sessionStorage.removeItem(Ut),sessionStorage.removeItem(gr),localStorage.removeItem(It+"salt"),await K0(),localStorage.setItem(mr,cl()),localStorage.removeItem(It+"flutterflow"),localStorage.removeItem(It+"flutterflow_project_id"),sessionStorage.removeItem(Ot+"flutterflow"),sessionStorage.removeItem(Ot+"flutterflow_project_id"),tt=null,Dt=null,yr=null,await oc();const t=document.getElementById("flutterflow-projects-select");t&&(t.innerHTML=''),cc()}function oo(t){return!t||t.trim().length<5||t.includes(" ")?!1:/^[a-zA-Z0-9-]+$/.test(t)}function Ct(){const t=document.getElementById("acct-ff-dot"),e=document.getElementById("acct-ff-status"),n=document.getElementById("acct-ff-endpoint"),i=document.getElementById("acct-ff-project");if(n){const o=Ge();n.textContent=o.includes("staging")?"Staging":"Production"}if(i&&(i.textContent=Bt||"—"),!e)return;let r,s;if(!Lt("flutterflow"))r="Not connected — add your FlutterFlow API key",s="";else switch(ut){case"connected":r="Connected to FlutterFlow",s="ok";break;case"no-projects":r="Key accepted — no projects found",s="warn";break;case"unauthorized":r="API key rejected (401/403) — re-enter your key",s="bad";break;case"network-error":r="Could not reach FlutterFlow — check your network",s="bad";break;default:r="Checking connection…",s="warn";break}e.textContent=r,t&&(t.className=`acct-dot${s?" "+s:""}`)}async function uc(){const t=nw(),e=++ro,n=bt,i=Ae,r=await Le("flutterflow"),s=()=>bp({seq:t,currentSeq:dl,generation:n,storedKeyAtStart:i,requestKey:r});if(!s()||e<=en)return null;const o=()=>{hn=Math.max(hn,e)};if(!r||!Lt("flutterflow"))return en=e,o(),ut="not-configured",Ct(),null;ut="validating",Ct();try{const l=await new Jn(r,"","main",Ge()).listProjects();return!s()||e<=en?null:(en=e,o(),ut=l&&l.length>0?"connected":"no-projects",e>=hn&&sc(l,r,n),Ct(),l)}catch(a){if(!s()||e<=en)return null;en=e,o();const l=String(a&&a.message||"");return ut=/(401|403)|denied|unauthorized|scoped|list permission/i.test(l)?"unauthorized":"network-error",Ct(),null}}function ss(){Bt="",tt=null,localStorage.removeItem(It+"flutterflow_project_id"),sessionStorage.removeItem(Ot+"flutterflow_project_id")}function dw(){bt+=1,Dt=null,yr=null,ss();const t=document.getElementById("flutterflow-projects-select");t&&(t.innerHTML='',t.value=""),Lt("flutterflow")?(ut="validating",ao(Ae)):ut="not-configured",Ct()}function fw(t,e){const n=document.getElementById(t);n&&(n.value?e?n.style.borderColor="#22c55e":n.style.borderColor="#ef4444":n.style.borderColor="")}function hw(){const t=document.getElementById("flutterflow-api-key-input");t&&(t.addEventListener("input",n=>{const i=n.target.value.trim().length>0;fw("flutterflow-api-key-input",i)}),t.addEventListener("blur",pw(async n=>{const i=n.target.value.trim();i&&await ao(i)},500)));const e=document.getElementById("flutterflow-projects-select");e&&e.addEventListener("change",()=>{const n=e.value.trim();n&&Dt?_r(n,Dt.key,Dt.generation):_r("",null,null)})}function pw(t,e){let n;return function(...r){const s=()=>{clearTimeout(n),t(...r)};clearTimeout(n),n=setTimeout(s,e)}}async function ao(t){const e=document.getElementById("flutterflow-projects-select"),n=document.getElementById("flutterflow-projects-error");if(!e){console.error("Projects dropdown element not found");return}const i=tw(),r=++ro,s=bt,o=Ae,a=()=>bp({seq:i,currentSeq:ul,generation:s,storedKeyAtStart:o,requestKey:t}),l=()=>r>en,u=()=>{en=Math.max(en,r)};Dt=null,e.innerHTML='',n&&n.classList.add("hidden"),l()&&t===Ae&&(Lt("flutterflow")||t)&&(ut="validating"),Ct();try{const d=await new Jn(t,"","main",Ge()).listProjects();if(!a())return;Dt={key:t,generation:s};const f=t===Ae,p=l()&&f;if(p&&u(),r>hn&&f&&(hn=r,sc(d,t,s)),!d||d.length===0){p&&(ut="no-projects",Ct()),e.innerHTML='';return}p&&(ut="connected",Ct()),e.innerHTML='',d.forEach(h=>{const g=document.createElement("option");g.value=h.id||h.projectId||"",g.textContent=h.name||h.projectName||`Project ${h.id}`,e.appendChild(g)}),Bt&&(e.value=Bt)}catch(c){if(!a())return;console.error("Failed to fetch projects:",c);const d=String(c&&c.message||"");l()&&t===Ae&&(u(),ut=/(401|403)|denied|unauthorized|scoped|list permission/i.test(d)?"unauthorized":"network-error",Ct()),e.innerHTML='',n&&(n.textContent=`Failed to load projects: ${c.message}`,n.classList.remove("hidden"))}}function gw(t){const e=document.getElementById(t),i=e.nextElementSibling.querySelector("svg");e.type==="password"?(e.type="text",i.innerHTML=` + + `):(e.type="password",i.innerHTML=` + + + `)}let _={step1Result:null,step2Result:null,step3Result:null,bundleSpec:null,artifactBundle:null,bundleReview:null,selectedArtifactId:null,resultsViewMode:"summary",currentStep:0,isRunning:!1,runId:0,submittedPrompt:"",submittedImages:[]};function mw(){_.step1Result=null,_.step2Result=null,_.step3Result=null,_.bundleSpec=null,_.artifactBundle=null,_.bundleReview=null,_.selectedArtifactId=null,_.resultsViewMode="summary"}function vw(){_.bundleSpec=fr(_.step1Result,{artifactType:"CustomWidget",artifactName:"GeneratedWidget"})}function lo(){const t=_i(_.bundleSpec);_.artifactBundle=fr(_.step2Result,{id:_.bundleSpec?.id,title:_.bundleSpec?.title,description:_.bundleSpec?.description,artifactType:t.artifactType,artifactName:t.artifactName,fileName:t.fileName,dependencies:t.dependencies,relationships:_.bundleSpec?.relationships,code:_.step2Result||""});const e=My(_.artifactBundle);_.artifactBundle={..._.artifactBundle,warnings:[..._.artifactBundle.warnings,...e.findings.map(n=>n.message)],metadata:{..._.artifactBundle.metadata,compatibility:e}},_.selectedArtifactId=_i(_.artifactBundle).id}function co(){const t=fr(_.step3Result,{id:_.artifactBundle?.id,title:_.artifactBundle?.title}),e=new Map(t.artifacts.map(i=>[i.id,i.review])),n=new Map(t.artifacts.filter(i=>{const r=i.review;return r&&typeof r.fixedSource=="string"&&r.fixedSource.trim()}).map(i=>[i.id,i.review.fixedSource.trim()]));_.bundleReview=fr({id:_.artifactBundle?.id,title:_.artifactBundle?.title,artifacts:_.artifactBundle?.artifacts?.map(i=>{const r=n.get(i.id)||null;return{...i,review:e.get(i.id)||i.review||_.step3Result||null,...r?{fixedCode:r}:{}}})||[],relationships:_.artifactBundle?.relationships,warnings:_.artifactBundle?.warnings})}function Cp(){const t=dc();return{artifactType:t.artifactType||"CustomWidget",artifactName:t.artifactName||"GeneratedWidget",fileName:t.fileName||""}}function dc(){const t=_.artifactBundle||_.bundleSpec||null;return(Array.isArray(t?.artifacts)?t.artifacts:[]).find(n=>n.id===_.selectedArtifactId)||_i(t)}function fc(){return dc().code||_.step2Result||""}async function yw(){try{await oc()}catch(t){return console.error("checkConnection: initializeApiKeys failed:",t),!1}return!0}const os={production:"https://api.flutterflow.io/v2/",staging:"https://api.flutterflow.io/v2-staging/"};function _w(t,e){const n=e?.trim()?` (${e.trim().slice(0,200)})`:"";return t===401?`Your FlutterFlow API key was rejected (401 Unauthorized)${n}. Re-enter a current key under API Keys settings, then try again.`:`Listing FlutterFlow projects was denied (403)${n}. The key may be scoped to sync a single project without list permission - verify the key's access in FlutterFlow, re-enter it under API Keys settings, then retry.`}class Jn{constructor(e,n,i="main",r=os.production){this.apiKey=e,this.baseUrl=r,this._projectId=n,this._branchName=i,this._endpoint=r}get projectId(){return this._projectId}get branchName(){return this._branchName==="main"?"":this._branchName}async exportProjectZip(){console.log(`Exporting code from FlutterFlow project: ${this.projectId}, branch: ${this.branchName||"main"}`);const e=[{project:{path:`projects/${this.projectId}`},...this.branchName?{branch_name:this.branchName}:{},export_as_module:!1,include_assets_map:!1,format:!1,export_as_debug:!1},{project_id:this.projectId,branch_name:this.branchName,include_assets:!1,export_as_module:!1}];let n=null;for(const i of e)try{const r=await fetch(`${this.baseUrl}exportCode`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`},body:JSON.stringify(i)});if(!r.ok){const a=await r.text();n=new Error(`Export failed: ${r.status} - ${a}`);continue}const s=await r.json(),o=s?.value?.project_zip||s?.project_zip;if(!o){n=new Error("Export response did not include project source.");continue}return o}catch(r){n=r}throw n||new Error("Export failed for an unknown reason.")}async fetchProjectSource(){const e=await this.exportProjectZip(),n=await JSZip.loadAsync(e,{base64:!0}),i=Object.keys(n.files).filter(a=>!n.files[a].dir&&(a==="pubspec.yaml"||a.endsWith("/pubspec.yaml"))).sort((a,l)=>a.split("/").length-l.split("/").length)[0];if(!i)throw new Error("Export did not contain a pubspec.yaml.");const r=i.slice(0,i.length-12),s=new Map,o=Object.keys(n.files).filter(a=>{if(n.files[a].dir||!a.startsWith(r))return!1;const l=a.slice(r.length);return l==="lib/flutter_flow/custom_functions.dart"||l.startsWith("lib/custom_code/")&&l.endsWith(".dart")});return await Promise.all(o.map(async a=>{s.set(a.slice(r.length),await n.files[a].async("string"))})),{pubspecYaml:await n.files[i].async("string"),files:s}}async pushCodeWithRetry(e,n=3,i=null){const r=[os.production,os.staging],s=Math.max(0,r.indexOf(this._endpoint));let o=!1,a=null;for(let l=0;lsetTimeout(h,1e3*(l+1)));continue}if(d.ok)return console.log(`Push to ${c} succeeded!`),d;a=d.status;const f=d.status<500&&!o;if(hl(f?d.clone():d,ip).then(p=>console.log(`Push to ${c} returned ${d.status}: ${p}`),()=>console.log(`Push to ${c} returned ${d.status} (unreadable response body)`)),d.status>=500&&(o=!0),d.status===500){console.warn(`Endpoint ${c} returned 500, trying next...`),await new Promise(p=>setTimeout(p,1e3*(l+1)));continue}if(d.status>=500)throw new at(`FlutterFlow reported a server error (HTTP ${d.status}), which cannot prove the push was refused — the write may have been applied before the failure. Open your FlutterFlow project to reconcile before retrying.`);if(o)throw new at(`The push was refused (HTTP ${d.status}), but an earlier sync attempt may already have applied it — server errors and dropped responses cannot prove a refusal. Open your FlutterFlow project to reconcile before retrying.`);return d}throw md({httpStatus:a})}async pushCode(e,n=null){return this.pushCodeWithRetry(e,3,n)}parseProjectsResponse(e){if(e?.success&&typeof e.value=="string")try{const i=JSON.parse(e.value);if(i&&Array.isArray(i.entries))return i.entries.map(r=>({id:r.id,name:r.project?.name||r.id}))}catch(i){console.error("Failed to parse stringified project value:",i)}const n=e?.projects||e?.items||e?.entries||(Array.isArray(e)?e:[]);return Array.isArray(n)?n:[]}async listProjects(){console.log("Listing projects for API key");const e=[`${this.baseUrl}listProjects`,"https://api.flutterflow.io/v2/l/listProjects"];let n=0,i="";for(const r of e){const s=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`},body:JSON.stringify({project_type:"ALL",deserialize_response:!0})});if(s.ok)return r!==e[0]&&console.log(`listProjects answered on legacy path ${r}`),this.parseProjectsResponse(await s.json());if(n=s.status,i=await s.text(),console.warn(`listProjects via ${r} returned ${n}: ${i}`),s.status===401||s.status===403)throw new Error(_w(s.status,i));if(s.status!==404)throw new Error(`List projects failed: ${s.status} - ${i}`)}throw new Error(`List projects failed: ${n} - ${i}`)}}function hl(t,e){const n=t.body?.getReader?.(),i=n?(async()=>{const r=new TextDecoder;let s="";for(;;){const{done:o,value:a}=await n.read();if(o)break;s+=r.decode(a,{stream:!0})}return s+r.decode()})():Promise.resolve("");return gc(i,e,(r,s)=>{try{n?.cancel()?.catch?.(()=>{})}catch{}s(new Error("The response body stalled before it finished."))})}async function ww(t,e=ip){const n=t.clone();let i;try{i=JSON.parse(await hl(t,e))}catch{let o="";try{o=await hl(n,e)}catch{}if(!t.ok)return{success:!1,responseCode:t.status,errorMessage:o||`HTTP ${t.status}`,errorMap:new Map};throw new at(`FlutterFlow accepted the sync but returned an unreadable response${o?`: ${o.slice(0,200)}`:"."}`)}if(!t.ok){let s=i.message||`HTTP ${t.status}`,o=new Map;if(i.errors)o=new Map(Object.entries(i.errors));else if(!i.message&&typeof i=="object"){const a=Object.keys(i).filter(l=>l.endsWith(".dart")&&Array.isArray(i[l]));a.length>0&&(o=new Map(Object.entries(i)),s=a.flatMap(u=>i[u].map(c=>`${u}: ${c.errorMessage}`)).join(` +`)||`HTTP ${t.status}`)}return{success:!1,responseCode:t.status,errorMessage:s,errorMap:o}}let r={};if(i.value)try{r=typeof i.value=="string"?JSON.parse(i.value):i.value}catch(s){console.warn("Ignoring malformed push response value:",s)}return{success:!0,responseCode:t.status,errorMap:new Map(Object.entries(r))}}function hc(t,e){return{401:"Authentication failed. Please check your FlutterFlow API key.",403:"Access denied. You may not have permission to modify this project.",404:"Project not found. Please check your Project ID.",409:"Conflict detected. The project may have been modified elsewhere.",422:"Validation failed: Invalid request format",429:"Rate limit exceeded. Please try again in a few minutes.",500:"FlutterFlow server error. Please try again later.",503:"FlutterFlow service temporarily unavailable."}[t]||`FlutterFlow API error: ${`HTTP ${t}`}`}const Z={ACTION:"A",WIDGET:"W",FUNCTION:"F",CODE_FILE:"C",DEPENDENCIES:"D",OTHER:"O"},Ap=/class\s+\w+\s+extends\s+(?:StatelessWidget|StatefulWidget)\b/,Pp=/extends\s+State<\w+>/;function bw(t,e=""){if(t==="pubspec.yaml")return Z.DEPENDENCIES;if(!t.endsWith(".dart")||t.endsWith("index.dart"))return Z.OTHER;if(t==="custom_functions.dart")return Z.FUNCTION;if(e){const n=Ap.test(e),i=Pp.test(e);if(n||i)return Z.WIDGET;if(/^\s*Future(?:<[^>]+>)?\s+\w+\s*\(/m.test(e))return Z.ACTION;if(e.match(/^\s*(String|int|double|bool|List|Map|dynamic|void)\s+\w+\s*\(/m))return Z.FUNCTION}return Z.CODE_FILE}function Fp(t,e){switch(e){case Z.ACTION:return`lib/custom_code/actions/${t}`;case Z.WIDGET:return`lib/custom_code/widgets/${t}`;case Z.FUNCTION:return"lib/flutter_flow/custom_functions.dart";case Z.CODE_FILE:return`lib/custom_code/${t}`;case Z.DEPENDENCIES:return"pubspec.yaml";case Z.OTHER:return`lib/custom_code/${t}`;default:return t}}async function pc(t,e=new Map){return gy(t,e)}const pl=new Map,di=new Map,fi=new Map;function Ir(t){return`${t.baseUrl}|${t.projectId}|${t.branchName}`}function Si(t){pl.delete(Ir(t))}function as(t,e,n){const i=Ir(t),r=di.get(i)??new Map;for(const{path:s,content:o}of e){const a=r.get(s)??new Map,l=a.get(o)??{uncertain:0,verified:0};n.uncertain&&(l.uncertain+=n.uncertain),n.verified&&(l.verified+=n.verified),l.uncertain<=0&&l.verified<=0?a.delete(o):a.set(o,l),a.size===0?r.delete(s):r.set(s,a)}r.size===0?di.delete(i):di.set(i,r)}function Ew(t,e){as(t,e,{uncertain:1})}function Sw(t){const e=Ir(t);fi.set(e,(fi.get(e)??0)+1)}function Md(t){const e=Ir(t),n=(fi.get(e)??0)-1;n<=0?fi.delete(e):fi.set(e,n)}function gc(t,e,n){return new Promise((i,r)=>{let s=!1;const o=(l,u,c)=>{s||(s=!0,c==="resolve"?i(u):r(u))},a=setTimeout(()=>{s||(s=!0,n(i,r))},e);t.then(l=>{clearTimeout(a),o(i,l,"resolve")},l=>{clearTimeout(a),o(r,l,"reject")})})}async function mc(t,e,n=np){const i={stop:!1},r=(async()=>{const s=await t.pushCode(e,i);return ww(s)})();return gc(r,n,(s,o)=>{i.stop=!0,Si(t),Sw(t),r.then(()=>Md(t),()=>Md(t)),o(new at("FlutterFlow did not answer the sync in time — the push may still have been applied. The outcome is not yet known: open your FlutterFlow project to reconcile before retrying the deploy."))})}async function vc(t,e,n,i,r="",s=np){const o=Jy(e,n);if(o.length===0)return{remoteFiles:n,syncFileMap:e,unverified:[],approximate:[]};const a=q_(o,r),l={...a.manifest,sources:a.sources},u=a.skipped.map(h=>h.reason);u.forEach(h=>console.warn(`[custom class deploy] ${h}`));const c=a.approximate;c.forEach(h=>console.warn(`[custom class deploy] ${h}`)),console.log(`Provisioning ${o.length} new FlutterFlow custom code file(s) before sync.`),He.set("provision");let d=!0,f,p;try{if(p=(async()=>{let h;try{h=await fetch(I0,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:t.apiKey,projectId:t.projectId,baseUrl:t.baseUrl,commitMessage:i,customClasses:o,verification:l,stream:!0})})}catch{throw new at("The provisioning request did not return a response. The deploy may have reached the FlutterFlow server — open your FlutterFlow project to reconcile before retrying.")}return V_(h,{onPhase:g=>{d&&He.setSubstatus(g)},onLog:g=>{d&&console.log(`[custom class deploy] ${g}`)}})})(),f=await gc(p,s,(h,g)=>{d=!1,g(new at("The deploy is still working on the FlutterFlow server, but this browser tab has stopped waiting. Your custom classes may or may not have been written — the outcome is not yet known. Open your FlutterFlow project to reconcile before retrying the deploy."))}),!f.finalResultReceived){if(vd(f)===Oe.FAILED)throw new Error(f.error||`FlutterFlow custom class provisioning failed (HTTP ${f.httpStatus}).`);const h=f.httpRejected&&typeof f.httpStatus=="number"?`The FlutterFlow deploy runner returned HTTP ${f.httpStatus} without reporting a result.`:"The connection to the FlutterFlow deploy runner dropped before it reported a result.";throw new at(`${h} The deploy may still be finishing on the server; open your FlutterFlow project to reconcile before retrying.`)}if(!f.success){const h=f.details?` ${f.details}`:"",g=`${f.error||"FlutterFlow custom class provisioning failed."}${h}`;throw vd(f)===Oe.UNCONFIRMED?new at(`${g} The failure arrived after the deploy began — custom classes may already be written. Open your FlutterFlow project to reconcile before retrying.`):new Error(g)}}catch(h){throw h instanceof at&&(Si(t),Ew(t,o),p?.then(g=>{g?.finalResultReceived&&g.success?as(t,o,{uncertain:-1,verified:1}):g?.finalResultReceived&&sp(g)&&as(t,o,{uncertain:-1})},()=>{})),h}return Si(t),as(t,o,{verified:1}),f.verificationSkipped&&(console.warn(`[custom class deploy] ${f.verificationSkipped}`),u.push(f.verificationSkipped)),{remoteFiles:n,syncFileMap:Zy(e,o),unverified:u,approximate:c,provisionSucceeded:!0}}async function yc(t,e={}){const n=Ir(t);let i=pl.get(n);if(i===void 0){try{i=await t.fetchProjectSource()}catch(u){throw new Error(`Could not read your project's pubspec.yaml (${u.message}). Deploy was stopped so your existing package dependencies aren't overwritten. Check your FlutterFlow API key and project, then try again.`)}const a=ep(i.pubspecYaml);if(!a.valid)throw new Error(`Your project's pubspec.yaml could not be read reliably (${a.errors.join("; ")}). Deploy was stopped so your existing package dependencies aren't overwritten.`);const l=di.get(n);if(l){for(const[u,c]of[...l]){const d=i.files.get(u);if(d!==void 0){const f=c.get(d);f&&(f.verified>0?(f.verified-=1,f.explainedByVerified=!0):f.explainedByVerified||(f.uncertain-=1),f.uncertain<=0&&f.verified<=0&&c.delete(d))}for(const[f,p]of[...c])p.verified=0,p.uncertain<=0&&c.delete(f);c.size===0&&l.delete(u)}l.size===0&&di.delete(n)}!di.has(n)&&!fi.has(n)&&pl.set(n,i)}const r=await c0(i.pubspecYaml,e),s=D_(i.pubspecYaml,r.overrides),o=B_(s.yaml,r.additions);return r.warnings.forEach(a=>console.warn(`[pubspec] ${a}`)),o.added.length>0&&console.log("Adding dependencies:",o.added.map(a=>{const l=r.additions[a],u=l?.sdk?`sdk: ${l.sdk}`:l||"any";return`${a}: ${u}`}).join(", "),r.sdk.dartSdkFloor?`(resolved for Dart ${r.sdk.dartSdkFloor})`:""),r.kept.forEach(({name:a,constraint:l})=>console.log(`Keeping your existing ${a}: ${l||"(non-version source)"}`)),{...o,overridden:s.overridden,warnings:r.warnings,remoteFiles:i.files}}function xw(t){const e=[],n=[];t.content.length>5e4&&n.push("Code file is large (>50KB). This may take longer to commit."),t.content.length>1e5&&e.push("Code file is too large (>100KB). Consider splitting into smaller components.");const i=t.content.split(` +`).length;i>500&&n.push(`Code has ${i} lines. Consider breaking it into smaller widgets.`),t.content.includes("setState")&&t.codeType===Z.ACTION&&n.push("Using setState in a Custom Action may not work as expected. Consider using a Custom Widget."),t.content.includes("dynamic")&&!t.content.includes("?")&&n.push('Code uses "dynamic" types. Consider adding explicit types for better null safety.'),t.content.match(/Color\(0xFF[0-9A-Fa-f]{6}\)/)&&n.push("Code contains hardcoded colors. Consider using FlutterFlowTheme.of(context) for theme consistency.");const r=t.content.match(/print\s*\(/g);r&&r.length>3&&n.push(`Code contains ${r.length} print statements. Consider removing debug prints before committing.`);const s=g_(t.content);if(s&&e.push(`FlutterFlow cannot format this code - ${s}. Fix or regenerate before committing.`),t.codeType===Z.WIDGET){const o=Wh(t.content),a=f_(t.fileName);if(o.length===0)e.push("No public widget class found (must extend StatelessWidget or StatefulWidget).");else if(!o.includes(a)){const l=`${qh(o[0])}`;e.push(`Widget class name "${o[0]}" does not match the file name "${t.fileName}". FlutterFlow derives the widget from the file name, so it will report "No widget ${a} found". Rename the file to "${l}" or the class to match before committing.`)}}return{canProceed:e.length===0,issues:e,warnings:n}}function Rp(t,e={}){const{artifactType:n="CustomWidget",artifactName:i="GeneratedCode",fileName:r}=e,s=u_(t);let o=r||i;if(n==="CustomFunction")o="custom_functions.dart";else if(n==="CustomWidget"){const u=Wh(s)[0],c=u?qh(u):null;c&&o!==c?(console.warn(`Commit file name "${o}" does not match declared widget class "${u}"; renaming to "${c}" so FlutterFlow can find the widget.`),o=c):o.endsWith(".dart")||(o+=".dart")}else o.endsWith(".dart")||(o+=".dart");let a=Z.CODE_FILE;switch(n){case"CustomAction":a=Z.ACTION;break;case"CustomWidget":a=Z.WIDGET;break;case"CustomFunction":a=Z.FUNCTION;break;case"CustomClass":case"CodeFile":a=Z.CODE_FILE;break}let l="";return a===Z.WIDGET?l=`// Automatic FlutterFlow imports +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +// Begin custom widget code +// DO NOT REMOVE OR MODIFY THE CODE ABOVE! + +`:a===Z.ACTION?l=`// Automatic FlutterFlow imports +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +// Begin custom action code +// DO NOT REMOVE OR MODIFY THE CODE ABOVE! + +`:a===Z.FUNCTION&&(l=`// Automatic FlutterFlow imports +import 'dart:convert'; +import 'dart:math' as math; + +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:intl/intl.dart'; +import 'package:timeago/timeago.dart' as timeago; +import '/flutter_flow/lat_lng.dart'; +import '/flutter_flow/place.dart'; +import '/flutter_flow/uploaded_file.dart'; + +`),{content:Ny(s,l),fileName:o,codeType:a,artifactType:n,artifactName:i}}function Iw(t){const e={};for(const n of Vl(t))e[n]="";return e}function kw(t,e={}){return{timestamp:new Date().toISOString(),artifactType:t.artifactType,artifactName:t.artifactName,codeType:t.codeType,fileName:t.fileName,generatedFrom:e.step1Result?"pipeline":"direct",model:e.selectedModel||"unknown",codeSize:t.content.length}}function Cw(t,e,n,i=new Set,r=""){const s=[],o=Ap.test(e),a=Pp.test(e);return n===Z.WIDGET&&!o&&!a&&s.push("No widget class definition found (must extend StatelessWidget or StatefulWidget)"),{valid:s.length===0,errors:s}}function uo(t){const e=[],n=[];if(!t||t.size===0)return e.push("No files to commit"),{valid:!1,errors:e,warnings:n};const i=new Set(Array.from(t.values()).flatMap(r=>Xs(r.content||"")));for(const[r,s]of t.entries()){if((!s.content||s.content.trim().length===0)&&e.push(`File ${r} is empty`),s.content&&s.content.length>1e5&&n.push(`File ${r} is very large (>100KB)`),r.endsWith(".dart")){const o=Cw(r,s.content,s.type,i,s.artifactName);o.valid||e.push(...o.errors.map(a=>`${r}: ${a}`))}if(r==="pubspec.yaml"){const o=ep(s.content);o.valid||e.push(...o.errors)}}return{valid:e.length===0,errors:e,warnings:n}}const ne={IDLE:"IDLE",PREPARING:"PREPARING",VALIDATING:"VALIDATING",PUSHING:"PUSHING",SUCCESS:"SUCCESS",ERROR:"ERROR"},Y={currentState:ne.IDLE,startTime:null,endTime:null,error:null,result:null,filesProcessed:0,totalFiles:0,reset(){this.currentState=ne.IDLE,this.startTime=null,this.endTime=null,this.error=null,this.result=null,this.filesProcessed=0,this.totalFiles=0},setState(t){if(!Object.values(ne).includes(t)){console.error(`Invalid commit state: ${t}`);return}this.currentState=t,t===ne.PREPARING&&(this.startTime=Date.now()),(t===ne.SUCCESS||t===ne.ERROR)&&(this.endTime=Date.now()),typeof window<"u"&&window.dispatchEvent&&window.dispatchEvent(new CustomEvent("commitStateChange",{detail:{state:t,commitState:this}})),console.log(`Commit state changed to: ${t}`)},setError(t){this.error=t,this.setState(ne.ERROR)},setSuccess(t){this.result=t,this.setState(ne.SUCCESS)},setProgress(t,e){this.filesProcessed=t,this.totalFiles=e},getElapsedTime(){return this.startTime?(this.endTime||Date.now())-this.startTime:null},isInProgress(){return this.currentState===ne.PREPARING||this.currentState===ne.VALIDATING||this.currentState===ne.PUSHING}};async function _c(t){const e=t!==void 0?t:await Le("flutterflow"),n=await Le("flutterflow_project_id");if(!e||!n)return"";if(fl(n,e))return n;const i=++ro,r=bt;let s=!1;try{s=(await new Jn(e,"","main",Ge()).listProjects()||[]).some(l=>(l.id||l.projectId)===n)}catch(o){const a=String(o&&o.message||"");if(!/denied \(403\)|without list permission/i.test(a))return"";s=!0}return r!==bt||e!==Ae||i<=hn||(hn=i,!s)?"":tt&&tt.projectId!==n&&fl(tt.projectId,e)?tt.projectId:((!tt||tt.projectId===n)&&_r(n,e,r),n)}async function Aw(t,e,n={}){let{codeType:i="W"}=n;const{pubspecDeps:r={},artifactName:s=e}=n;i==="CustomWidget"&&(i=Z.WIDGET),i==="CustomAction"&&(i=Z.ACTION),i==="CustomFunction"&&(i=Z.FUNCTION),i==="CustomClass"&&(i=Z.CODE_FILE),i==="CodeFile"&&(i=Z.CODE_FILE),Y.reset(),Y.setState(ne.PREPARING);try{const o=await Le("flutterflow"),a=Ge();let l=await _c(o);if((o!==Ae||a!==Ge())&&(l=""),!o)throw new Error("FlutterFlow API Key not configured. Please set your API key in the API Keys settings.");if(!l)throw new Error("No confirmed FlutterFlow project target. Choose a project from the loaded list in API Keys settings.");if(!oo(l))throw new Error("Invalid FlutterFlow Project ID format.");const u=new Jn(o,l,"main",a);Y.setState(ne.VALIDATING);const c=new Map,d=i||bw(e,t),f=Fp(e,d);c.set(e,{artifactName:s,content:t,type:d,path:f}),Y.setProgress(0,c.size);const p=uo(c);if(!p.valid)throw new Error(`Validation failed: +${p.errors.join(` +`)}`);const h=await yc(u,r),g=h.yaml,m=await vc(u,c,h.remoteFiles,`Provision ${s} custom class`,g),v=await pc(m.syncFileMap,m.remoteFiles),x=new Map(m.syncFileMap);x.set("pubspec.yaml",{content:g,type:"D",path:"pubspec.yaml"}),He.set("package");const E=await wc(x),y={project_id:l,zipped_custom_code:E,uid:`web_${Date.now()}`,branch_name:u.branchName,serialized_yaml:g,file_map:v.fileMapContents,functions_map:v.functionsMapContents};Y.setState(ne.PUSHING),Y.setProgress(1,c.size),Si(u),He.set("push");const b=await mc(u,y);if(b.success)Y.setSuccess({fileCount:c.size,projectId:l,warnings:b.errorMap&&b.errorMap.size>0?Array.from(b.errorMap.entries()):[]});else{const I=b.errorMessage||hc(b.responseCode),T=new Error(I);throw T.remoteRefusal=!0,T}return{success:!0,message:`Successfully committed ${e} to FlutterFlow project ${l}`,addedDependencies:h.added,unverified:m.unverified,approximate:m.approximate,warnings:b.errorMap?Array.from(b.errorMap.entries()):[]}}catch(o){return console.error("Commit failed:",o),Y.setError(o),o instanceof at?{success:!1,unconfirmed:!0,error:o.message,state:Y.currentState}:{success:!1,error:o.message,remoteRefusal:o.remoteRefusal===!0,state:Y.currentState}}}async function wc(t){const e=new JSZip;for(const[n,i]of t.entries())e.file(n,i.content);return e.generateAsync({type:"base64",compression:"DEFLATE",compressionOptions:{level:6}})}async function Pw(t,e={}){const{artifactType:n,artifactName:i,fileName:r,pipelineResult:s}=e;console.log(`Starting commit for ${i} (${n})`);let o=!1;const a={projectId:null,endpoint:Ge(),artifactType:n,artifactName:i,fileName:r};try{Y.setState(ne.PREPARING);const l=Rp(t,{artifactType:n,artifactName:i,fileName:r}),u=Iw(l.content);console.log("Detected dependencies:",u),Y.setState(ne.VALIDATING);const c=await Le("flutterflow"),d=Ge(),f=await Le("flutterflow_project_id");let p=ir||await _c(c);if((c!==Ae||d!==Ge())&&(p=""),!c)throw new Error("FlutterFlow API Key not configured. Please add it in API Keys settings.");if(!p)throw new Error(f?"The FlutterFlow project target is not confirmed for your current API key. Reopen the deploy dialog and choose a project from the loaded list.":"FlutterFlow Project ID not configured. Please add it in API Keys settings.");if(!oo(p))throw new Error("Invalid FlutterFlow Project ID format.");a.projectId=p;const h=new Map;h.set(l.fileName,{artifactName:i,content:l.content,type:l.codeType,path:Fp(l.fileName,l.codeType),functionName:l.codeType===Z.FUNCTION?i:void 0}),Y.setProgress(0,h.size);const g=uo(h);if(!g.valid)throw new Error(`File validation failed: +${g.errors.join(` +`)}`);g.warnings.length>0&&console.warn("Validation warnings:",g.warnings),Y.setState(ne.PUSHING);const m=new Jn(c,p,"main",d),v=await yc(m,u),x=v.yaml,E=await vc(m,h,v.remoteFiles,`Provision ${i} custom class`,x);o=E.provisionSucceeded===!0;const y=await pc(E.syncFileMap,E.remoteFiles),b=new Map(E.syncFileMap);b.set("pubspec.yaml",{content:x,type:Z.DEPENDENCIES,path:"pubspec.yaml"}),He.set("package");const I=await wc(b),T={project_id:p,zipped_custom_code:I,uid:`web_${Date.now()}`,branch_name:m.branchName,serialized_yaml:x,file_map:y.fileMapContents,functions_map:y.functionsMapContents};Y.setProgress(1,h.size),Si(m),He.set("push");const S=await mc(m,T);if(S.success){const C={...kw(l,s),projectId:p};return Y.setSuccess({...C,fileCount:h.size,warnings:S.errorMap?Array.from(S.errorMap.entries()):[]}),{success:!0,message:`Successfully committed ${l.fileName} to FlutterFlow`,metadata:C,targetIdentity:a,addedDependencies:v.added,unverified:E.unverified,approximate:E.approximate,warnings:S.errorMap?Array.from(S.errorMap.entries()):[],elapsedTime:Y.getElapsedTime()}}else{const C=S.errorMessage||hc(S.responseCode),R=new Error(C);throw R.errorMap=S.errorMap,R.remoteRefusal=!0,R}}catch(l){console.error("Commit execution failed:",l),Y.setError(l);let u=new Map;if(l.errorMap)u=l.errorMap;else if(l.message&&l.message.includes("{"))try{const c=l.message.match(/\{[\s\S]*\}/);if(c){const d=JSON.parse(c[0]);u=new Map(Object.entries(d))}}catch(c){console.warn("Failed to parse error map from commit response:",c)}return l instanceof at?{success:!1,unconfirmed:!0,error:l.message,errorMap:u,targetIdentity:a,state:Y.currentState,elapsedTime:Y.getElapsedTime()}:o?{success:!1,partial:!0,error:l.message,errorMap:u,targetIdentity:a,state:Y.currentState,elapsedTime:Y.getElapsedTime()}:{success:!1,error:l.message,errorMap:u,remoteRefusal:l.remoteRefusal===!0,targetIdentity:a,state:Y.currentState,elapsedTime:Y.getElapsedTime()}}}async function Fw(t,e={}){const{pipelineResult:n}=e;let i=!1;const r={projectId:null,endpoint:Ge(),artifactType:"Bundle",artifactName:t?.title,fileName:t?.fileEntries?`${t.fileEntries.length} artifacts`:"bundle"};try{if(Y.setState(ne.PREPARING),t.errors?.length>0)throw new Error(`Bundle validation failed: +${t.errors.join(` +`)}`);const s=new Map(t.fileEntries.map(I=>[I.fileName,{artifactId:I.artifactId,artifactName:I.artifactName,content:I.content,type:I.type,path:I.path,functionName:I.type===Z.FUNCTION?I.artifactName:void 0}]));Y.setProgress(0,s.size);const o=uo(s);if(!o.valid)throw new Error(`File validation failed: +${o.errors.join(` +`)}`);Y.setState(ne.VALIDATING);const a=await Le("flutterflow"),l=Ge(),u=await Le("flutterflow_project_id");let c=ir||await _c(a);if((a!==Ae||l!==Ge())&&(c=""),!a)throw new Error("FlutterFlow API Key not configured. Please add it in API Keys settings.");if(!c)throw new Error(u?"The FlutterFlow project target is not confirmed for your current API key. Reopen the deploy dialog and choose a project from the loaded list.":"FlutterFlow Project ID not configured. Please add it in API Keys settings.");if(!oo(c))throw new Error("Invalid FlutterFlow Project ID format.");r.projectId=c,Y.setState(ne.PUSHING);const d=new Jn(a,c,"main",l),f=await yc(d,t.dependencies),p=f.yaml,h=await vc(d,s,f.remoteFiles,`Provision ${t.title} custom classes`,p);i=h.provisionSucceeded===!0;const g=await pc(h.syncFileMap,h.remoteFiles),m=new Map(h.syncFileMap);m.set("pubspec.yaml",{content:p,type:Z.DEPENDENCIES,path:"pubspec.yaml"}),He.set("package");const v=await wc(m),x={project_id:c,zipped_custom_code:v,uid:`web_${Date.now()}`,branch_name:d.branchName,serialized_yaml:p,file_map:g.fileMapContents,functions_map:g.functionsMapContents};Y.setProgress(1,s.size),Si(d),He.set("push");const E=await mc(d,x);if(E.success){const I={...n,artifactType:"Bundle",artifactName:t.title,fileName:`${t.fileEntries.length} artifacts`,codeSize:t.fileEntries.reduce((T,S)=>T+S.content.length,0),projectId:c};return Y.setSuccess({...I,fileCount:s.size,warnings:E.errorMap?Array.from(E.errorMap.entries()):[]}),{success:!0,message:`Successfully committed ${t.fileEntries.length} artifacts to FlutterFlow`,metadata:I,targetIdentity:r,addedDependencies:f.added,unverified:h.unverified,approximate:h.approximate,warnings:E.errorMap?Array.from(E.errorMap.entries()):[],elapsedTime:Y.getElapsedTime()}}const y=E.errorMessage||hc(E.responseCode),b=new Error(y);throw b.errorMap=E.errorMap,b.remoteRefusal=!0,b}catch(s){console.error("Bundle commit execution failed:",s),Y.setError(s);const o=s.errorMap||new Map;return s instanceof at?{success:!1,unconfirmed:!0,error:s.message,errorMap:o,targetIdentity:r,state:Y.currentState,elapsedTime:Y.getElapsedTime()}:i?{success:!1,partial:!0,error:s.message,errorMap:o,targetIdentity:r,state:Y.currentState,elapsedTime:Y.getElapsedTime()}:{success:!1,error:s.message,errorMap:o,targetIdentity:r,state:Y.currentState,elapsedTime:Y.getElapsedTime()}}}async function Rw(t,e=[]){const n=Hl("architect");try{return await Vs("architect",mp,iy(t),n,e)}catch(i){throw i.isModelArmor||i.isUsageLimit||i.isPipelineCancel?i:new Error(`Prompt Architect failed: ${i.message}`)}}async function fo(t,e,n=[],i){const r=ry(t),s=Hl("generator",_.bundleSpec);try{return await Vs("generator",e,r,s,n)}catch(o){if(o.isModelArmor||o.isUsageLimit||o.isPipelineCancel)throw o;if(e!==Vr){console.warn(`Code Generator failed with ${e}, retrying with fallback model:`,o.message),Nb(e,Vr,i);try{return await Vs("generator",Vr,r,s,n)}catch(a){throw a.isModelArmor||a.isUsageLimit||a.isPipelineCancel?a:new Error(`Code Generator failed: primary (${e}): ${o.message} | fallback (${Vr}): ${a.message}`)}}throw new Error(`Code Generator failed: ${o.message}`)}}async function ho(t,e=null){const n={...Hl("review",_.artifactBundle||_.bundleSpec),architect_output:e};try{return await Vs("review",vp,sy(t),n)}catch(i){throw i.isModelArmor||i.isUsageLimit||i.isPipelineCancel?i:new Error(`Code Review failed: ${i.message}`)}}function qs(t,e){const n=document.getElementById(`step${t}-item`),i=document.getElementById(`step${t}-status`);!n||!i||(n.classList.remove("active","completed","error"),i.classList.remove("running","completed","error"),e==="active"?(n.classList.add("active"),i.classList.add("running"),i.innerHTML=` + + `):e==="completed"?(n.classList.add("completed"),i.classList.add("completed"),i.innerHTML=` + + `):e==="error"?(n.classList.add("error"),i.classList.add("error"),i.innerHTML=` + + `):i.innerHTML=` + + `)}function Me(t,e){const n=document.getElementById(`step${t}-loading`),i=document.getElementById(`step${t}-result`);e?(n.classList.remove("hidden"),i.classList.add("hidden"),qs(t,"active")):(n.classList.add("hidden"),i.classList.remove("hidden"),qs(t,"completed"))}function Tw(t){const e=document.getElementById(`${t}-content`),n=document.getElementById(`${t}-chevron`);e.classList.contains("open")?(e.classList.remove("open"),n&&(n.style.transform="rotate(0deg)")):(e.classList.add("open"),n&&(n.style.transform="rotate(180deg)"))}function Mw(t){dt(parseInt(t.replace("step","")))}function dt(t){for(let o=1;o<=3;o++){const a=document.getElementById(`step${o}-item`);a&&a.classList.remove("active")}const e=document.getElementById(`step${t}-item`);e&&e.classList.add("active"),Yn();const n=document.getElementById("ready-state");n&&n.classList.add("hidden");for(let o=1;o<=3;o++){const a=document.getElementById(`step${o}-content`);a&&a.classList.add("hidden")}const i=document.getElementById(`step${t}-content`);i&&i.classList.remove("hidden");const r=document.getElementById("stage-title"),s={1:"Prompt Architect",2:"Code Generator",3:"Code Review"};r&&(r.textContent=s[t]||"Active Workflow Stage")}function $w(t){const e=document.getElementById(t);if(!e)return;const n=e.dataset.raw||e.textContent;navigator.clipboard.writeText(n).then(()=>{const r=e.closest(".code-container")?.querySelector(".copy-btn");r&&(r.classList.add("copied"),r.innerHTML=' Copied!',setTimeout(()=>{r.classList.remove("copied"),r.innerHTML=' Copy'},2e3))}).catch(i=>{console.warn("Failed to copy to clipboard:",i)})}function gl(t){const e=ml(t);console.log(`Step 1 (Prompt Architect): ${on(mp)}`),console.log(e!==t?`Step 2 (Code Generator): ${on(t)} → ${on(e)} (Free Tier fallback)`:`Step 2 (Code Generator): ${on(t)}`),console.log(`Step 3 (Code Review): ${on(vp)}`)}function Tp(){return{step1Result:_.step1Result,step2Result:_.step2Result,step3Result:_.step3Result,artifactBundle:_.artifactBundle,bundleReview:_.bundleReview,selectedArtifactId:_.selectedArtifactId,resultsViewMode:_.resultsViewMode}}function Lw(t){if(!t)return;Object.assign(_,t),new Set((_.artifactBundle?.artifacts||[]).map(n=>n.id)).has(_.selectedArtifactId)||(_.selectedArtifactId=_i(_.artifactBundle)?.id||null)}const Mp="results-replacement-error";function Nw(t,{stage:e=2,runId:n,retry:i}){if(!le(n))return;const r=document.getElementById(Mp);if(!r)return;const s=ap(t),o=document.getElementById("results-replacement-error-title"),a=document.getElementById("results-replacement-error-message"),l=document.getElementById("results-replacement-error-retry"),u=document.getElementById("results-replacement-error-upgrade");o&&(o.textContent=`${vo[e]||"Regeneration"}: ${s.title}`),a&&(a.textContent=s.message),r.hidden=!1;let c=null;u&&(u.hidden=!s.canUpgrade,s.canUpgrade&&(u.textContent="View plans",u.onclick=()=>xi(),c=u)),l&&(l.hidden=s.canUpgrade,s.canUpgrade||(l.onclick=()=>{bc(),typeof i=="function"&&i()},l.textContent="Retry",c=l)),(c||r).focus({preventScroll:!0})}function bc(){const t=document.getElementById(Mp);t&&(t.hidden=!0)}function $p(t,{previous:e,stage:n,runId:i,retry:r}){le(i)&&(t.isUsageLimit&&En(),Lw(e),Ci(),Wt(!0),Fr(),_.resultsViewMode=e.resultsViewMode||"summary",Pr(),An(),Nw(t,{stage:n,runId:i,retry:r}),vn())}async function Lp(){if(console.log("runRefinement called"),_.isRunning)return;const t=document.getElementById("code-generator-model").value;_.isRunning=!0;const e=yo();Ec("standardRegenerate",_.step2Result,_.step1Result);const n=document.querySelectorAll(".btn-refine-action"),i=Tp();n.forEach(r=>{r.disabled=!0,r.innerHTML=` + + + Refining...`});try{bc();const r=dc(),s=r.id,o=oy({bundleSpec:_.step1Result,artifactBundle:JSON.stringify(_.artifactBundle||_.step2Result),bundleReview:_.step3Result,artifactId:r.id,userFeedback:"Fix the issues listed in the audit report."});bo({runId:e}),jt(2,e),dt(2),Me(2,!0);const a=await fo(o,t,[],e);if(!le(e))return;_.step2Result=a,lo(),gn(2,e);const l=document.getElementById("step2-output"),u=bi(_.step2Result);l.textContent=u,l.dataset.raw=u,Me(2,!1),dt(3),jt(3,e),Me(3,!0);const c=await ho(_.step2Result,_.step1Result);if(!le(e))return;_.step3Result=c,co(),gn(3,e),_.artifactBundle?.artifacts?.some(p=>p.id===s)?_.selectedArtifactId=s:_.selectedArtifactId=_i(_.artifactBundle)?.id||null;const d=document.getElementById("step3-output");d.textContent=_.step3Result,Me(3,!1),Ci();const f=io(_.step3Result);Fr(u,f)}catch(r){if(console.error("Refinement failed:",r),!le(e))return;const s=no(r,{architect:2,generator:2,review:3});$p(r,{previous:i,stage:s,runId:e,retry:Lp})}finally{n.forEach(r=>{r.disabled=!1,r.textContent="Refine & Regenerate"}),le(e)&&(_.isRunning=!1,vn())}}async function Ec(t,e,n){const i=`${At}/connectFeedback`,r={type:t,code:e,input:n};try{const s=await fetch(i,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)});if(!s.ok){const a=await s.text();return console.error(`callEndpoint failed: ${s.status} ${s.statusText}`,a),{success:!1,status:s.status,error:a}}const o=await s.json();return console.log("Telemetry success:",o),o}catch(s){return console.error("callEndpoint failed:",s),{success:!1,error:s.message}}}function Ow(){const t=document.getElementById("ff-error-paste-input");t&&(t.value="")}async function Np(){const t=document.getElementById("ff-error-paste-input"),e=t?.value?.trim();if(!e){t?.focus(),t?.classList.add("ring-2","ring-red-400","border-red-300"),setTimeout(()=>t?.classList.remove("ring-2","ring-red-400","border-red-300"),2e3);return}if(!_.step2Result){Ie("No generated code found. Please run the full pipeline first.","warning");return}if(_.isRunning)return;const n=document.getElementById("code-generator-model").value;_.isRunning=!0;const i=yo();Ec("flutterflowError",_.step2Result,e);const r=document.getElementById("btn-fix-from-errors");r&&(r.disabled=!0,r.innerHTML=` + + Fixing…`);const s=Tp();try{bc();const o=Nh({bundleSpec:_.step1Result,artifactBundle:JSON.stringify(_.artifactBundle||_.step2Result),bundleReview:_.step3Result,userFeedback:e});hg(),bo({runId:i}),jt(2,i),dt(2),Me(2,!0);const a=await fo(o,n,[],i);if(!le(i))return;_.step2Result=a,lo(),gn(2,i);const l=document.getElementById("step2-output"),u=bi(_.step2Result);l.textContent=u,l.dataset.raw=u,Me(2,!1),dt(3),jt(3,i),Me(3,!0);const c=await ho(_.step2Result,_.step1Result);if(!le(i))return;_.step3Result=c,co(),gn(3,i);const d=document.getElementById("step3-output");d.textContent=_.step3Result,Me(3,!1),Ci();const f=io(_.step3Result);Fr(u,f),t&&(t.value="")}catch(o){if(console.error("Fix from errors failed:",o),!le(i))return;const a=no(o,{architect:2,generator:2,review:3});$p(o,{previous:s,stage:a,runId:i,retry:Np})}finally{r&&(r.disabled=!1,r.textContent="Fix Errors & Regenerate"),le(i)&&(_.isRunning=!1,vn())}}async function br(){if(console.log("runThinkingPipeline called"),_.isRunning)return;localStorage.setItem("hasSeenWalkthrough","true");const t=document.getElementById("pipeline-input").value,e=document.getElementById("code-generator-model").value,n=Ue.slice();if(!t.trim()){Ie("Please describe your FlutterFlow widget first.","warning");return}_.isRunning=!0;const i=yo();try{if(await rl,!le(i)||(kn.length&&await Promise.allSettled(kn.map(E=>E.job)),!le(i))||!await ab()||!le(i)||(await tb(),!le(i)))return;const r=ml(e);t.length,mw(),_.submittedPrompt=t,_.submittedImages=n.filter(E=>E.url),Gs(!0),gl(r),Yn();const s=document.getElementById("ready-state");s&&s.classList.add("hidden");const o=document.getElementById("paywall-exhausted");o&&o.classList.add("hidden");const a=document.getElementById("composer")?.getBoundingClientRect(),l=document.getElementById("hero")?.getBoundingClientRect();bo({prompt:t,runId:i}),jb(a,l),dt(1),jt(1,i),Me(1,!0);const u=_.submittedImages.map(E=>({url:E.url})),c=await Rw(t,u);if(!le(i))return;_.step1Result=c,vw(),gn(1,i);const d=document.getElementById("step1-output"),f=bi(_.step1Result);d.textContent=f,d.dataset.raw=f,Me(1,!1),dt(2),jt(2,i),Me(2,!0);const p=await fo(_.step1Result,r,u,i);if(!le(i))return;_.step2Result=p,lo(),gn(2,i);const h=document.getElementById("step2-output"),g=bi(_.step2Result);h.textContent=g,h.dataset.raw=g,Me(2,!1),dt(3),jt(3,i),Me(3,!0);const m=await ho(_.step2Result,_.step1Result);if(!le(i))return;_.step3Result=m,co(),gn(3,i);const v=document.getElementById("step3-output");v.textContent=_.step3Result,Me(3,!1),Ci();const x=io(_.step3Result);Fr(g,x)}catch(r){if(r.isPipelineCancel||console.error("Pipeline failed:",r),!le(i))return;const s=no(r,{architect:1,generator:2,review:3});r.isUsageLimit?En():(r.message,ml(document.getElementById("code-generator-model").value),void 0),dt(s),Me(s,!1),cg(r,{stage:s,runId:i}),qs(s,"error")}finally{le(i)&&(_.isRunning=!1,Gs(!1),vn())}}function Bw(){const t=document.getElementById("code-generator-model").value,e=[Ds,"anthropic/claude-opus-5","openai/gpt-5.6-sol"].filter(i=>i!==t),n=prompt(`Retry with different model? + +Current: ${t} + +Options: +1. ${e[0]} +2. ${e[1]} + +Enter 1 or 2:`);n==="1"?(document.getElementById("code-generator-model").value=e[0],br()):n==="2"&&(document.getElementById("code-generator-model").value=e[1],br())}async function Dw(){const t=fc();if(!t){Ie("No code to commit. Please run the pipeline first.","warning");return}const e=await Le("flutterflow"),n=await Le("flutterflow_project_id");if(!e||!n){Ie("FlutterFlow credentials not configured. Add your API Key and Project ID in settings.","warning"),ac();return}if(_.artifactBundle?.artifacts?.length>1){await jw();return}const{artifactType:i,artifactName:r,fileName:s}=Cp(),o=Rp(t,{artifactType:i,artifactName:r,fileName:s}),a=xw(o);if(!a.canProceed){Ie(`Pre-commit checks failed: ${a.issues.join("; ")}`,"error");return}Ic(o,a,null,null)}async function jw(){const t=await Le("flutterflow"),e=await Le("flutterflow_project_id");if(!t||!e){Ie("FlutterFlow credentials not configured. Add your API Key and Project ID in settings.","warning"),ac();return}const n=Vy(_.artifactBundle);if(n.errors.length>0){Ie(`Bundle validation failed: ${n.errors.join("; ")}`,"error");return}const i=new Map(n.fileEntries.map(a=>[a.fileName,{content:a.content,type:a.type,path:a.path}])),r=uo(i),s={canProceed:r.valid&&n.errors.length===0,issues:[...n.errors,...r.errors],warnings:[...n.warnings,...r.warnings]};if(!s.canProceed){Ie(`Bundle validation failed: ${s.issues.join("; ")}`,"error");return}const o={content:n.fileEntries.map(a=>`// ${a.fileName} +${a.content}`).join(` + +`),fileName:`${n.fileEntries.length} files`,codeType:"bundle",artifactType:"Bundle",artifactName:n.title};Ic(o,s,n.dependencies,n)}function Uw(t){let e=t.errorMap||new Map;!(e instanceof Map)&&typeof e=="object"&&(e=new Map(Object.entries(e)));let n=`
    +

    FlutterFlow Commit Failed

    +

    ${W(t.error)}

    `;if(e&&e.size>0){n+=`
    +

    Errors:

    +
      `;for(const[r,s]of e.entries()){const o=Kl(s);n+=`
    • + ${W(r)}: ${W(o)} +
    • `}n+="
    "}n+="
    ",n+=`
    + +
    `;const i=document.getElementById("step3-output");i&&(i.innerHTML=n,document.getElementById("btn-regenerate-from-error")?.addEventListener("click",()=>{Op(t.error,e)}))}async function Op(t,e){if(_.isRunning)return;const n=document.getElementById("code-generator-model").value;_.isRunning=!0;const i=yo(),r=document.getElementById("btn-regenerate-from-error");r&&(r.disabled=!0,r.innerHTML=` + + Fixing...`);try{let s=`The previous code had the following errors when committing to FlutterFlow: + +`;if(e&&e.size>0)for(const[p,h]of e.entries()){const g=Kl(h);s+=`File: ${p} +Error: ${g} + +`}else s+=`${t} +`;const o=Nh({bundleSpec:_.step1Result,artifactBundle:JSON.stringify(_.artifactBundle||_.step2Result),bundleReview:_.step3Result,userFeedback:s});bo({runId:i}),jt(2,i),dt(2),Me(2,!0);const a=await fo(o,n,[],i);if(!le(i))return;_.step2Result=a,lo(),gn(2,i);const l=document.getElementById("step2-output"),u=bi(_.step2Result);l.textContent=u,l.dataset.raw=u,Me(2,!1),dt(3),jt(3,i),Me(3,!0);const c=await ho(_.step2Result,_.step1Result);if(!le(i))return;_.step3Result=c,co(),gn(3,i);const d=document.getElementById("step3-output");d.textContent=_.step3Result,Me(3,!1),Ci();const f=io(_.step3Result);Fr(u,f)}catch(s){if(console.error("Regeneration failed:",s),!le(i))return;const o=no(s,{architect:2,generator:2,review:3});s.isUsageLimit&&En(),dt(o),Me(o,!1),cg(s,{stage:o,runId:i,retry:()=>Op(t,e)}),qs(o,"error")}finally{r&&(r.disabled=!1,r.textContent="Fix Errors & Regenerate"),le(i)&&(_.isRunning=!1,vn())}}async function Hw(){const t=document.getElementById("ff-status-dot"),e=document.getElementById("ff-status-text");if(!t||!e)return;const n=await Le("flutterflow"),i=await Le("flutterflow_project_id");n&&i?(t.className="w-2 h-2 rounded-full bg-green-500",e.textContent="FlutterFlow credentials configured",e.className="text-green-600"):n||i?(t.className="w-2 h-2 rounded-full bg-yellow-500",e.textContent="FlutterFlow credentials incomplete",e.className="text-yellow-600"):(t.className="w-2 h-2 rounded-full bg-red-500",e.textContent="FlutterFlow credentials not configured",e.className="text-red-600")}async function Bp(t){try{const e=await fetch(`${At}/auth/send-magic-link`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:t})});if(!e.ok)throw new Error(`Failed to send magic link: HTTP ${e.status}`);return e.json()}catch(e){throw console.error("sendMagicLink failed:",{email:t,message:e.message,stack:e.stack}),e}}async function Ww(t){try{const n=await(await fetch(`${At}/auth/verify-magic-link`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:t})})).json();if(n.error||!n.email||!n.sessionToken)throw new Error(n.error||"Invalid or expired link");return n}catch(e){throw console.error("verifyMagicLink failed:",{message:e.message,stack:e.stack}),e}}async function qw(t){try{const e=await fetch(`${At}/auth/refresh-session`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionToken:t})});if(!e.ok)return console.error("refreshSession: non-OK response",{url:`${At}/auth/refresh-session`,status:e.status}),null;const n=await e.json();return n.error||!n.email||!n.sessionToken?(console.warn("refreshSession: validation failed",{error:n.error,hasEmail:!!n.email,hasToken:!!n.sessionToken}),null):n}catch(e){return console.error("refreshSession: fetch failed",{url:`${At}/auth/refresh-session`,message:e.message,stack:e.stack}),null}}function $d(t,e){const n=jp(),i=(H.email||n.email)!==t;H.email=t,H.sessionToken=e,H.isVerified=!0,he=Kn({isLoading:!0}),localStorage.setItem(Ns,JSON.stringify({email:t,sessionToken:e})),i&&Vp()}function Dp(){H.email=null,H.sessionToken=null,H.isVerified=!1,he=Kn({isResolved:!0}),localStorage.removeItem(Ns),localStorage.removeItem(Bs)}function jp(){try{const t=localStorage.getItem(Ns);if(!t)return{email:null,sessionToken:null};const e=JSON.parse(t);return!e.email||!e.sessionToken?{email:null,sessionToken:null}:e}catch(t){return console.warn("getStoredSession: failed to parse auth session:",t),localStorage.removeItem(Ns),{email:null,sessionToken:null}}}async function zw(){const e=new URLSearchParams(window.location.search).get("token");if(e){window.history.replaceState({},"",window.location.pathname+window.location.hash);try{const{email:n,sessionToken:i}=await Ww(e);$d(n,i),Up();const r=Ld();r&&!window.location.hash&&(window.location.hash=r)}catch(n){Ld();const i=n.message||"Sign-in link invalid or expired.";Ie(i,"error"),po(),ai(i,"error")}}else{const{email:n,sessionToken:i}=jp();if(n&&i){const r=await qw(i);r?$d(r.email,r.sessionToken):Dp()}}Sc()}function Vw(){try{localStorage.setItem(il,JSON.stringify({hash:window.location.hash||"#home",ts:Date.now()}))}catch(t){console.warn("rememberSignInReturnSurface: failed to persist return surface:",t)}}function Ld(){try{const t=localStorage.getItem(il);if(localStorage.removeItem(il),!t)return null;const{hash:e,ts:n}=JSON.parse(t);return!e||typeof n!="number"||Date.now()-n>k0?null:e}catch(t){return console.warn("consumeSignInReturnSurface: failed to read return surface:",t),null}}function po(){const t=document.getElementById("signin-modal");if(!t)return;Vw(),document.getElementById("signin-email-input")?.removeAttribute("aria-invalid"),ai(""),Ke(t)}function Up(t){if(t&&t.target!==t.currentTarget)return;const e=document.getElementById("signin-modal");e&&Ye(e)}function ai(t,e){const n=document.getElementById("signin-message");n&&(n.textContent=t||"",n.classList.remove("signin-message-success","signin-message-error"),e&&n.classList.add(`signin-message-${e}`))}async function Gw(){const t=document.getElementById("signin-email-input"),e=document.getElementById("signin-submit-btn"),n=eo(t?.value);if(!n||!/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(n)||n.length>254){t?.setAttribute("aria-invalid","true"),ai("Please enter a valid email address.","error");return}t?.removeAttribute("aria-invalid"),e&&(e.disabled=!0,e.textContent="Sending…");const r=zh(n);r&&ai(r,"error");try{const s=await Bp(n),o=Yl(s);t&&o&&(t.value=""),t?.setAttribute("aria-invalid",String(!o)),ai(Vh(s,n),o?"success":"error"),e&&(e.disabled=!1,e.textContent=o?"Sent!":"Send Sign-in Link",o&&setTimeout(()=>{e.textContent==="Sent!"&&(e.textContent="Send Sign-in Link")},2500))}catch(s){console.error("handleMagicLinkRequest: sendMagicLink failed",{email:n,err:s}),ai("Something went wrong. Please try again.","error"),e&&(e.disabled=!1,e.textContent="Send Sign-in Link")}}function Kw(){H.email=null,H.sessionToken=null,H.isVerified=!1,he=Kn({isResolved:!0}),F_({storage:window.localStorage,onIdentityChanged:Sc,onPlanChanged:mo})}const Yw=T_({sendLink:Bp,getEmail:()=>H.email||"",onState:Jw});function Jw(t){const e=document.getElementById("send-new-link-btn"),n=document.getElementById("send-new-link-msg");if(!e||!n)return;if(t.status==="pending"){e.disabled=!0,e.textContent="Sending…",n.className="acct-access-msg",n.textContent="Sending a fresh sign-in link…";return}if(t.status==="sent"){e.disabled=!1,e.textContent="Send new link",n.className="acct-access-msg",n.textContent=Vh(t.data,H.email||"")||"Link sent — check your email.";return}e.disabled=!1,e.textContent="Send new link",n.className="acct-access-msg error";const i=t.error?.message?`Couldn't send a link right now. ${t.error.message}`:"Couldn't send a link right now. Please try again.";n.textContent=i}async function Zw(){await Yw()}function Xw(){const t=A_(window.localStorage),e=t.length?`Cleared disposable UI caches: ${t.join(", ")}.`:"Nothing disposable to clear.";Ie(`${e} Your run count, identity and stored keys are kept.`,"info")}function Qw(){const t=document.getElementById("delete-unavailable-modal");t&&Ke(t,{trigger:document.activeElement})}function eb(t){if(t&&t.target!==t.currentTarget)return;const e=document.getElementById("delete-unavailable-modal");e&&Ye(e)}function Sc(){const t=H.isVerified&&!!H.email,e=document.getElementById("auth-signedout"),n=document.getElementById("auth-signedin"),i=document.getElementById("auth-guest-usage");e&&e.classList.toggle("hidden",t),n&&n.classList.toggle("hidden",!t),i&&i.classList.toggle("hidden",t);const r=document.getElementById("auth-user-email");r&&(r.textContent=H.email||"");const s=document.getElementById("access-signed-email");s&&(s.textContent=H.email||""),ub(),mo()}async function Hp(){try{if(typeof FingerprintJS>"u"){console.warn("resolveIdentity: FingerprintJS not loaded, skipping");return}const e=await(await FingerprintJS.load()).get(),n=e.visitorId,i=await fetch(F0,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({fingerprint:e.visitorId,cookie_id:n})});if(!i.ok)throw new Error(`Identity check HTTP ${i.status}`);const r=await i.json();if(xt.userId=r.user_id,xt.token=r.identity_token||null,xt.status=r.status,xt.resolved=!0,sessionStorage.setItem(A0,r.user_id),xt.token&&sessionStorage.setItem(P0,xt.token),r.usage_count!==void 0){const s=Cn(),a=(r.usage_month||s)===s?r.usage_count:0;localStorage.setItem(Wn,JSON.stringify({count:a,month:s})),En()}console.log(`Identity resolved: ${r.status} (${r.user_id.slice(0,8)}...) usage: ${r.usage_count??"n/a"}`)}catch(t){console.error("resolveIdentity failed:",t)}}let da=null;function tb(t=5e3){return xt.resolved?Promise.resolve():(da||(da=Hp().catch(e=>{console.warn("ensureIdentityReady: identity resolution failed",e)})),Promise.race([da,new Promise(e=>setTimeout(e,t))]))}function Wp(){const t=Cn();try{const e=localStorage.getItem(Wn);return e?JSON.parse(e):{count:0,month:t}}catch(e){return console.warn("getUsageData: failed to parse usage storage",{key:Wn,month:t,err:e}),localStorage.removeItem(Wn),{count:0,month:t}}}function Cn(){const t=new Date;return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}`}function kr(){const t=Wp();return t.month!==Cn()?{count:0,month:Cn()}:t}function nb(){const e={count:kr().count+1,month:Cn()};return localStorage.setItem(Wn,JSON.stringify(e)),e}function ki(){return!!he.isLoading}function Ht(){return!!he.isResolved}function ib(t){if(!t)return null;const e=String(t).toLowerCase().replace(/[^a-z0-9]+/g,"_");return e==="pro"||e==="professional_plan"?"professional":e==="power_developer"||e==="power_plan"?"power":Object.prototype.hasOwnProperty.call(Os,e)?e:null}function rb(t){return t&&Object.entries(dp).find(([,e])=>e===t)?.[0]||null}function Gr(...t){return t.find(e=>e!=null&&e!=="")}function sb(...t){return t.find(e=>e&&typeof e=="object")||{}}function ob(t){const e=t.data&&typeof t.data=="object"?t.data:t,n=sb(e.subscription,e.stripeSubscription,e.currentSubscription,e.customer?.subscriptions?.data?.[0],e.subscriptions?.data?.[0],e.subscriptions?.[0]),i=e.metadata||n.metadata||e.customer?.metadata||{},r=Gr(e.priceId,e.price_id,e.stripePriceId,e.stripe_price_id,n.priceId,n.price_id,n.plan?.id,n.price?.id,n.items?.data?.[0]?.price?.id,n.items?.[0]?.price?.id,n.lines?.data?.[0]?.price?.id),s=Gr(e.status,e.subscriptionStatus,e.subscription_status,n.status,"none"),o=ib(Gr(e.tier,e.plan,e.planId,e.plan_id,e.subscriptionTier,e.subscription_tier,e.product,e.productName,n.tier,n.plan,i.tier,i.plan)),a=R0.has(String(s).toLowerCase()),l=e.active===!0||e.isSubscribed===!0||e.subscribed===!0||e.hasSubscription===!0,u=o||rb(r)||(a||l?"professional":"free");return Kn({tier:u,status:s,periodEnd:Gr(e.periodEnd,e.currentPeriodEnd,e.current_period_end,n.current_period_end,n.periodEnd,null),isResolved:!0})}function go(){return Os[he.tier]??Os.free}async function ab(){if(H.isVerified&&(!Ht()||ki())&&(await zp({force:!0}),mo()),H.isVerified&&!Ht())return Ie("Could not verify your subscription. Please refresh or try Manage billing.","error"),!1;const{count:t}=kr(),e=go();if(t>=e)return qp(t,e,{openModal:!0}),!1;const n=Math.floor(e*.8);if(t>=n){const i=e-t;Ie(`${i} run${i===1?"":"s"} remaining this month.`,"warning")}return!0}function Nd(){const t=document.getElementById("paywall-exhausted");t&&t.classList.add("hidden")}function qp(t,e,n={}){Wt(!0);const i=document.getElementById("walkthrough-modal");i&&Ye(i,{restoreFocus:!1});const r=document.getElementById("ready-state");r&&r.classList.add("hidden");const s=document.getElementById("preview-frame-container");s&&(s.style.display="none");const o=document.getElementById("main-stage-container");o&&o.classList.add("visible");const a=document.getElementById("results-view");a&&a.classList.remove("visible"),document.body.classList.remove("results-fullscreen","results-with-sidebar");const l=document.getElementById("pipeline-progress");l&&l.classList.remove("visible");const u=document.getElementById("paywall-exhausted");if(!u){Ie(`You've used all ${e} runs for this month. Upgrade to continue.`,"error"),xi();return}const c=document.getElementById("paywall-exhausted-text");if(c){const f=he.tier;f==="free"?c.textContent=`You've used all ${e} free generations this month. Upgrade to Pro for 50 generations/month and access to all AI models.`:c.textContent=`You've used all ${e} generations this month on your ${f} plan. Your limit resets next month.`}const d=document.getElementById("paywall-signin-btn");d&&d.classList.toggle("hidden",H.isVerified),u.classList.remove("hidden"),n.openModal&&xi()}function ml(t){return he.tier==="free"&&ns.includes(t)?Ds:t}function lb(){const t=document.getElementById("code-options-content"),e=document.getElementById("code-generator-model");if(!t||!e)return;const n=he.tier,r=!(H.isVerified&&!Ht())&&n==="free";Array.from(e.options).forEach(o=>{const a=on(o.value),l=ns.includes(o.value);o.textContent=l&&r?`${a} (PRO)`:a,o.disabled=!1}),r&&ns.includes(e.value)&&(e.value=Ds),e.disabled=!1,Ed.has(e)||(e.addEventListener("change",()=>{Ht()&&he.tier==="free"&&ns.includes(e.value)&&(e.value=Ds,xi()),gl(e.value),tc()}),Ed.add(e));let s=document.getElementById("model-selector-free-notice");r?(s||(s=document.createElement("p"),s.id="model-selector-free-notice",s.className="text-xs text-gray-400 mt-1",t.appendChild(s)),s.innerHTML='Free plan — Gemini only. '):s&&s.remove(),gl(e.value)}function xc(){const t=H.isVerified&&!!H.email,e=t&&ki(),n=!t||Ht(),i=kr(),r=n?i.count:0,s=n?go():0,o=Math.max(0,s-r),a=`${r} / ${s} runs this month`,l=Ul,u=n?he.tier||"free":null,c=document.getElementById("topbar-credits-count");c&&(e?c.textContent="…":n?c.textContent=String(o):c.textContent="—");const d=document.getElementById("credits-balance");d&&(e?d.textContent="Checking plan…":n?d.textContent=a:d.textContent="Plan check failed");const f=document.getElementById("usage-dialog-tier");f&&(e?f.textContent="Checking…":n?f.textContent=l[u]||"Free":f.textContent="Unavailable");const p=document.getElementById("usage-dialog-status");p&&(e?p.textContent="Verifying your subscription…":n?p.textContent="Runs reset at the start of each month.":p.textContent="Could not verify your subscription. Try again or sign out.");const h=document.getElementById("usage-counter");if(h)if(e&&t)h.textContent="Checking plan…",h.className="text-xs text-gray-500";else if(!n&&t)h.textContent="Plan check failed",h.className="text-xs text-red-600 font-medium";else{h.textContent=a;const g=s>0?r/s:0;h.className=g>=1?"text-xs text-red-600 font-medium":g>=.8?"text-xs text-yellow-600 font-medium":"text-xs text-gray-500"}if(!t){const g=document.getElementById("guest-usage-text");if(g){const m=Wp(),v=m.month===Cn()?m.count??0:0;g.textContent=`${v} / ${Os.free} generations used`}}cb()}function cb(){if(!(H.isVerified&&!!H.email))return;const e=ki(),n=Ht(),i=kr(),r=n?i.count:0,s=n?go():0,o=Math.max(0,s-r),a=n?he.tier||"free":null,l={free:"Free",professional:"Pro",power:"Power"}[a]||"Free",u=H.email||"",c=u.split("@")[0]||u,d=document.getElementById("acct-avatar");d&&(d.textContent=(u[0]||"?").toUpperCase());const f=document.getElementById("acct-name");f&&(f.textContent=c||"—");const p=document.getElementById("acct-plan-tier"),h=document.getElementById("acct-plan-price"),g=document.getElementById("acct-plan-note"),m=document.getElementById("acct-renewal");if(p&&(p.textContent=e?"Checking…":n?l:"Plan unavailable"),h)if(e)h.textContent="—";else if(!n)h.textContent="—";else if(a==="free")h.textContent="$0 / month";else{const S=Ji(Yi[a]??0,nc());h.textContent=`${S} / month`}if(g&&(e?g.textContent="Verifying your subscription…":n?a==="free"?g.textContent="No subscription. Upgrade for more generations.":g.textContent="billed monthly through Stripe":g.textContent="Could not verify your subscription. Check billing or sign out."),m){const S=Date.parse(he.periodEnd||""),C=n&&a!=="free"&&!!he.periodEnd&&!Number.isNaN(S);if(e)m.textContent="";else if(!n)m.textContent="";else if(a==="free")m.textContent="";else if(C){const R=new Date(S).toLocaleDateString(void 0,{year:"numeric",month:"long",day:"numeric"});m.textContent=`Renews ${R} · reset at the start of each month.`}else m.textContent="Renewal date is not available for this period."}const v=document.getElementById("acct-left-count"),x=document.getElementById("acct-left-limit"),E=document.getElementById("acct-reset-note");v&&(v.textContent=e?"…":n?String(o):"—"),x&&(x.textContent=e?"…":n?String(s):"—"),E&&(e?E.textContent="Checking plan…":n?E.textContent="Runs reset at the start of each month.":E.textContent="Plan check failed. Refresh or manage billing.");const y=document.getElementById("acct-used-count"),b=document.getElementById("acct-meter-fill"),I=document.getElementById("acct-meter-meta"),T=document.getElementById("acct-meter-track");if(y&&(y.textContent=e?"…":n?String(r):"—"),b){const S=n&&s>0?Math.min(100,Math.round(r/s*100)):0;b.style.width=`${S}%`}if(I)if(e)I.textContent="Checking…";else if(!n)I.textContent="Plan check failed";else if(s===0)I.textContent=`${r} of ${s}`;else{const S=Math.round(r/s*100);I.textContent=`${r} of ${s} · ${S}%`}T&&(e?T.setAttribute("aria-label","Checking usage…"):n?T.setAttribute("aria-label",`${r} of ${s} generations used`):T.setAttribute("aria-label","Usage unavailable")),Ct()}function En(){if(xc(),H.isVerified&&(ki()||!Ht())){Nd();return}const{count:t}=kr(),e=go();t>=e&&!_.isRunning&&!Yv()?qp(t,e):Nd()}function ub(){xc()}async function zp(t={}){const e=t.force===!0;if(!H.isVerified||!H.sessionToken){he=Kn({isResolved:!0});return}he={...he,isLoading:!0,error:null};const n=H.sessionToken,i=localStorage.getItem(Bs);if(!e&&i)try{const{data:r,email:s,ts:o,version:a}=JSON.parse(i);if(a===Sd&&s===H.email&&Date.now()-o<300*1e3){he={...r,isLoading:!1,isResolved:r.isResolved!==!1};return}}catch(r){console.warn("Failed to parse subscription cache:",r,"| raw value:",i)}try{const s=await(await fetch(`${At}/stripe/get-subscription`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionToken:H.sessionToken,user_id:xt.userId})})).json();if(!H.isVerified||H.sessionToken!==n)return;if(s.error){if(["unauthorized","invalid session","expired session"].some(a=>String(s.error).toLowerCase().includes(a))){Dp(),Sc();return}he=Kn({isResolved:!1,error:s.error});return}he=ob(s),localStorage.setItem(Bs,JSON.stringify({version:Sd,data:he,email:H.email,ts:Date.now()}))}catch(r){if(!H.isVerified||H.sessionToken!==n)return;console.error("fetchSubscription failed:",r),he={...he,isLoading:!1,isResolved:!1,error:r.message}}}function Vp(){localStorage.removeItem(Bs)}async function db(t){if(!H.isVerified||!H.sessionToken){Kp(),po();return}if(!dp[t]){Ie("Invalid plan selected.","error");return}const e=document.getElementById(`checkout-btn-${t}`);e&&(e.disabled=!0,e.textContent="Redirecting…");try{const i=await(await fetch(`${At}/stripe/create-checkout-session-intl`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({tierId:t,sessionToken:H.sessionToken,currency:nc()})})).json();if(i.error||!i.url)throw new Error(i.error||"Failed to create checkout session");const{url:r}=i;window.location.href=r}catch(n){console.error("startCheckout failed:",n),e&&(e.disabled=!1,e.textContent="Subscribe"),Ie("Could not start checkout. Please try again.","error")}}async function fb(t){if(!H.isVerified||!H.sessionToken){po();return}const e=t||document.getElementById("manage-billing-btn"),n=e?e.textContent:"";e&&(e.disabled=!0,e.textContent="Loading…");try{const r=await(await fetch(`${At}/stripe/create-portal-session`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionToken:H.sessionToken})})).json();if(r.error||!r.url)throw new Error(r.error||"Failed to open billing portal");const{url:s}=r;window.location.href=s}catch(i){console.error("openCustomerPortal failed:",i),e&&(e.disabled=!1,e.textContent=n),Ie("Could not open billing portal. Please try again.","error")}}const zs=new Set;function Gp(){zs.forEach(t=>t.abort()),zs.clear()}async function Vs(t,e,n,i={},r=[]){const o=new AbortController;zs.add(o);let a=!1;const l=setTimeout(()=>{a=!0,o.abort()},12e4);try{const u=await fetch(C0,{method:"POST",headers:{"Content-Type":"application/json",...xt.token?{Authorization:`Bearer ${xt.token}`}:{}},signal:o.signal,body:JSON.stringify({user_id:xt.userId,step:t,model:e,prompt:n,images:r,context:i})}),c=await u.text();let d={};try{d=c?JSON.parse(c):{}}catch{d={}}if(u.status===429){d.serverCount!==void 0&&(localStorage.setItem(Wn,JSON.stringify({count:d.serverCount,month:Cn()})),En());const h=new Error(d.message||"Monthly usage limit reached. Upgrade to continue.");throw h.isUsageLimit=!0,h.pipelineStep=t,h}const f=hy(d,t);if(f)throw f;if(console.log(`[BuildShip] ${t} response keys:`,Object.keys(d),"content type:",typeof d.content),!u.ok)throw new Error(`${d.message||d.error||"BuildShip pipeline error"} (HTTP ${u.status})`);if(t==="generator")if(d.usage_status==="success"&&Number.isFinite(d.usage_count)){const h=Cn();(d.usage_month||h)===h&&(localStorage.setItem(Wn,JSON.stringify({count:d.usage_count,month:h})),En())}else nb(),En();let p=d.output||d.content;if(!p){const h=c?` (body: ${c.slice(0,120)})`:"";throw new Error(`BuildShip returned no output for step "${t}"${h}`)}return Array.isArray(p)&&(p=p.map(h=>typeof h=="string"?h:h.text||"").join("")),typeof p!="string"&&(p=JSON.stringify(p)),p}catch(u){if(u.name==="AbortError"){if(a)throw new Error(`BuildShip ${t} timed out after ${12e4/1e3}s`);const c=new Error(`BuildShip ${t} request cancelled`);throw c.isPipelineCancel=!0,c}throw u instanceof TypeError?new Error(`BuildShip unreachable: ${u.message}`):u}finally{clearTimeout(l),zs.delete(o)}}let vl=!1;function hb(){const e=new URLSearchParams(window.location.search).get("checkout");return e==="success"?(window.history.replaceState({},"",window.location.pathname+window.location.hash),Vp(),vl=!0):e==="cancel"&&(window.history.replaceState({},"",window.location.pathname+window.location.hash),Ie("Checkout cancelled.","info")),e}function pb(){if(!vl)return;vl=!1;const t=he.tier!=="free";Ie(t?"Subscription active! Your plan is live.":"Checkout complete — confirming your subscription. Check Manage billing if it does not update.",t?"success":"info")}function mo(){const t=H.isVerified&&!!H.email,e=he.tier,n=t&&ki(),i=!t||Ht(),r=document.getElementById("subscription-tier-badge");if(r){const a=Ul,l={free:"bg-gray-100 text-gray-600",professional:"bg-indigo-100 text-indigo-700",power:"bg-purple-100 text-purple-700",unresolved:"bg-red-50 text-red-600"};r.textContent=n?"Checking…":i?a[e]||"Free":"Plan unavailable",r.className=`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${i?l[e]||l.free:l.unresolved}`}const s=document.getElementById("upgrade-prompt");s&&s.classList.toggle("hidden",!t||n||!i||e!=="free");const o=document.getElementById("manage-billing-btn");o&&o.classList.toggle("hidden",!t||n||i&&e==="free"),gb(i?e:null),lb(),tc(),En(),pg()}function gb(t){const e=["bg-gray-100","text-gray-500","cursor-default"];Object.entries({professional:{btnId:"checkout-btn-professional",defaultText:"Subscribe"},power:{btnId:"checkout-btn-power",defaultText:"Subscribe"}}).forEach(([r,{btnId:s,defaultText:o}])=>{const a=document.getElementById(s);a&&(r===t?(a.disabled=!0,a.textContent="Current plan",a.classList.add(...e)):(a.disabled=!1,a.textContent=o,a.classList.remove(...e)))});const i=document.getElementById("free-tier-current");i&&i.classList.toggle("hidden",t!=="free")}function mb(){document.querySelectorAll(".pm-card[data-tier]").forEach(t=>{const e=t.dataset.tier,n=ey[e];if(!n)return;const i=t.querySelector("ul.pm-features");if(i){i.innerHTML="";for(const r of n){const s=document.createElement("li");s.textContent=r,i.appendChild(s)}}})}function yl(){const t=nc(),e=document.getElementById("pro-price"),n=document.getElementById("power-price"),i=document.getElementById("plans-pro-price"),r=document.getElementById("plans-power-price"),s=document.getElementById("pro-price-note"),o=document.getElementById("power-price-note"),a=document.getElementById("plans-pro-price-note"),l=document.getElementById("plans-power-price-note");e&&(e.textContent=Ji(Yi.professional,t)),n&&(n.textContent=Ji(Yi.power,t)),i&&(i.textContent=Ji(Yi.professional,t)),r&&(r.textContent=Ji(Yi.power,t));const u="billed monthly";s&&(s.textContent=u),o&&(o.textContent=u),a&&(a.textContent=u),l&&(l.textContent=u)}function xi(){yl();const t=document.getElementById("pricing-modal");t&&Ke(t),H0().then(()=>yl())}function Kp(t){if(t&&t.target!==t.currentTarget)return;const e=document.getElementById("pricing-modal");e&&Ye(e)}function Ie(t,e="info"){const n={success:"bg-green-600 text-white",error:"bg-red-600 text-white",warning:"bg-amber-500 text-white",info:"bg-gray-800 text-white"},i=document.createElement("div");i.className=`fixed bottom-6 left-1/2 -translate-x-1/2 px-5 py-3 rounded-lg text-sm font-medium shadow-lg z-50 transition-opacity duration-300 ${n[e]||n.info}`,i.textContent=t,document.body.appendChild(i),setTimeout(()=>{i.style.opacity="0",setTimeout(()=>i.remove(),300)},3500)}document.addEventListener("DOMContentLoaded",async()=>{Zv(),Rb(),hljs.configure({tabReplace:" ",classPrefix:"hljs-"}),vb(),window.__heroField=K_(),window.__pipelineLogo=X_(),Xb(),ec=b0({onSubmit:br}),rl=(async()=>{try{await zw(),hb(),await zp()}catch(n){console.warn("Startup auth/subscription initialization failed:",n)}})(),await rl,pb(),mo(),yl(),mb(),await yw(),hw();const t=document.getElementById("flutterflow-endpoint-select");if(t){const n=Ge();t.value=n}kp(),Hp();const e=document.getElementById("pipeline-input");e&&(e.addEventListener("input",()=>{pn===2&&e.value.trim().length>0&&(lc(),so())}),e.addEventListener("blur",()=>{const n=document.getElementById("walkthrough-modal");pn===2&&n&&Ke(n)}),e.addEventListener("keydown",n=>{if(n.key==="Tab"){const i=document.getElementById("walkthrough-modal");pn===2&&i&&setTimeout(()=>{Ke(i)},100)}})),window.addEventListener("commitStateChange",n=>{const{state:i}=n.detail;i===ne.PREPARING||i===ne.VALIDATING||i===ne.PUSHING?(eg(),He.phaseId||tg(),Bd(i)):(i===ne.SUCCESS||i===ne.ERROR)&&(Bd(i),Un&&clearTimeout(Un),Un=setTimeout(()=>{Un=null,Cc()},1e3))}),Mc()});function vb(){const t=document.getElementById("preview-frame-container");t&&(t.style.display="")}function yb(){const t=document.getElementById("welcome-video-player");t&&(t.addEventListener("click",Yn),document.addEventListener("keydown",Yn))}function Yn(){const t=document.getElementById("preview-frame-container"),e=document.getElementById("main-stage-container"),n=document.getElementById("ready-state");t&&(t.style.display="none"),e&&e.classList.add("visible"),n&&n.classList.remove("hidden");const i=document.getElementById("welcome-video-player");i&&i.removeEventListener("click",Yn),document.removeEventListener("keydown",Yn),kp()}let rr=null;async function _l(){const t=document.getElementById("confirm-project-select");if(!t)return;const e=++Ad,n=++ro,i=()=>e===Ad,r=bt;yr=null;const s=await Le("flutterflow"),o=await Le("flutterflow_project_id");if(i()){if(!s){t.innerHTML='',t.disabled=!0;return}t.disabled=!1,t.innerHTML='';try{const l=await new Jn(s,"","main",Ge()).listProjects();if(!i())return;if(r!==bt||s!==Ae)return _l();if(n>hn&&(hn=n,sc(l,s,r)),!l||l.length===0){t.innerHTML='';return}t.innerHTML='',l.forEach(u=>{const c=document.createElement("option");c.value=u.id||u.projectId||"",c.textContent=u.name||u.projectName||`Project ${u.id}`,t.appendChild(c)}),yr={key:s,generation:r},o&&(t.value=o)}catch(a){if(!i())return;if(r!==bt||s!==Ae)return _l();console.error("Failed to load projects for deploy:",a),t.innerHTML=''}}}function _b(){const e=document.getElementById("confirm-project-select")?.value?.trim();if(!e)return null;const n=yr;return!n||n.key!==Ae||n.generation!==bt?null:e}function Ic(t,e,n,i=null){rr={codeInfo:t,checks:e,deps:n,bundlePlan:i},document.getElementById("confirm-file-name").textContent=t.fileName,document.getElementById("confirm-artifact-type").textContent=t.artifactType,document.getElementById("confirm-file-size").textContent=`${(t.content.length/1024).toFixed(1)} KB`,document.getElementById("confirm-line-count").textContent=i?`${i.fileEntries.length} files`:t.content.split(` +`).length,_l();const r=document.getElementById("confirm-deps-list"),s=document.getElementById("confirm-deps-section");n&&Object.keys(n).length>0?(r.innerHTML=Object.entries(n).map(([u,c])=>{const d=c?`at least ${fn(c)}`:"version resolved from your project";return`
  • • ${fn(u)}: ${d}
  • `}).join(""),s.classList.remove("hidden")):s.classList.add("hidden");const o=document.getElementById("confirm-warnings-list"),a=document.getElementById("confirm-warnings-section");e.warnings&&e.warnings.length>0?(o.innerHTML=e.warnings.map(u=>`
  • • ${fn(u)}
  • `).join(""),a.classList.remove("hidden")):a.classList.add("hidden"),document.getElementById("confirm-code-preview").textContent=t.content,document.getElementById("code-preview-content").classList.add("hidden"),document.getElementById("code-preview-chevron").style.transform="rotate(0deg)";const l=document.getElementById("commit-confirm-modal");l&&Ke(l)}function Yp(t){if(t&&t.target!==t.currentTarget)return;const e=document.getElementById("commit-confirm-modal");e&&Ye(e),rr=null}function wb(t){if(t&&t.target!==t.currentTarget)return;const e=document.getElementById("commit-success-modal");e&&Ye(e);const n=["success-message","success-project-id","success-file-name","success-artifact-type","success-time","success-size"];for(const s of n){const o=document.getElementById(s);o&&(o.textContent="")}const i=document.getElementById("success-warnings-section");i&&i.classList.add("hidden");const r=document.getElementById("success-warnings-list");r&&(r.innerHTML="")}function Jp(t){const e=(m,v)=>{const x=document.getElementById(m);x&&(x.textContent=v||"")},n=t.metadata?.fileName||"",i=t.metadata?.projectId||"",r=t.metadata?.artifactType||"",s=t.elapsedTime?`${(t.elapsedTime/1e3).toFixed(1)}s`:"",o=t.metadata?.codeSize?`${(t.metadata.codeSize/1024).toFixed(1)} KB`:"";e("success-message",t.message||"Code committed successfully!"),e("success-project-id",i),e("success-file-name",n),e("success-artifact-type",r),e("success-time",s),e("success-size",o);const a=t.addedDependencies||[],l=document.getElementById("success-deps-row");l&&l.classList.toggle("hidden",a.length===0),e("success-deps",a.join(", "));const u=document.getElementById("success-open-ff-link");u&&i&&(u.href=`https://app.flutterflow.io/project/${i}`);const c=document.getElementById("success-warnings-section"),d=document.getElementById("success-warnings-list"),f=t.unverified||[],p=t.approximate||[],h=t.warnings||[];(h.length>0||f.length>0||p.length>0)&&c&&d&&(d.innerHTML=[...f.map(m=>`
  • Not verified before deploying: ${W(String(m))}
  • `),...p.map(m=>`
  • Verified approximately: ${W(String(m))}
  • `),...h.map(([m,v])=>`
  • ${W(m)}: ${W(String(v))}
  • `)].join(""),c.classList.remove("hidden"));const g=document.getElementById("commit-success-modal");g&&Ke(g)}function Zp(t){Cc(),Uw(t);const e=t.remoteRefusal===!0;kc(t,{heading:"Deploy failed",title:e?"FlutterFlow refused this deploy — nothing was confirmed written.":"The deploy failed before FlutterFlow confirmed anything.",guidance:e?"Review the error and any per-file outcomes above, fix them in your code or in FlutterFlow, then deploy again. A refusal is definitive: no part of this deploy was applied, so retrying is safe once the problem is fixed.":"Review the error above, fix it, then deploy again. The deploy stopped before a write was confirmed, so nothing was applied."})}function kc(t,{heading:e,title:n,guidance:i}){const r=t.targetIdentity||{},s=document.getElementById("commit-terminal-modal");if(!s)return!1;const o=(h,g)=>{const m=document.getElementById(h);m&&(m.textContent=g||"")};o("terminal-heading",e),o("terminal-title",n),o("terminal-message",t.error||t.message||"");const a=document.getElementById("terminal-identity-list");if(a){const h=[["Project",r.projectId||t.metadata?.projectId],["Endpoint",r.endpoint],["File",r.fileName||t.metadata?.fileName],["Artifact",r.artifactType||t.metadata?.artifactType]];a.innerHTML=h.map(([g,m])=>`
    ${W(g)}:${W(String(m??"—"))}
    `).join("")}const l=document.getElementById("terminal-file-outcomes");let u=t.errorMap;u&&!(u instanceof Map)&&(u=new Map(Object.entries(u)));const c=l?.querySelector("ul");l&&c&&u&&u.size>0?(c.innerHTML=[...u.entries()].map(([h,g])=>`
  • ${W(h)}: ${W(Kl(g))}
  • `).join(""),l.classList.remove("hidden")):l&&(c&&(c.innerHTML=""),l.classList.add("hidden"));const d=document.getElementById("terminal-guidance");d&&(d.innerHTML=i);const f=document.getElementById("terminal-open-ff-link"),p=r.projectId||t.metadata?.projectId;return f&&(f.href=p?`https://app.flutterflow.io/project/${p}`:"https://app.flutterflow.io/"),Ke(s),!0}function Xp(t){kc(t,{heading:"Deploy partially applied",title:"Some custom classes reached FlutterFlow, but the deploy did not fully complete.",guidance:"The custom classes the runner confirmed are already in your project and are not lost. Review the per-file errors above, fix them in FlutterFlow or regenerate, then deploy again. Open the project to see exactly what landed."})}function Qp(t){kc(t,{heading:"Deploy outcome not yet known",title:"This browser stopped waiting before the FlutterFlow server reported a result.",guidance:"The deploy may still be finishing on the server — it was not cancelled. Open your FlutterFlow project and confirm whether the class landed before retrying, so you do not push a duplicate or build on top of an unknown state."})}function bb(t){t&&t.target!==t.currentTarget||Ye(document.getElementById("commit-terminal-modal"))}function Eb(){const t=document.getElementById("code-preview-content"),e=document.getElementById("code-preview-chevron");t.classList.contains("hidden")?(t.classList.remove("hidden"),e.style.transform="rotate(90deg)"):(t.classList.add("hidden"),e.style.transform="rotate(0deg)")}const Od={prepare:{message:"Preparing your code...",start:4,end:14},validate:{message:"Checking FlutterFlow credentials...",start:14,end:22},project:{message:"Reading your FlutterFlow project...",start:22,end:40},provision:{message:"Creating custom classes in FlutterFlow...",start:40,end:82},package:{message:"Packaging files for upload...",start:82,end:88},push:{message:"Pushing to FlutterFlow...",start:88,end:97},done:{message:"Complete!",start:100,end:100}},Sb=[{after:0,text:"Starting a FlutterFlow build runner..."},{after:12,text:"Preparing the FlutterFlow AI workspace..."},{after:35,text:"Uploading your custom classes..."},{after:60,text:"FlutterFlow is applying the changes..."},{after:100,text:"Still working — this can take a couple of minutes..."}];let Un=null;function eg(){Un&&clearTimeout(Un),Un=null}const He={sequence:[],phaseId:null,phaseStartedAt:null,timer:null,substatus:null,liveSubstatus:!1,start({withProvisioning:t=!1}={}){eg(),this.sequence=["prepare","validate","project"],t&&this.sequence.push("provision"),this.sequence.push("package","push","done");const e=document.getElementById("commit-progress-overlay");e&&(Xu(e,!0,"Deploying to FlutterFlow"),Ke(e)),this.set("prepare")},set(t,e=null){if(!(!Od[t]||t===this.phaseId)){if(!this.sequence.includes(t)){const n=this.sequence.indexOf("package");this.sequence.splice(n===-1?this.sequence.length:n,0,t)}this.phaseId=t,this.phaseStartedAt=Date.now(),this.substatus=e,this.liveSubstatus=!1,this.render(),this.timer&&clearInterval(this.timer),t!=="done"&&(this.timer=setInterval(()=>this.render(),500))}},setSubstatus(t){t&&(this.liveSubstatus=!0,this.substatus=t,this.render())},render(){const t=Od[this.phaseId];if(!t)return;const e=(Date.now()-this.phaseStartedAt)/1e3,n=t.start+(t.end-t.start)*(1-Math.exp(-e/25));if(this.phaseId==="provision"&&!this.liveSubstatus){const o=Sb.filter(a=>e>=a.after).pop();o&&(this.substatus=o.text)}const i=this.sequence.indexOf(this.phaseId),s=[`Step ${i===-1?1:i+1} of ${this.sequence.length}`];e>=5&&s.push(xb(e)),ng(this.phaseId==="done"?100:n,t.message,s.join(" · "),this.substatus)},stop(){this.timer&&clearInterval(this.timer),this.timer=null,this.phaseId=null;const t=document.getElementById("commit-progress-overlay");t&&(Xu(t,!1),Ye(t,{force:!0,restoreFocus:!1}))}};function xb(t){const e=Math.floor(t);return e<60?`${e}s elapsed`:`${Math.floor(e/60)}m ${String(e%60).padStart(2,"0")}s elapsed`}function tg(t){He.start(t)}function Cc(){He.stop()}function ng(t,e,n,i=null){const r=document.getElementById("commit-progress-bar"),s=document.getElementById("progress-message"),o=document.getElementById("progress-detail"),a=document.getElementById("progress-substatus");r&&(r.style.width=`${Math.round(t*10)/10}%`),s&&(s.textContent=e),o&&(o.textContent=n),a&&(a.textContent=i||"",a.classList.toggle("hidden",!i))}function Bd(t){const e={[ne.PREPARING]:"prepare",[ne.VALIDATING]:"validate",[ne.PUSHING]:"project",[ne.SUCCESS]:"done"};if(t===ne.ERROR){He.timer&&clearInterval(He.timer),He.timer=null,ng(100,"Failed","Error occurred");return}const n=e[t];n&&He.set(n)}function Ib(t){return t.bundlePlan?t.bundlePlan.fileEntries.some(e=>e.type===Z.CODE_FILE):t.codeInfo?.codeType===Z.CODE_FILE}let ig=!1;function rg(t){ig=t;const e=document.querySelector("#commit-confirm-modal button[data-deploy-confirm]");e&&(e.disabled=t),[...document.querySelectorAll("[data-deploy-start]"),...document.querySelectorAll("#btn-deploy-to-ff")].forEach(i=>{i.disabled=t})}function Dd(t){Cc(),rg(!1);const e=rp(t);e===Oe.COMMITTED?Jp(t):e===Oe.PARTIAL?Xp(t):e===Oe.UNCONFIRMED?Qp(t):Zp(t)}async function kb(){if(!rr){console.error("No pending commit data");return}if(ig){console.warn("Deploy already in flight; ignoring duplicate confirm.");return}const t=rr;if(rr=null,ir=_b(),Yp(),rg(!0),tg({withProvisioning:Ib(t)}),t.bundlePlan){const o=await Fw(t.bundlePlan,{pipelineResult:{step1Result:_.step1Result,selectedModel:document.getElementById("code-generator-model")?.value}});ir=null,Dd(o);return}const{codeInfo:e}=t,{artifactType:n,artifactName:i,fileName:r}=Cp(),s=await Pw(e.content,{artifactType:n,artifactName:i,fileName:r,pipelineResult:{step1Result:_.step1Result,selectedModel:document.getElementById("code-generator-model")?.value}});ir=null,Dd(s)}window.runThinkingPipeline=br;window.toggleStep=Mw;window.toggleSection=Tw;window.selectWorkflowStep=dt;window.copyCode=$w;window.retryWithDifferentModel=Bw;window.openApiKeysModal=ac;window.closeApiKeysModal=xp;window.openComposerSettings=Sp;window.closeComposerSettings=rw;window.walkthroughConnectAccount=iw;window.closeWalkthroughModal=ow;window.openWalkthroughModal=sw;window.advanceWalkthrough=lc;window.commitToFlutterFlow=Aw;function Cb(){_.isRunning||Wt(!1);const t=document.getElementById("pipeline-input");t&&t.focus()}function Ab(){Sp();const t=document.getElementById("composer-settings-model");t&&(t.scrollIntoView({behavior:"smooth",block:"center"}),t.focus(),t.click())}window.focusPromptInput=Cb;window.openModelSelector=Ab;window.handlePromptImageSelect=j0;window.removePromptImage=U0;window.saveApiKeys=cw;window.validateFlutterFlowConnection=uc;window.clearAllApiKeys=uw;window.toggleKeyVisibility=gw;window.handleWelcomeVideoEnd=yb;window.dismissWelcomeVideo=Yn;window.initiateCommitToFlutterFlow=Dw;window.updateFlutterFlowCredentialStatus=Hw;window.openCommitConfirmModal=Ic;window.closeCommitConfirmModal=Yp;window.closeCommitSuccessModal=wb;window.closeCommitTerminalModal=bb;window.showCommitPartialModal=Xp;window.showCommitUnconfirmedModal=Qp;window.showCommitSuccessModal=Jp;window.showCommitFailureModal=Zp;window.toggleCodePreview=Eb;window.confirmCommitToFlutterFlow=kb;window.runRefinement=Lp;window.regenerateFromPastedErrors=Np;window.clearErrorInput=Ow;window.setFlutterFlowEndpoint=ew;window.getFlutterFlowEndpoint=Ge;window.commitProgress=He;window.openSignInModal=po;window.closeSignInModal=Up;window.handleMagicLinkRequest=Gw;window.handleSignOut=Kw;window.handleSendNewLink=Zw;window.handleClearCache=Xw;window.handleDeleteAccount=Qw;window.closeDeleteUnavailableModal=eb;window.startCheckout=db;window.openCustomerPortal=fb;window.openPricingModal=xi;window.closePricingModal=Kp;let ls=null,sg=null,mn={1:"pending",2:"pending",3:"pending"},qn=1,wl=null,Ac=null;const vo={1:"Prompt Architect",2:"Code Generator",3:"Code Review"},Pb={1:"Understanding your prompt",2:"Generating Dart code",3:"Running the code audit"},Fb={1:"Prompt understood",2:"Dart code generated",3:"Code audit complete"};function yo(){return _.runId+=1,_.runId}function le(t){return t===void 0||t===_.runId}function og(){_.runId+=1}function Pc(t){return document.getElementById(`pdot-${t}`)}const ag=window.matchMedia("(max-width: 920px)");function jd(){const t=document.getElementById("pipeline-progress"),e=t?.querySelector(":scope > .pipeline-view"),n=t?.querySelector(":scope > .pipeline-prompt-recap");if(!e||!n)return;const i=ag.matches;if((e.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_FOLLOWING)!==0===i)return;const s=document.activeElement;t.insertBefore(n,i?e.nextSibling:e),s instanceof HTMLElement&&n.contains(s)&&s.focus({preventScroll:!0})}function Rb(){jd(),ag.addEventListener("change",jd)}function Tb(t){return{1:"Turning your idea into a clear FlutterFlow specification.",2:"Building the Dart source, widget parameters and animation.",3:"Checking the generated code and preparing the file review."}[t]||""}function Gs(t){const e=document.getElementById("btn-run-pipeline")||document.getElementById("hero-send");e&&(e.disabled=t,e.classList.toggle("is-busy",t),t?e.setAttribute("aria-busy","true"):e.removeAttribute("aria-busy"))}function _o(t){const e=document.getElementById("pipeline-progress");e&&(e.dataset.runState=t)}function zn(t,e){mn[t]=e;const n=Pc(t);if(!n)return;n.dataset.state=e,n.disabled=e==="pending"||e==="skipped";const i=vo[t],r={pending:"not started",active:"in progress",done:"complete",failed:"failed",skipped:"not run"};n.setAttribute("aria-label",`Step ${t} of 3, ${i}: ${r[e]||e}`),e==="active"?n.setAttribute("aria-current","step"):n.removeAttribute("aria-current")}function Mb(){return[1,2,3].filter(t=>mn[t]==="done").length}function Cr(){const t=document.getElementById("pipeline-progress-fill");if(t)if(mn[qn]==="failed"){const n=getComputedStyle(t).width,i=t.parentElement,r=i?i.getBoundingClientRect().width:0,s=parseFloat(n)||0;t.style.transition="none",t.style.width=r?`${s/r*100}%`:n}else t.style.transition="",t.style.width=`${$b()}%`;const e=document.getElementById("progress-stage-count");e&&(e.textContent=`Step ${qn} of 3`)}function $b(){const t=33.333333333333336,e=mn[qn];if(e==="active"&&wl!==null){const n=(Date.now()-wl)/1e3;return(qn-1)*t+t*.95*(1-Math.exp(-n/12))}return e==="done"?qn/3*100:Mb()/3*100}function wo(t,{done:e=!1}={}){const n=document.getElementById("progress-title-text"),i=document.getElementById("progress-description-text"),r=document.getElementById("progress-substep-text"),s=mn[t],o=e||s==="done";if(n&&(n.textContent=o?Fb[t]:Pb[t]),i&&(i.textContent=Tb(t)),r){const a=o?" — complete":s==="failed"?" — stopped":"";r.textContent=`Step ${t} of 3 — ${vo[t]}${a}`}}function Lb(t){mn[t]==="pending"||mn[t]==="skipped"||(Ac=t,[1,2,3].forEach(e=>{const n=Pc(e);n&&n.setAttribute("aria-pressed",String(e===t))}),wo(t))}function Fc(){Ac=null,[1,2,3].forEach(t=>{const e=Pc(t);e&&e.removeAttribute("aria-pressed")})}function lg(t){const e=document.getElementById("pipeline-note");e&&(e.textContent=t||"",e.hidden=!t)}function Nb(t,e,n){le(n)&&lg(`${on(t)} did not answer. Continuing on ${on(e)}.`)}function Rc(){const t=document.getElementById("pipeline-failure");if(!t)return;t.hidden=!0;const e=document.getElementById("pipeline-failure-actions");e&&e.replaceChildren()}function Ob(){return window.matchMedia?.("(prefers-reduced-motion: reduce)").matches===!0}function An(){Gn()}function Bb(){return[".pipeline-prompt-kicker","#pipeline-submitted-prompt","#pipeline-edit-prompt",".pipeline-glyph","#progress-title-text","#progress-description-text",".progress-track",".progress-meta"].map(t=>document.querySelector(t))}function Db(){const e=document.getElementById("pipeline-stage-nav").classList.toggle("is-open");document.getElementById("progress-stage-count").setAttribute("aria-expanded",String(e))}window.togglePipelineStageNavigation=Db;function jb(t,e){up(t,document.getElementById("main-stage-container"),Bb()),x0(document.getElementById("hero"),e)}window.addEventListener("hashchange",An);window.addEventListener("popstate",An);function bo(t={}){const{prompt:e=null,runId:n}=t;if(!le(n))return;Ar(),An(),Wt(!0);const i=document.getElementById("pipeline-progress"),r=document.getElementById("results-view"),s=document.getElementById("ready-state");if(s&&s.classList.add("hidden"),r&&r.classList.remove("visible"),document.body.classList.remove("results-fullscreen","results-with-sidebar"),i&&i.classList.add("visible"),document.getElementById("pipeline-stage-nav")?.classList.remove("is-open"),document.getElementById("progress-stage-count")?.setAttribute("aria-expanded","false"),_o("running"),e!==null){const a=document.getElementById("pipeline-submitted-prompt");a&&(a.textContent=e)}sg=Date.now();const o=document.getElementById("progress-elapsed");o&&(o.textContent="0s"),mn={1:"pending",2:"pending",3:"pending"},Fc(),Rc(),lg(""),[1,2,3].forEach(a=>zn(a,"pending")),jt(1,n),Ub()}function jt(t,e){le(e)&&(qn=t,wl=Date.now(),Fc(),[1,2,3].forEach(n=>{n===t?zn(n,"active"):nt&&zn(n,"pending")}),wo(t),Cr())}function gn(t,e){le(e)&&(zn(t,"done"),Ac===null&&wo(t,{done:!0}),Cr())}function cg(t,{stage:e=1,runId:n,retry:i=ug}={}){if(!le(n))return;Eo(),Ar(),An(),_o("failed"),Wt(!0);const r=document.getElementById("pipeline-progress");r&&r.classList.add("visible");const s=document.getElementById("results-view");s&&s.classList.remove("visible"),document.body.classList.remove("results-fullscreen","results-with-sidebar"),zn(e,"failed"),[1,2,3].forEach(h=>{h>e&&zn(h,"pending")}),qn=e,Fc(),wo(e),Cr();const o=ap(t),a=document.getElementById("pipeline-failure"),l=document.getElementById("pipeline-failure-title"),u=document.getElementById("pipeline-failure-message"),c=document.getElementById("pipeline-failure-hint"),d=document.getElementById("pipeline-failure-actions");if(!a||!l||!u||!d)return;if(a.dataset.kind=o.kind,l.textContent=`${vo[e]}: ${o.title}`,u.textContent=o.message,c){const h=o.detail&&o.detail!==o.message?o.detail:"";c.textContent=h,c.hidden=!h}d.replaceChildren();const f=[o.canUpgrade&&{id:"upgrade",label:"View plans",variant:"primary",onClick:()=>xi()},o.canRetry&&{id:"retry",label:"Retry",variant:o.canUpgrade?"secondary":"primary",onClick:i},o.canEdit&&{id:"edit",label:"Edit prompt",variant:"secondary",onClick:bl}].filter(Boolean);!o.canEdit&&!o.canRetry&&f.push({id:"edit",label:"Back to prompt",variant:"secondary",onClick:bl}),f.forEach(h=>{const g=document.createElement("button");g.type="button",g.textContent=h.label,g.dataset.action=h.id,g.dataset.variant=h.variant,g.addEventListener("click",h.onClick),d.appendChild(g)}),a.hidden=!1;const p=d.querySelector("button");p&&p.focus({preventScroll:!0})}function bl(){og(),Gp(),_.isRunning=!1,Gs(!1),vn(),_o("settled"),An(),Eo(),Ar(),Rc();const t=document.getElementById("pipeline-progress");t&&t.classList.remove("visible"),Wt(!1);const e=document.getElementById("pipeline-input");e&&(_.submittedPrompt&&(e.value=_.submittedPrompt,e.dispatchEvent(new Event("input",{bubbles:!0}))),e.focus({preventScroll:!0}),e.setSelectionRange(e.value.length,e.value.length))}function ug(){const t=document.getElementById("pipeline-input");t&&_.submittedPrompt&&(t.value=_.submittedPrompt,t.dispatchEvent(new Event("input",{bubbles:!0}))),Ue=_.submittedImages.slice(),bn(),Rc(),br()}function Ub(){Eo(),ls=setInterval(()=>{const t=(Date.now()-sg)/1e3,e=document.getElementById("progress-elapsed");e&&(e.textContent=`${Math.floor(t)}s`),Cr()},250)}function Eo(){ls&&(clearInterval(ls),ls=null)}let sr=null;function Ar(){sr&&(clearTimeout(sr),sr=null)}function Ci(){Eo(),Ar(),_o("settled"),Cr();const t=document.getElementById("pipeline-progress-fill");sr=setTimeout(()=>{sr=null;const e=document.getElementById("pipeline-progress");e&&e.classList.remove("visible"),t&&(t.style.width="0%")},400)}function Ii(t,e=""){const n={pass:'',warning:'',fail:'',info:''};return``}function dg(t){return{pass:"Passed review",warning:"Needs attention",fail:"Blocking issues"}[t]||"Needs attention"}function Hb(){return l_({bundle:_.artifactBundle,reviewResult:_.step3Result})}function Wb(t){return` +
    + ${Ii(t.severity)} +
    +
    ${W(t.message)}
    + ${t.suggestion?`
    ${W(t.suggestion)}
    `:""} + ${W(t.source)} +
    +
    + `}function qb(t){return` +
  • +
    + ${W(t.title)} + ${t.detail&&t.detail!==t.title?`

    ${W(t.detail)}

    `:""} +
    +
  • + `}function zb(t){const e=document.getElementById("results-summary-detail"),n=document.getElementById("results-title");if(!e)return;n&&(n.textContent=t.title);const i=t.score,r=i==null?"neutral":i>=80?"pass":i>=60?"warning":"fail",s=i==null?"":i>=80?"Strong":i>=60?"Needs work":"High risk",o=t.findings.length?` +
      + ${t.findings.map(u=>` +
    • + ${Ii(u.severity)} + + ${W(u.message)} + ${u.suggestion?`${W(u.suggestion)}`:""} + +
    • + `).join("")} +
    + `:"",a=t.warnings.length?` +
    +

    ${Ii("warning")} Bundle

    +
      + ${t.warnings.map(u=>`
    • ${W(u)}
    • `).join("")} +
    +
    + `:"",l=t.manualSteps.length?` +
    +

    Complete in FlutterFlow

    +

    For your information — these don't block the deploy. Finish them by hand in the FlutterFlow editor once the code is pushed.

    +
      + ${t.manualSteps.map(u=>` +
    1. + ${W(u.title)} + ${u.detail&&u.detail!==u.title?`${W(u.detail)}`:""} +
    2. + `).join("")} +
    +
    + `:"";e.innerHTML=` +
    +
    +

    ${W(t.title)}

    +

    ${W(t.summary)}

    +
    +
    Artifact${t.artifacts.length===1?"":"s"}
    ${t.artifacts.map(u=>W(u.artifactType||u.type||u.name)).join(" · ")}
    +
    Public API
    ${t.artifacts.flatMap(u=>u.publicApi||[]).map(W).join(" · ")||"No parameters returned"}
    +
    Manual Steps Required
    ${l||"None reported"}
    +
    Review
    ${W(t.status||"Not reported")}
    +
    + ${o} + ${a} +
    +
    + +
    + Is the generated code correct? +
    + + +
    + +
    +
    +
    + `}function Vb(t){const e=t.artifacts.find(l=>l.id===_.selectedArtifactId)||t.artifacts[0];if(!e)return"";const n={pass:{icon:"pass",message:"No file-specific issues were found."},warning:{icon:"warning",message:"This file needs attention, but Code Review did not return a specific finding."},fail:{icon:"fail",message:"This file is blocked, but Code Review did not return a specific finding."}}[e.status],i=e.findings.length?e.findings.map(Wb).join(""):`
    ${Ii(n.icon)} ${W(n.message)}
    `,r=e.dependencies?.length?e.dependencies.map(l=>` +
  • ${W(l.name)}${l.version?` ${W(l.version)}`:""}${l.reason?`

    ${W(l.reason)}

    `:""}
  • + `).join(""):'
  • No external packages
  • ',s=e.imports?.length?e.imports.map(l=>`${W(l)}`).join(""):'No imports returned',o=e.publicApi?.length?e.publicApi.map(l=>`${W(l)}`).join(""):'No public API signature returned',a=e.relationships.length?e.relationships.map(l=>` +
  • ${W(l.from||"Bundle")} ${W(l.type)} ${W(l.to||"Bundle")}${l.description?`

    ${W(l.description)}

    `:""}
  • + `).join(""):'
  • No relationships for this file
  • ';return` +
    +
    + ${Ii(e.status)} ${W(dg(e.status))} +

    ${W(e.artifactName)}

    + ${e.description?`

    ${W(e.description)}

    `:""} +
    +
    + ${W(e.artifactType)} + ${W(e.fileName)} +
    +
    +
    +

    Code Review findings

    + ${i} +
    + ${e.manualSteps.length?` +
    +

    Manual FlutterFlow steps for this file

    +
      ${e.manualSteps.map(qb).join("")}
    +
    + `:""} +
    + File details +
    +
    +

    Dependencies

    +
      ${r}
    +
    +
    +

    Deployment

    +
    +
    Status
    ${W(e.deployStatus||"pending")}
    +
    Order
    ${e.index+1} of ${t.artifacts.length}
    +
    Path hint
    ${W(e.pathHint||"Not returned")}
    +
    +
    +
    +
    +

    Public API

    +
    ${o}
    +
    +
    +

    Imports

    +
    ${s}
    +
    +
    +

    Relationships

    +
      ${a}
    +
    +
    + `}function Gb(t){const e=document.getElementById("bundle-strip"),n=document.getElementById("results-summary-tab"),i=document.getElementById("artifact-tabs"),r=document.getElementById("results-file-count");if(n){const s=_.resultsViewMode==="summary";n.classList.toggle("active",s),n.setAttribute("role","tab"),n.setAttribute("aria-selected",String(s)),n.setAttribute("aria-controls","results-summary-detail"),n.tabIndex=s?0:-1}if(i&&(i.setAttribute("role","tablist"),i.setAttribute("aria-label","Artifacts in this bundle")),!t.artifacts.length){r&&(r.textContent="0 files"),e&&e.classList.remove("visible"),i&&(i.innerHTML=""),Ud();return}if(r){const s=t.artifacts.length;r.textContent=`${s} ${s===1?"file":"files"}`}i&&(i.innerHTML=t.artifacts.map(s=>{const o=_.resultsViewMode==="file"&&s.id===_.selectedArtifactId;return` + + `}).join(""),i.onclick=s=>{const o=s.target.closest(".artifact-tab");o?.dataset?.artifactId&&Tc(o.dataset.artifactId)},Ud()),e&&e.classList.add("visible")}function Ud(){const t=document.getElementById("bundle-strip");!t||t.dataset.tabKeyboard==="bound"||(t.dataset.tabKeyboard="bound",t.addEventListener("keydown",e=>{if(e.defaultPrevented)return;const n=[document.getElementById("results-summary-tab"),...Array.from(document.querySelectorAll("#artifact-tabs .artifact-tab"))].filter(Boolean);if(!n.length||!n.includes(document.activeElement))return;let i=-1;const r=n.indexOf(document.activeElement);if(e.key==="ArrowRight")i=(r+1)%n.length;else if(e.key==="ArrowLeft")i=(r-1+n.length)%n.length;else if(e.key==="Home")i=0;else if(e.key==="End")i=n.length-1;else return;e.preventDefault();const s=n[i];if(!s)return;if(s.id==="results-summary-tab")fg();else{const a=s.dataset.artifactId;a&&Tc(a)}const o=s.id==="results-summary-tab"?document.getElementById("results-summary-tab"):document.querySelector(`#artifact-tabs .artifact-tab[data-artifact-id="${s.dataset.artifactId}"]`);o&&o.focus()}))}function Pr(){document.body.classList.add("results-fullscreen"),document.body.classList.add("results-with-sidebar");const t=document.getElementById("results-view"),e=document.getElementById("results-code-output"),n=document.getElementById("results-audit-output"),i=document.getElementById("results-summary-detail"),r=document.getElementById("artifact-results-split"),s=Hb(),o=fc();if(i&&(i.setAttribute("role","tabpanel"),i.setAttribute("aria-labelledby","results-summary-tab")),r){r.setAttribute("role","tabpanel");const a=s?.artifacts?.find(l=>l.id===_.selectedArtifactId);r.setAttribute("aria-labelledby",a?`artifact-tab-${a.id}`:"results-summary-tab")}zb(s),Gb(s),e&&(e.textContent=""),e&&(e.replaceChildren(),o.split(` +`).forEach((a,l)=>{const u=document.createElement("span");u.className="code-line",u.innerHTML=lp(a),!Ob()&&_.resultsViewMode==="file"&&(u.classList.add("is-in"),u.style.setProperty("--d",`${l*10}ms`),u.addEventListener("animationend",()=>u.classList.remove("is-in"),{once:!0})),e.appendChild(u)})),n&&(n.innerHTML=Vb(s)),i&&i.classList.toggle("hidden",_.resultsViewMode!=="summary"),r&&r.classList.toggle("hidden",_.resultsViewMode!=="file"),t&&t.classList.add("visible")}function Fr(t,e){const n=document.getElementById("main-stage-container"),i=E0(n),r=document.body.classList.contains("results-fullscreen");Ar(),document.getElementById("pipeline-progress")?.classList.remove("visible"),Wt(!0),_.selectedArtifactId||(_.selectedArtifactId=_i(_.artifactBundle).id),_.resultsViewMode="summary",document.body.classList.add("results-fullscreen");const s=document.getElementById("step3-output");s&&(s.textContent=""),Pr(),vn(),Kb(),r||up(i,n,["#bundle-strip",".summary-heading",".review-summary-text",".summary-spec",".review-score-column",".results-action-bar"].map(o=>document.querySelector(o)),{results:!0})}function Kb(){const t=document.getElementById("btn-feedback-up"),e=document.getElementById("btn-feedback-down"),n=document.getElementById("results-feedback-status");t&&(t.className="feedback-btn",t.setAttribute("aria-pressed","false"),t.disabled=!1,t.removeAttribute("aria-disabled")),e&&(e.className="feedback-btn",e.setAttribute("aria-pressed","false"),e.disabled=!1,e.removeAttribute("aria-disabled")),n&&(n.textContent=""),El=!1}function Tc(t){_.selectedArtifactId=t,_.resultsViewMode="file",Pr()}function fg(){_.resultsViewMode="summary",Pr()}function Yb(){const t=document.getElementById("btn-copy-results"),e=document.getElementById("results-copy-status"),n=fc(),i=(r,s)=>{e&&(e.textContent=r,e.classList.toggle("ok",!!s),e.classList.toggle("fail",!s))};if(!navigator.clipboard?.writeText){i("Copying isn't supported in this browser.",!1);return}navigator.clipboard.writeText(n).then(()=>{if(i("Copied to clipboard",!0),t){t.classList.add("copied");const r=t.querySelector("span");if(r){const s=r.textContent;r.textContent="Copied!",setTimeout(()=>{t.classList.remove("copied"),r.textContent=s},2e3)}}}).catch(()=>{i("Clipboard permission was denied. Select the code to copy it manually.",!1)})}let El=!1;async function Jb(t){const e=document.getElementById("btn-feedback-up"),n=document.getElementById("btn-feedback-down"),i=document.getElementById("results-feedback-status");if(!e||!n||El)return;const r=l=>{i&&(i.textContent="",i.offsetWidth,i.textContent=l)},s=l=>{El=l,[e,n].forEach(u=>{u.disabled=l,u.setAttribute("aria-disabled",String(l))})},o=t==="up"?"thumbsUp":"thumbsDown";s(!0),r("Submitting review feedback…");const a={type:o,code:_.step2Result,input:_.step1Result};try{const l=await Ec(a.type,a.code,a.input);if(!l||l.success!==!0){s(!1),r("Review feedback could not be sent. Tap again to retry.");return}e.classList.toggle("active-up",t==="up"),n.classList.toggle("active-down",t==="down"),e.setAttribute("aria-pressed",String(t==="up")),n.setAttribute("aria-pressed",String(t==="down")),s(!1),r("Review feedback saved.")}catch{s(!1),r("Review feedback could not be sent. Tap again to retry.")}}function Zb(){const t=document.getElementById("error-input-panel");if(t){t.classList.remove("hidden"),t.style.display="flex";const e=document.getElementById("ff-error-paste-input");e&&setTimeout(()=>e.focus(),100)}}function hg(){const t=document.getElementById("error-input-panel");t&&(t.classList.add("hidden"),t.style.display="none")}function Xb(){const t=document.getElementById("shell-stage"),e=document.getElementById("main-stage-container"),n=e?.querySelector(".pipeline-prompt-recap"),i=window.matchMedia("(max-width: 920px)"),r=()=>t?.style.setProperty("--fit",Math.min(1,document.documentElement.clientWidth/1920)),s=()=>{if(!n)return;const o=n.contains(document.activeElement)?document.activeElement:null;i.matches?e.appendChild(n):e.prepend(n),o?.focus({preventScroll:!0})};r(),s(),window.addEventListener("resize",r),i.addEventListener("change",s)}function Wt(t){const e=document.getElementById("generation-stage");if(!e)return;const n=document.getElementById("hero");n&&(n.hidden=t,n.inert=t),t?(e.hidden=!1,e.inert=!1,e.classList.add("is-active")):(An(),document.body.classList.remove("results-fullscreen","results-with-sidebar"),e.classList.remove("is-active"),e.inert=!0,e.hidden=!0)}function pg(){const t=H.isVerified&&!!H.email,e=he.tier||"free",n=t&&ki(),i=!t||Ht(),s=n?"Checking…":i?Ul[e]||"Free":"—",o=document.getElementById("topbar-plan");o&&(o.textContent=s);const a=document.getElementById("topbar-avatar");a&&(a.textContent=(H.email||"?")[0].toUpperCase()),xc();const l=document.getElementById("plans-free-current");l&&l.classList.toggle("hidden",e!=="free"||!i);const u=document.getElementById("plans-checkout-btn-professional");if(u){const d=e==="professional"&&i;u.disabled=d,u.textContent=d?"Current plan":"Subscribe"}const c=document.getElementById("plans-checkout-btn-power");if(c){const d=e==="power"&&i;c.disabled=d,c.textContent=d?"Current plan":"Subscribe"}}function Qb(){pg();const t=document.getElementById("credits-modal");t&&Ke(t)}function eE(t){if(t&&t.target!==t.currentTarget)return;const e=document.getElementById("credits-modal");e&&Ye(e)}function gg(t,e=!0,n=!0){if(t=["home","account","plans"].includes(t)?t:"home",document.body.dataset.shellView=t,t!=="home"&&(An(),ec?.cancelTyping?.(),_.isRunning&&(og(),Gp(),_.isRunning=!1,Gs(!1),Ci(),_.artifactBundle?Pr():(document.getElementById("results-view")?.classList.remove("visible"),document.getElementById("ready-state")?.classList.remove("hidden")))),document.querySelectorAll(".view[data-view]").forEach(r=>{r.dataset.view===t?(r.hidden=!1,r.removeAttribute("inert"),requestAnimationFrame(()=>{r.classList.add("is-active"),n&&r.focus({preventScroll:!0})})):(r.classList.remove("is-active"),r.setAttribute("inert","true"),setTimeout(()=>{r.classList.contains("is-active")||(r.hidden=!0)},260))}),t!=="home")Wt(!1);else{const r=document.getElementById("main-stage-container");r&&r.classList.contains("visible")&&Wt(!0)}if(e){const r=t==="home"?"":`#${t}`;window.location.hash!==r&&window.history.pushState({view:t},"",r||"#")}}let Hd=!1;function Mc(){const t=window.location.hash.replace(/^#/,"");gg(t||"home",!1,Hd),Hd=!0}window.addEventListener("popstate",t=>{Mc()});window.addEventListener("hashchange",()=>{Mc()});window.copyResultsCode=Yb;window.selectArtifact=Tc;window.selectResultsSummary=fg;window.submitResultsFeedback=Jb;window.showErrorInputPanel=Zb;window.hideErrorInputPanel=hg;window.setGenerationStageVisible=Wt;window.switchView=gg;window.selectPipelineStage=Lb;window.editPipelinePrompt=bl;window.retryPipelineRun=ug;window.openCreditsModal=Qb;window.closeCreditsModal=eE; diff --git a/dist/index.html b/dist/index.html index 2e28dca..8e2e158 100644 --- a/dist/index.html +++ b/dist/index.html @@ -32,41 +32,24 @@ - - - -
    - - - -
    -
    -
    -
    -
    -

    FlutterFlow Custom Code, Solved.

    -

    We speak Dart with a FlutterFlow accent.
    Custom widgets and actions tailored to your project, fully reviewed and deployed in one click

    -
    -
    -
    - -
    -
    -
    -

    Watch the Tutorials

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