@agent-native/core 0.63.2 → 0.63.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.js +23 -19
- package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
- package/dist/client/blocks/library/diagram.d.ts.map +1 -1
- package/dist/client/blocks/library/diagram.js +10 -11
- package/dist/client/blocks/library/diagram.js.map +1 -1
- package/dist/client/blocks/library/wireframe.d.ts.map +1 -1
- package/dist/client/blocks/library/wireframe.js +2 -1
- package/dist/client/blocks/library/wireframe.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +5 -1
- package/dist/server/auth.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +50 -5
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/styles/blocks.css +25 -3
- package/docs/content/a2a-protocol.md +48 -10
- package/docs/content/actions.md +35 -16
- package/docs/content/agent-mentions.md +25 -32
- package/docs/content/agent-surfaces.md +31 -0
- package/docs/content/agent-teams.md +17 -14
- package/docs/content/agent-web-surfaces.md +24 -15
- package/docs/content/authentication.md +21 -0
- package/docs/content/automations.md +37 -21
- package/docs/content/blueprint-installer.md +7 -0
- package/docs/content/cli-adapters.md +7 -0
- package/docs/content/client.md +14 -0
- package/docs/content/cloneable-saas.md +14 -0
- package/docs/content/code-agents-ui.md +27 -0
- package/docs/content/components.md +21 -0
- package/docs/content/context-awareness.md +33 -48
- package/docs/content/creating-templates.md +43 -52
- package/docs/content/cross-app-sso.md +41 -0
- package/docs/content/database.md +41 -21
- package/docs/content/deployment.md +23 -6
- package/docs/content/dispatch.md +27 -0
- package/docs/content/drop-in-agent.md +26 -27
- package/docs/content/durable-resume.md +13 -1
- package/docs/content/embedding-sdk.md +14 -0
- package/docs/content/evals.md +14 -0
- package/docs/content/extensions.md +19 -0
- package/docs/content/external-agents.md +38 -1
- package/docs/content/faq.md +14 -0
- package/docs/content/file-uploads.md +20 -0
- package/docs/content/frames.md +14 -0
- package/docs/content/getting-started.md +34 -16
- package/docs/content/harness-agents.md +14 -0
- package/docs/content/human-approval.md +15 -30
- package/docs/content/key-concepts.md +37 -0
- package/docs/content/local-file-mode.md +26 -19
- package/docs/content/mcp-apps.md +36 -1
- package/docs/content/mcp-clients.md +49 -0
- package/docs/content/mcp-protocol.md +36 -0
- package/docs/content/messaging.md +34 -8
- package/docs/content/migration-workbench.md +7 -0
- package/docs/content/multi-app-workspace.md +29 -16
- package/docs/content/multi-tenancy.md +14 -0
- package/docs/content/native-chat-ui.md +20 -3
- package/docs/content/notifications.md +30 -0
- package/docs/content/observability.md +20 -1
- package/docs/content/observational-memory.md +14 -0
- package/docs/content/onboarding.md +32 -41
- package/docs/content/plan-plugin.md +14 -0
- package/docs/content/pr-visual-recap.md +14 -0
- package/docs/content/processors.md +7 -0
- package/docs/content/progress.md +23 -0
- package/docs/content/pure-agent-apps.md +7 -0
- package/docs/content/real-time-collaboration.md +19 -18
- package/docs/content/recurring-jobs.md +22 -19
- package/docs/content/routing.md +8 -0
- package/docs/content/sandbox-adapters.md +19 -0
- package/docs/content/security.md +38 -0
- package/docs/content/server.md +47 -25
- package/docs/content/sharing.md +50 -0
- package/docs/content/skills-guide.md +27 -42
- package/docs/content/template-analytics.md +71 -41
- package/docs/content/template-assets.md +76 -3
- package/docs/content/template-brain.md +89 -1
- package/docs/content/template-calendar.md +86 -58
- package/docs/content/template-chat.md +25 -9
- package/docs/content/template-clips.md +124 -16
- package/docs/content/template-content.md +146 -47
- package/docs/content/template-design.md +62 -2
- package/docs/content/template-dispatch.md +56 -9
- package/docs/content/template-forms.md +69 -13
- package/docs/content/template-mail.md +73 -26
- package/docs/content/template-plan.md +80 -1
- package/docs/content/template-slides.md +95 -74
- package/docs/content/template-videos.md +73 -52
- package/docs/content/tracking.md +21 -0
- package/docs/content/using-your-agent.md +14 -0
- package/docs/content/voice-input.md +31 -10
- package/docs/content/what-is-agent-native.md +25 -13
- package/docs/content/workspace-connections.md +49 -0
- package/docs/content/workspace-management.md +24 -0
- package/docs/content/workspace.md +50 -19
- package/docs/content/writing-agent-instructions.md +7 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onboarding-html.js","sourceRoot":"","sources":["../../src/server/onboarding-html.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * First-run onboarding page for agent-native apps.\n *\n * Shown when Better Auth is active and the user isn't signed in.\n * Provides a path to create or sign into an account from day one.\n *\n * After first account exists, this page acts as a normal login page.\n */\n\nimport { getPublicOAuthOrigin } from \"./oauth-public-origin.js\";\nimport {\n resolveGoogleAuthMode,\n type GoogleAuthMode,\n} from \"./google-auth-mode.js\";\nimport { getWorkspaceGatewayReturnOrigin } from \"./oauth-return-url.js\";\nimport { identitySsoLoginButtonHtml } from \"./identity-sso-store.js\";\nimport {\n resolveBuiltInAuthMarketing,\n type AuthMarketingContent,\n} from \"./auth-marketing.js\";\nimport { AUTH_REDIRECT_QUERY_PARAM } from \"../shared/auth-redirect-url.js\";\nimport {\n AGENT_NATIVE_SOCIAL_IMAGE_ALT,\n AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT,\n AGENT_NATIVE_SOCIAL_IMAGE_PATH,\n AGENT_NATIVE_SOCIAL_IMAGE_TYPE,\n AGENT_NATIVE_SOCIAL_IMAGE_WIDTH,\n withAgentNativeSocialImageCacheBuster,\n} from \"../shared/social-meta.js\";\nimport { normalizeAppBasePath } from \"./app-base-path.js\";\n\nfunction hasGoogleOAuth(): boolean {\n return !!(process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET);\n}\n\nfunction getConnectionLabel(): string {\n const url = process.env.DATABASE_URL || \"\";\n if (!url) return \"SQLite (local file)\";\n if (url.startsWith(\"postgres://\") || url.startsWith(\"postgresql://\")) {\n if (url.includes(\"neon.tech\")) return \"Neon Postgres\";\n if (url.includes(\"supabase\")) return \"Supabase Postgres\";\n return \"Postgres\";\n }\n if (url.startsWith(\"file:\")) return \"SQLite (local file)\";\n if (url.startsWith(\"libsql://\") || url.includes(\"turso.io\")) return \"Turso\";\n return \"SQL database\";\n}\n\nfunction withAppBasePath(path: string): string {\n const cleanPath = path.startsWith(\"/\") ? path : `/${path}`;\n const basePath = normalizeAppBasePath(\n process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH,\n );\n return `${basePath}${cleanPath}`;\n}\n\nexport interface OnboardingHtmlOptions {\n /**\n * Hide email/password forms and show ONLY the Google sign-in button.\n * Useful for templates (mail, calendar) where Google is required anyway.\n * If Google OAuth env vars are not configured, an error message is shown.\n */\n googleOnly?: boolean;\n /**\n * Product marketing content shown alongside the sign-in form.\n * When provided, the page uses a split layout: marketing on the left,\n * sign-in form on the right (stacked on mobile).\n */\n marketing?: {\n appName: string;\n tagline: string;\n description?: string;\n features?: string[];\n runLocalCommand?: string;\n };\n /**\n * Request context used only to recover branded first-party marketing when a\n * default auth guard serves before a template-specific auth plugin.\n */\n requestHost?: string;\n requestPath?: string;\n requestOrigin?: string;\n /**\n * Optional preflight copy shown before redirecting through Google sign-in.\n * Use this when a hosted app needs to warn about provider-specific consent\n * screens while leaving self-hosted deployments untouched.\n */\n googleSignInNotice?: {\n host?: string;\n title: string;\n body: string | string[];\n continueLabel?: string;\n cancelLabel?: string;\n };\n /**\n * Google sign-in flow: `'popup'`, `'redirect'`, or `'auto'` (default).\n * Falls back to `GOOGLE_AUTH_MODE` env var, then `'auto'`. Builder web\n * iframes use popup; Builder desktop preview/editor surfaces use redirect.\n */\n googleAuthMode?: GoogleAuthMode;\n}\n\nexport function getOnboardingHtml(opts: OnboardingHtmlOptions = {}): string {\n const showGoogle = hasGoogleOAuth();\n const googleOnly = !!opts.googleOnly;\n // In a Google-only app, Google is the sole sign-in method, so always render\n // a working button — never gate it on env vars detected at render time. The\n // login page is a public, CDN-cacheable shell served to everyone (per-user\n // and per-config state is resolved client-side after load), so baking a\n // \"not configured\" message in here would freeze that error into the cache\n // for every visitor. A genuinely misconfigured server instead surfaces a\n // clear error at click time via the auth API.\n const renderGoogleButton = showGoogle || googleOnly;\n const appBasePath = normalizeAppBasePath(\n process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH,\n );\n const publicOAuthOrigin = getPublicOAuthOrigin();\n const workspaceGatewayReturnOrigin = getWorkspaceGatewayReturnOrigin();\n const googleAuthMode = resolveGoogleAuthMode(opts.googleAuthMode);\n\n const marketing: AuthMarketingContent | undefined =\n opts.marketing ??\n resolveBuiltInAuthMarketing({\n requestHost: opts.requestHost,\n requestPath: opts.requestPath,\n });\n const hasMarketing = !!marketing;\n const runLocalCommand = marketing?.runLocalCommand?.trim();\n const brandMarkSrc = withAppBasePath(\"/agent-native-icon-dark.svg\");\n const socialImageUrl = withAgentNativeSocialImageCacheBuster(\n opts.requestOrigin\n ? `${opts.requestOrigin}${withAppBasePath(AGENT_NATIVE_SOCIAL_IMAGE_PATH)}`\n : withAppBasePath(AGENT_NATIVE_SOCIAL_IMAGE_PATH),\n );\n const esc = (s: string) =>\n s\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\n const googleSignInNotice = opts.googleSignInNotice;\n const googleNoticeBodyParts = googleSignInNotice\n ? (Array.isArray(googleSignInNotice.body)\n ? googleSignInNotice.body\n : [googleSignInNotice.body]\n ).filter((body) => body.trim().length > 0)\n : [];\n const googleNoticeBodyHtml = googleNoticeBodyParts\n .map(\n (body, index) =>\n `<p class=\"google-preflight-copy\"${index === 0 ? ' id=\"google-preflight-copy\"' : \"\"}>${esc(body)}</p>`,\n )\n .join(\"\\n\");\n const googleNoticeRunLocalHtml = runLocalCommand\n ? `\n <button type=\"button\" class=\"btn-secondary google-preflight-local\" id=\"google-preflight-run-local\" onclick=\"__anChooseRunLocalFromGoogleNotice()\">${esc(googleSignInNotice?.cancelLabel ?? \"Run locally\")}</button>`\n : `\n <button type=\"button\" class=\"btn-secondary\" onclick=\"__anHideGoogleNotice()\">${esc(googleSignInNotice?.cancelLabel ?? \"Close\")}</button>`;\n const googleNoticeRunLocalPanelHtml = runLocalCommand\n ? `\n <div class=\"google-preflight-command\" id=\"google-preflight-run-local-panel\" hidden data-command=\"${esc(runLocalCommand)}\">\n <p class=\"google-preflight-command-label\">Use your own Google OAuth client:</p>\n <code>${esc(runLocalCommand)}</code>\n <button type=\"button\" class=\"copy-run-local\" id=\"copy-google-preflight-run-local\" onclick=\"__anCopyGoogleNoticeRunLocalCommand()\">Copy command</button>\n </div>`\n : \"\";\n const googleNoticeHtml =\n renderGoogleButton && googleSignInNotice\n ? `\n <div\n class=\"google-preflight\"\n id=\"google-preflight\"\n data-host=\"${esc(googleSignInNotice.host ?? \"\")}\"\n role=\"dialog\"\n aria-labelledby=\"google-preflight-title\"\n aria-describedby=\"google-preflight-copy\"\n tabindex=\"-1\"\n >\n <div class=\"google-preflight-heading\">\n <p class=\"google-preflight-title\" id=\"google-preflight-title\">${esc(googleSignInNotice.title)}</p>\n <button type=\"button\" class=\"google-preflight-close\" aria-label=\"Close Google sign-in choices\" onclick=\"__anHideGoogleNotice()\">×</button>\n </div>\n${googleNoticeBodyHtml}\n <div class=\"google-preflight-actions\">\n <button type=\"button\" class=\"btn-primary\" id=\"google-preflight-continue\" onclick=\"__anAcceptGoogleNotice()\">${esc(googleSignInNotice.continueLabel ?? \"Continue\")}</button>\n${googleNoticeRunLocalHtml}\n </div>\n${googleNoticeRunLocalPanelHtml}\n </div>`\n : \"\";\n\n const marketingStyles = hasMarketing\n ? `\n body.has-marketing { padding: 0; position: relative; overflow-x: hidden; }\n #starfield {\n position: fixed;\n inset: 0;\n width: 100%;\n height: 100%;\n opacity: 0.35;\n pointer-events: none;\n z-index: 0;\n }\n @media (prefers-reduced-motion: reduce) {\n #starfield { opacity: 0.18; }\n }\n .split {\n position: relative;\n z-index: 1;\n display: flex;\n min-height: 100vh;\n width: 100%;\n max-width: 1100px;\n margin: 0 auto;\n }\n .marketing-panel {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n padding: 3rem 3.5rem;\n }\n .marketing-content { max-width: 480px; }\n .app-name {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n font-size: 2rem;\n font-weight: 700;\n color: #fff;\n margin-bottom: 0.625rem;\n letter-spacing: -0.02em;\n }\n .app-name img.brand-mark {\n height: 2.21375rem;\n width: auto;\n display: block;\n flex-shrink: 0;\n }\n .app-tagline {\n font-size: 1.25rem;\n color: #a1a1aa;\n line-height: 1.6;\n margin-bottom: 2rem;\n }\n .app-desc {\n font-size: 1rem;\n color: #71717a;\n line-height: 1.6;\n margin-bottom: 2rem;\n }\n .feature-list {\n list-style: none;\n display: flex;\n flex-direction: column;\n gap: 0.875rem;\n }\n .feature-list li {\n display: flex;\n align-items: flex-start;\n gap: 0.625rem;\n font-size: 1rem;\n color: #a1a1aa;\n line-height: 1.5;\n }\n .feature-list li::before {\n content: '';\n flex-shrink: 0;\n width: 8px;\n height: 8px;\n margin-top: 6px;\n border-radius: 50%;\n background: #3f3f46;\n border: 1px solid #52525b;\n }\n .oss-link {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n font-size: 0.8125rem;\n font-weight: 600;\n color: #00B5FF;\n text-decoration: none;\n transition: color 0.15s ease;\n }\n .oss-link:hover { color: #33C4FF; }\n .oss-link svg { width: 15px; height: 15px; flex-shrink: 0; }\n .marketing-actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0.75rem;\n margin-top: 2rem;\n }\n .run-local-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-height: 2.25rem;\n padding: 0.5rem 0.875rem;\n background: rgba(255,255,255,0.08);\n color: #fff;\n border: 1px solid rgba(255,255,255,0.14);\n border-radius: 8px;\n font-size: 0.8125rem;\n font-weight: 500;\n cursor: pointer;\n }\n .run-local-button:hover {\n background: rgba(255,255,255,0.12);\n border-color: rgba(255,255,255,0.24);\n }\n .run-local-panel {\n max-width: 480px;\n margin-top: 0.75rem;\n padding: 0.75rem;\n background: rgba(20,20,20,0.86);\n border: 1px solid rgba(255,255,255,0.1);\n border-radius: 10px;\n box-shadow: 0 14px 36px rgba(0,0,0,0.28);\n }\n .run-local-panel[hidden] { display: none; }\n .run-local-panel code {\n display: block;\n overflow-x: auto;\n padding-bottom: 0.125rem;\n color: #e5e5e5;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", monospace;\n font-size: 0.75rem;\n line-height: 1.5;\n white-space: nowrap;\n }\n .copy-run-local {\n margin-top: 0.625rem;\n padding: 0.375rem 0.625rem;\n background: transparent;\n color: #a1a1aa;\n border: 1px solid rgba(255,255,255,0.12);\n border-radius: 6px;\n font-size: 0.75rem;\n cursor: pointer;\n }\n .copy-run-local:hover { color: #fff; border-color: rgba(255,255,255,0.22); }\n .form-panel {\n flex: 0 0 440px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 2rem;\n }\n .form-panel .card { max-width: 400px; }\n .form-panel .local-note { max-width: 400px; }\n @media (max-width: 900px) {\n .split { flex-direction: column; min-height: auto; }\n .marketing-panel { padding: 2rem 1.5rem 1.5rem; }\n .app-name { font-size: 1.375rem; }\n .app-name img.brand-mark { height: 1.58125rem; }\n .app-tagline { font-size: 1rem; margin-bottom: 1rem; }\n .app-desc { margin-bottom: 1rem; }\n .feature-list { gap: 0.5rem; }\n .form-panel { flex: none; padding: 1.5rem 1rem; }\n }\n`\n : \"\";\n\n const marketingPanelHtml = hasMarketing\n ? `<canvas id=\"starfield\"></canvas>\n<div class=\"split\">\n <div class=\"marketing-panel\">\n <div class=\"marketing-content\">\n <h2 class=\"app-name\">\n <img class=\"brand-mark\" src=\"${esc(brandMarkSrc)}\" alt=\"\" aria-hidden=\"true\" />\n <span>${esc(marketing!.appName)}</span>\n </h2>\n <p class=\"app-tagline\">${esc(marketing!.tagline)}</p>\n${marketing!.description ? ` <p class=\"app-desc\">${esc(marketing!.description)}</p>\\n` : \"\"}${\n marketing!.features?.length\n ? ` <ul class=\"feature-list\">\\n${marketing!.features.map((f) => ` <li>${esc(f)}</li>`).join(\"\\n\")}\\n </ul>\\n`\n : \"\"\n } <div class=\"marketing-actions\">\n${runLocalCommand ? ` <button type=\"button\" class=\"run-local-button\" id=\"run-local-button\" aria-expanded=\"false\" aria-controls=\"run-local-panel\" onclick=\"__anToggleRunLocalCommand()\">Run Locally</button>\\n` : \"\"} <a class=\"oss-link\" href=\"https://github.com/BuilderIO/agent-native\" target=\"_blank\" rel=\"noreferrer\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 19c-4.3 1.4-4.3-2.5-6-3m12 5v-3.5c0-1 .1-1.4-.5-2 2.8-.3 5.5-1.4 5.5-6a4.6 4.6 0 00-1.3-3.2 4.2 4.2 0 00-.1-3.2s-1.1-.3-3.5 1.3a12.3 12.3 0 00-6.2 0C6.5 2.8 5.4 3.1 5.4 3.1a4.2 4.2 0 00-.1 3.2A4.6 4.6 0 004 9.5c0 4.6 2.7 5.7 5.5 6-.6.6-.6 1.2-.5 2V21\"/></svg>\n 100% free and open source\n </a>\n </div>\n${\n runLocalCommand\n ? ` <div class=\"run-local-panel\" id=\"run-local-panel\" hidden data-command=\"${esc(runLocalCommand)}\">\n <code>${esc(runLocalCommand)}</code>\n <button type=\"button\" class=\"copy-run-local\" id=\"copy-run-local\" onclick=\"__anCopyRunLocalCommand()\">Copy command</button>\n </div>\\n`\n : \"\"\n}\n </div>\n </div>\n <div class=\"form-panel\">`\n : \"\";\n\n const marketingCloseHtml = hasMarketing ? `\\n </div>\\n</div>` : \"\";\n\n const starfieldScript = hasMarketing\n ? `\n (function initStarfield() {\n var canvas = document.getElementById('starfield');\n if (!canvas) return;\n var gl = canvas.getContext('webgl', { alpha: false, antialias: false });\n if (!gl) return;\n\n var vs = gl.createShader(gl.VERTEX_SHADER);\n gl.shaderSource(vs, 'attribute vec2 position;void main(){gl_Position=vec4(position,0.0,1.0);}');\n gl.compileShader(vs);\n\n var fs = gl.createShader(gl.FRAGMENT_SHADER);\n gl.shaderSource(fs, [\n 'precision highp float;',\n 'uniform float iTime;uniform vec2 iResolution;uniform vec3 uPointer;',\n '#define S(a,b,t) smoothstep(a,b,t)',\n '#define NUM_LAYERS 4.',\n 'float N21(vec2 p){vec3 a=fract(vec3(p.xyx)*vec3(213.897,653.453,253.098));a+=dot(a,a.yzx+79.76);return fract((a.x+a.y)*a.z);}',\n 'vec2 GetPos(vec2 id,vec2 offs,float t){float n=N21(id+offs);float n1=fract(n*10.);float n2=fract(n*100.);float a=t+n;return offs+vec2(sin(a*n1),cos(a*n2))*.4;}',\n 'vec2 Attract(vec2 p,vec2 cursor,float strength){vec2 delta=cursor-p;float d=length(delta);float pull=1.-smoothstep(.08,1.9,d);pull=pull*pull*(3.-2.*pull);return p+delta*pull*.095*strength;}',\n 'float df_line(vec2 a,vec2 b,vec2 p){vec2 pa=p-a,ba=b-a;float h=clamp(dot(pa,ba)/dot(ba,ba),0.,1.);return length(pa-ba*h);}',\n 'float line(vec2 a,vec2 b,vec2 uv){float r1=.025;float r2=.006;float d=df_line(a,b,uv);float d2=length(a-b);float fade=S(1.5,.5,d2);fade+=S(.05,.02,abs(d2-.75));return S(r1,r2,d)*fade;}',\n 'float NetLayer(vec2 st,float n,float t,vec2 pointer,float pointerStrength){',\n ' vec2 cell=floor(st);vec2 id=cell+n;vec2 cursor=pointer-cell;st=fract(st)-.5;',\n ' vec2 p0=Attract(GetPos(id,vec2(-1,-1),t),cursor,pointerStrength);vec2 p1=Attract(GetPos(id,vec2(0,-1),t),cursor,pointerStrength);vec2 p2=Attract(GetPos(id,vec2(1,-1),t),cursor,pointerStrength);',\n ' vec2 p3=Attract(GetPos(id,vec2(-1,0),t),cursor,pointerStrength);vec2 p4=Attract(GetPos(id,vec2(0,0),t),cursor,pointerStrength);vec2 p5=Attract(GetPos(id,vec2(1,0),t),cursor,pointerStrength);',\n ' vec2 p6=Attract(GetPos(id,vec2(-1,1),t),cursor,pointerStrength);vec2 p7=Attract(GetPos(id,vec2(0,1),t),cursor,pointerStrength);vec2 p8=Attract(GetPos(id,vec2(1,1),t),cursor,pointerStrength);',\n ' float m=0.;float sparkle=0.;float d;float s;float pulse;',\n ' m+=line(p4,p0,st);d=length(st-p0);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p0.x)+fract(p0.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p4,p1,st);d=length(st-p1);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p1.x)+fract(p1.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p4,p2,st);d=length(st-p2);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p2.x)+fract(p2.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p4,p3,st);d=length(st-p3);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p3.x)+fract(p3.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p4,p4,st);d=length(st-p4);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p4.x)+fract(p4.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p4,p5,st);d=length(st-p5);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p5.x)+fract(p5.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p4,p6,st);d=length(st-p6);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p6.x)+fract(p6.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p4,p7,st);d=length(st-p7);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p7.x)+fract(p7.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p4,p8,st);d=length(st-p8);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p8.x)+fract(p8.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p1,p3,st);m+=line(p1,p5,st);m+=line(p7,p5,st);m+=line(p7,p3,st);',\n ' float sPhase=(sin(t+n)+sin(t*.1))*.25+.5;sPhase+=pow(sin(t*.1)*.5+.5,50.)*5.;m+=sparkle*sPhase;',\n ' return m;',\n '}',\n 'void mainImage(out vec4 fragColor,in vec2 fragCoord){',\n ' vec2 uv=(fragCoord-iResolution.xy*.5)/iResolution.y;',\n ' float t=iTime*.03;float s=sin(t);float c=cos(t);mat2 rot=mat2(c,-s,s,c);vec2 st=uv*rot;vec2 pointerUv=(uPointer.xy-iResolution.xy*.5)/iResolution.y;',\n ' float m=0.;',\n ' for(float i=0.;i<1.;i+=1./NUM_LAYERS){float z=fract(t+i);float size=mix(15.,1.,z);float fade=S(0.,.6,z)*S(1.,.8,z);vec2 pointerSt=pointerUv*rot*size;vec2 layerSt=st*size;float warp=1.-smoothstep(.15,2.7,length(layerSt-pointerSt));warp=warp*warp*(3.-2.*warp)*uPointer.z;layerSt-=(pointerSt-layerSt)*warp*.035;m+=fade*NetLayer(layerSt,i,iTime*0.3,pointerSt,uPointer.z);}',\n ' float cursorLift=1.-smoothstep(.04,.48,length(uv-pointerUv));cursorLift=cursorLift*cursorLift*(3.-2.*cursorLift)*uPointer.z;m*=1.+cursorLift*1.6;',\n ' vec3 col=vec3(0.35)*m;col*=1.-dot(uv,uv);',\n ' float tt=min(iTime,5.0);col*=S(0.,20.,tt);',\n ' col=clamp(col,0.,1.);fragColor=vec4(col,1.);',\n '}',\n 'void main(){mainImage(gl_FragColor,gl_FragCoord.xy);}'\n ].join('\\\\n'));\n gl.compileShader(fs);\n\n var prog = gl.createProgram();\n gl.attachShader(prog, vs);\n gl.attachShader(prog, fs);\n gl.linkProgram(prog);\n gl.useProgram(prog);\n\n var buf = gl.createBuffer();\n gl.bindBuffer(gl.ARRAY_BUFFER, buf);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]), gl.STATIC_DRAW);\n var pos = gl.getAttribLocation(prog, 'position');\n gl.enableVertexAttribArray(pos);\n gl.vertexAttribPointer(pos, 2, gl.FLOAT, false, 0, 0);\n\n var uTime = gl.getUniformLocation(prog, 'iTime');\n var uRes = gl.getUniformLocation(prog, 'iResolution');\n var uPointer = gl.getUniformLocation(prog, 'uPointer');\n var reducedMotionQuery = window.matchMedia ? window.matchMedia('(prefers-reduced-motion: reduce)') : null;\n var reducedMotion = reducedMotionQuery ? reducedMotionQuery.matches : false;\n var pointerDpr = 1, hasPointer = false;\n var pointerX = 0, pointerY = 0, pointerStrength = 0;\n var targetX = 0, targetY = 0, targetStrength = 0;\n\n function resize() {\n var w = window.innerWidth, h = window.innerHeight;\n pointerDpr = Math.min(window.devicePixelRatio, 1.5);\n canvas.width = w * pointerDpr; canvas.height = h * pointerDpr;\n gl.viewport(0, 0, canvas.width, canvas.height);\n if (!hasPointer) {\n pointerX = targetX = canvas.width * 0.5;\n pointerY = targetY = canvas.height * 0.5;\n }\n }\n function onPointerMove(event) {\n var rect = canvas.getBoundingClientRect();\n var x = event.clientX - rect.left;\n var y = event.clientY - rect.top;\n hasPointer = true;\n targetX = x * pointerDpr;\n targetY = (rect.height - y) * pointerDpr;\n targetStrength = x >= 0 && x <= rect.width && y >= 0 && y <= rect.height ? 1 : 0;\n }\n function fadePointer() {\n targetStrength = 0;\n }\n function easePointer(allowPointer) {\n if (!allowPointer) {\n pointerStrength = 0;\n return;\n }\n pointerX += (targetX - pointerX) * 0.22;\n pointerY += (targetY - pointerY) * 0.22;\n pointerStrength += (targetStrength - pointerStrength) * 0.14;\n if (pointerStrength < 0.001 && targetStrength === 0) pointerStrength = 0;\n }\n resize();\n window.addEventListener('resize', resize);\n window.addEventListener('pointermove', onPointerMove, { passive: true });\n window.addEventListener('mousemove', onPointerMove, { passive: true });\n document.addEventListener('pointerleave', fadePointer, { passive: true });\n window.addEventListener('blur', fadePointer);\n\n var start = performance.now(), last = 0, raf = 0, reducedMotionStaticTime = 20;\n function draw(timeSeconds, allowPointer) {\n easePointer(allowPointer !== false && !reducedMotion);\n gl.uniform1f(uTime, timeSeconds);\n gl.uniform2f(uRes, canvas.width, canvas.height);\n gl.uniform3f(uPointer, pointerX, pointerY, pointerStrength);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n }\n function render(now) {\n if (reducedMotion) {\n raf = 0;\n return;\n }\n raf = requestAnimationFrame(render);\n if (now - last < 33) return;\n last = now;\n draw((now - start) * 0.001);\n }\n function startAnimation() {\n if (!raf) raf = requestAnimationFrame(render);\n }\n function stopAnimation() {\n if (raf) {\n cancelAnimationFrame(raf);\n raf = 0;\n }\n }\n function onReducedMotionChange() {\n reducedMotion = reducedMotionQuery ? reducedMotionQuery.matches : false;\n if (reducedMotion) {\n stopAnimation();\n last = 0;\n draw(reducedMotionStaticTime, false);\n } else {\n startAnimation();\n }\n }\n draw(reducedMotion ? reducedMotionStaticTime : 0, !reducedMotion);\n if (reducedMotionQuery) {\n if (reducedMotionQuery.addEventListener) {\n reducedMotionQuery.addEventListener('change', onReducedMotionChange);\n } else {\n reducedMotionQuery.addListener(onReducedMotionChange);\n }\n }\n if (!reducedMotion) startAnimation();\n })();`\n : \"\";\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\">\n<title>${hasMarketing ? esc(marketing!.appName) + \" — Sign in\" : \"Welcome\"}</title>\n<link rel=\"icon\" type=\"image/svg+xml\" href=\"${withAppBasePath(\"/favicon.svg\")}\">\n<link rel=\"apple-touch-icon\" href=\"${withAppBasePath(\"/icon-180.svg\")}\">\n${\n hasMarketing\n ? `<meta name=\"description\" content=\"${esc(marketing!.tagline)}\">\n<meta property=\"og:title\" content=\"${esc(marketing!.appName)}\">\n<meta property=\"og:description\" content=\"${esc(marketing!.tagline)}\">\n<meta property=\"og:image\" content=\"${esc(socialImageUrl)}\">\n<meta property=\"og:image:secure_url\" content=\"${esc(socialImageUrl)}\">\n<meta property=\"og:image:type\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_TYPE}\">\n<meta property=\"og:image:width\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_WIDTH}\">\n<meta property=\"og:image:height\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT}\">\n<meta property=\"og:image:alt\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_ALT}\">\n<meta name=\"twitter:card\" content=\"summary_large_image\">\n<meta name=\"twitter:image\" content=\"${esc(socialImageUrl)}\">\n<meta name=\"twitter:image:alt\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_ALT}\">`\n : \"\"\n}\n<style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n background: #0a0a0a;\n color: #e5e5e5;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n padding: 1rem;\n }\n .card {\n width: 100%;\n max-width: 400px;\n padding: 2rem;\n background: #141414;\n border: 1px solid rgba(255,255,255,0.08);\n border-radius: 12px;\n }\n h1 { font-size: 1.25rem; font-weight: 600; margin-bottom: 0.25rem; color: #fff; }\n .subtitle { font-size: 0.8125rem; color: #888; margin-bottom: 1.5rem; }\n .tabs {\n display: inline-flex;\n width: 100%;\n padding: 4px;\n margin-bottom: 1.5rem;\n background: rgba(255,255,255,0.06);\n border-radius: 8px;\n }\n .tab {\n flex: 1;\n padding: 0.5rem 0.75rem;\n background: none;\n border: none;\n color: #888;\n font-size: 0.8125rem;\n font-weight: 500;\n cursor: pointer;\n border-radius: 6px;\n }\n .tab.active {\n background: #3a3a3a;\n color: #fff;\n box-shadow: 0 1px 2px rgba(0,0,0,0.3);\n }\n .tab:hover:not(.active) { color: #bbb; }\n .form { display: none; }\n .form.active { display: block; }\n .card.verifying .tabs,\n .card.verifying #google-btn,\n .card.verifying #google-err,\n .card.verifying #auth-divider,\n .card.verifying #upgrade-note {\n display: none;\n }\n label { display: block; font-size: 0.8125rem; color: #888; margin-bottom: 0.375rem; }\n input {\n width: 100%;\n padding: 0.5rem 0.75rem;\n background: transparent;\n border: 1px solid rgba(255,255,255,0.12);\n border-radius: 6px;\n color: #e5e5e5;\n font-size: 0.875rem;\n outline: none;\n margin-bottom: 0.875rem;\n }\n input:focus { border-color: rgba(255,255,255,0.3); box-shadow: 0 0 0 1px rgba(255,255,255,0.1); }\n input::placeholder { color: #555; }\n button[type=\"submit\"], .btn-primary {\n width: 100%;\n margin-top: 0.25rem;\n padding: 0.5rem;\n background: #fff;\n color: #000;\n border: none;\n border-radius: 6px;\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n }\n button[type=\"submit\"]:hover, .btn-primary:hover { background: #e5e5e5; }\n button[type=\"submit\"]:disabled { opacity: 0.5; cursor: not-allowed; }\n .btn-secondary {\n width: 100%;\n margin-top: 0.75rem;\n padding: 0.5rem;\n background: transparent;\n color: #888;\n border: 1px solid rgba(255,255,255,0.1);\n border-radius: 6px;\n font-size: 0.8125rem;\n cursor: pointer;\n }\n .btn-secondary:hover { color: #bbb; border-color: rgba(255,255,255,0.2); }\n .msg { margin-top: 0.75rem; font-size: 0.8125rem; display: none; }\n .msg.error { color: #f87171; }\n .msg.success { color: #4ade80; }\n .msg.show { display: block; }\n .step-progress {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 0.5rem;\n margin-bottom: 1.25rem;\n }\n .progress-step {\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.375rem;\n color: #666;\n font-size: 0.6875rem;\n line-height: 1.2;\n text-align: center;\n }\n .progress-step::before {\n content: '';\n position: absolute;\n top: 11px;\n left: calc(-50% + 16px);\n width: calc(100% - 32px);\n height: 1px;\n background: rgba(255,255,255,0.1);\n }\n .progress-step:first-child::before { display: none; }\n .progress-step span {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 999px;\n border: 1px solid rgba(255,255,255,0.14);\n background: #151515;\n color: #777;\n font-size: 0.6875rem;\n font-weight: 600;\n }\n .progress-step strong { font-weight: 500; }\n .progress-step.complete,\n .progress-step.current { color: #e5e5e5; }\n .progress-step.complete span {\n background: #d9f99d;\n border-color: #d9f99d;\n color: #111;\n }\n .progress-step.current span {\n background: #fff;\n border-color: #fff;\n color: #000;\n box-shadow: 0 0 0 4px rgba(255,255,255,0.08);\n }\n .verification-panel {\n padding: 1rem;\n margin-bottom: 0.875rem;\n background: rgba(255,255,255,0.04);\n border: 1px solid rgba(255,255,255,0.08);\n border-radius: 8px;\n }\n .verification-kicker {\n margin-bottom: 0.5rem;\n color: #bef264;\n font-size: 0.75rem;\n font-weight: 500;\n }\n .verification-copy {\n color: #d4d4d8;\n font-size: 0.875rem;\n line-height: 1.55;\n }\n .verification-copy strong {\n color: #fff;\n font-weight: 600;\n word-break: break-word;\n }\n .verification-note {\n margin-top: 0.75rem;\n color: #71717a;\n font-size: 0.75rem;\n line-height: 1.45;\n }\n .inline-actions {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.75rem;\n margin-top: 0.75rem;\n }\n .link-button {\n padding: 0.25rem 0;\n background: none;\n border: none;\n color: #888;\n cursor: pointer;\n font-size: 0.75rem;\n text-decoration: underline;\n text-underline-offset: 2px;\n }\n .link-button:hover { color: #bbb; }\n .link-button:disabled { cursor: wait; opacity: 0.5; }\n .divider {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n margin: 1.25rem 0;\n font-size: 0.75rem;\n color: #555;\n }\n .divider::before, .divider::after {\n content: '';\n flex: 1;\n height: 1px;\n background: rgba(255,255,255,0.08);\n }\n .upgrade-note {\n margin-bottom: 1rem;\n padding: 0.75rem;\n border: 1px solid rgba(255,255,255,0.08);\n border-radius: 8px;\n background: rgba(255,255,255,0.03);\n font-size: 0.75rem;\n line-height: 1.5;\n color: #a1a1aa;\n display: none;\n }\n .upgrade-note.show { display: block; }\n .btn-google {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.625rem;\n padding: 0.5rem;\n background: #fff;\n color: #000;\n border: none;\n border-radius: 6px;\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n }\n .btn-google:hover { background: #e5e5e5; }\n .btn-google:disabled { opacity: 0.5; cursor: wait; }\n .btn-google svg { width: 18px; height: 18px; flex-shrink: 0; }\n .google-signin {\n position: relative;\n width: 100%;\n }\n .google-error { margin-top: 0.5rem; font-size: 0.8125rem; color: #f87171; display: none; }\n .google-error.show { display: block; }\n .google-debug {\n display: none;\n margin-top: 0.5rem;\n font-size: 0.6875rem;\n line-height: 1.45;\n color: #777;\n word-break: break-word;\n }\n .google-debug.show { display: block; }\n .google-preflight {\n display: none;\n position: absolute;\n top: calc(100% + 0.625rem);\n left: 0;\n right: 0;\n z-index: 20;\n padding: 0.875rem;\n border: 1px solid rgba(255,255,255,0.12);\n border-radius: 10px;\n background: #1b1b1b;\n box-shadow: 0 18px 50px rgba(0,0,0,0.48);\n }\n .google-preflight.show { display: block; }\n .google-preflight::before {\n content: '';\n position: absolute;\n top: -6px;\n left: 50%;\n width: 10px;\n height: 10px;\n transform: translateX(-50%) rotate(45deg);\n background: #1b1b1b;\n border-left: 1px solid rgba(255,255,255,0.12);\n border-top: 1px solid rgba(255,255,255,0.12);\n }\n .google-preflight-heading {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 0.75rem;\n margin-bottom: 0.375rem;\n }\n .google-preflight-title {\n color: #fff;\n font-size: 0.8125rem;\n font-weight: 600;\n }\n .google-preflight-close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.5rem;\n height: 1.5rem;\n margin: -0.25rem -0.25rem 0 0;\n background: transparent;\n border: none;\n border-radius: 999px;\n color: #888;\n cursor: pointer;\n font-size: 1.125rem;\n line-height: 1;\n }\n .google-preflight-close:hover { color: #fff; background: rgba(255,255,255,0.07); }\n .google-preflight-copy {\n color: #b4b4b8;\n font-size: 0.75rem;\n line-height: 1.55;\n }\n .google-preflight-copy + .google-preflight-copy { margin-top: 0.5rem; }\n .google-preflight-actions {\n display: flex;\n gap: 0.5rem;\n margin-top: 0.875rem;\n }\n .google-preflight-actions .btn-primary,\n .google-preflight-actions .btn-secondary {\n flex: 1;\n width: auto;\n margin-top: 0;\n }\n .google-preflight-command {\n margin-top: 0.75rem;\n padding: 0.75rem;\n border: 1px solid rgba(255,255,255,0.1);\n border-radius: 8px;\n background: rgba(0,0,0,0.24);\n }\n .google-preflight-command[hidden] { display: none; }\n .google-preflight-command-label {\n margin-bottom: 0.5rem;\n color: #d4d4d8;\n font-size: 0.75rem;\n font-weight: 500;\n }\n .google-preflight-command code {\n display: block;\n overflow-x: auto;\n color: #e5e5e5;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", monospace;\n font-size: 0.71875rem;\n line-height: 1.45;\n white-space: nowrap;\n }\n @media (max-width: 480px) {\n .google-preflight {\n position: static;\n margin-top: 0.625rem;\n }\n .google-preflight::before { display: none; }\n .google-preflight-actions { flex-direction: column; }\n .google-preflight-actions .btn-primary,\n .google-preflight-actions .btn-secondary { width: 100%; }\n }\n .local-note {\n display: none;\n max-width: 400px;\n width: 100%;\n margin-top: 1rem;\n padding: 0.625rem 0.875rem;\n font-size: 0.6875rem;\n line-height: 1.5;\n color: #666;\n border: 1px dashed rgba(255,255,255,0.08);\n border-radius: 8px;\n text-align: center;\n }\n .local-note.show { display: block; }\n .local-note strong { color: #999; font-weight: 500; }\n .local-note a { color: #888; text-decoration: none; }\n .local-note a:hover { color: #bbb; }\n${marketingStyles}\n</style>\n</head>\n<body${hasMarketing ? ' class=\"has-marketing\"' : \"\"}>\n${marketingPanelHtml}\n<div class=\"card\">\n <h1 id=\"heading\">${googleOnly ? \"Sign in\" : \"Welcome\"}</h1>\n <p class=\"subtitle\" id=\"subtitle\">${googleOnly ? \"Use your workspace Google account to continue\" : \"Create an account to get started\"}</p>\n <p\n class=\"upgrade-note\"\n id=\"upgrade-note\"\n data-upgrade-copy=\"Continue signing in to attach this app to your account and migrate local data.\"\n ></p>\n${identitySsoLoginButtonHtml()}\n${\n renderGoogleButton\n ? `\n <div class=\"google-signin\" id=\"google-signin\">\n <button class=\"btn-google\" id=\"google-btn\" onclick=\"signInWithGoogle()\"${googleSignInNotice ? ' aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"google-preflight\"' : \"\"}>\n <svg viewBox=\"0 0 24 24\"><path fill=\"#4285F4\" d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z\"/><path fill=\"#34A853\" d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\"/><path fill=\"#FBBC05\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\"/><path fill=\"#EA4335\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\"/></svg>\n Sign in with Google\n </button>\n <p class=\"google-error\" id=\"google-err\"></p>\n <p class=\"google-debug\" id=\"google-debug\"></p>\n${googleNoticeHtml}\n </div>\n${googleOnly ? \"\" : `\\n <div class=\"divider\" id=\"auth-divider\">or</div>\\n`}\n`\n : \"\"\n}\n${\n googleOnly\n ? \"\"\n : ` <div class=\"tabs\">\n <button class=\"tab\" data-tab=\"signup\">Create account</button>\n <button class=\"tab\" data-tab=\"login\">Sign in</button>\n </div>\n\n <form id=\"signup-form\" class=\"form\">\n <label for=\"s-email\">Email</label>\n <input id=\"s-email\" type=\"email\" autocomplete=\"email\" autofocus placeholder=\"you@example.com\" required />\n <label for=\"s-pass\">Password</label>\n <input id=\"s-pass\" type=\"password\" autocomplete=\"new-password\" placeholder=\"At least 8 characters\" required minlength=\"8\" />\n <label for=\"s-pass2\">Confirm password</label>\n <input id=\"s-pass2\" type=\"password\" autocomplete=\"new-password\" placeholder=\"Confirm password\" required minlength=\"8\" />\n <button type=\"submit\">Create account</button>\n <p class=\"msg\" id=\"s-msg\"></p>\n </form>\n\n <div id=\"verification-step\" class=\"form verification-step\" aria-live=\"polite\">\n <div class=\"step-progress\" aria-label=\"Signup progress\">\n <div class=\"progress-step complete\"><span>1</span><strong>Account</strong></div>\n <div class=\"progress-step current\"><span>2</span><strong>Verify</strong></div>\n <div class=\"progress-step\"><span>3</span><strong>Start</strong></div>\n </div>\n <div class=\"verification-panel\">\n <p class=\"verification-kicker\">Verification email sent</p>\n <p class=\"verification-copy\">We sent a secure link to <strong id=\"verify-email\"></strong>. Click it, return here, and this app will finish signing you in automatically.</p>\n <p class=\"verification-note\">You can keep this tab open. If it has not refreshed after you come back, use Continue.</p>\n </div>\n <button type=\"button\" class=\"btn-primary\" id=\"verify-continue\">Continue</button>\n <div class=\"inline-actions\">\n <button type=\"button\" class=\"link-button\" id=\"resend-verification\">Resend email</button>\n <button type=\"button\" class=\"link-button\" id=\"back-to-signup\">Back</button>\n </div>\n <p class=\"msg\" id=\"verify-msg\"></p>\n </div>\n\n <form id=\"login-form\" class=\"form\">\n <label for=\"l-email\">Email</label>\n <input id=\"l-email\" type=\"email\" autocomplete=\"email\" placeholder=\"you@example.com\" required />\n <label for=\"l-pass\">Password</label>\n <input id=\"l-pass\" type=\"password\" autocomplete=\"current-password\" placeholder=\"Enter password\" required />\n <button type=\"submit\">Sign in</button>\n <p class=\"msg error\" id=\"l-msg\"></p>\n <p style=\"margin-top:0.75rem;font-size:0.75rem;text-align:right\">\n <a href=\"#\" id=\"forgot-link\" style=\"color:#888;text-decoration:underline;text-underline-offset:2px\">Forgot password?</a>\n </p>\n </form>\n\n <form id=\"forgot-form\" class=\"form\">\n <label for=\"f-email\">Email</label>\n <input id=\"f-email\" type=\"email\" autocomplete=\"email\" placeholder=\"you@example.com\" required />\n <button type=\"submit\">Send reset link</button>\n <p class=\"msg\" id=\"f-msg\"></p>\n <p style=\"margin-top:0.75rem;font-size:0.75rem;text-align:center\">\n <a href=\"#\" id=\"back-to-login\" style=\"color:#888;text-decoration:underline;text-underline-offset:2px\">Back to sign in</a>\n </p>\n </form>`\n}\n</div>\n<p class=\"local-note\" id=\"local-note\">\n Your account is stored in this app's own DB (<strong>${getConnectionLabel()}</strong>), not a third-party service.\n</p>${marketingCloseHtml}\n<script>\n function __anBasePath() {\n var configured = ${JSON.stringify(appBasePath)};\n if (configured) return configured;\n var marker = '/_agent-native';\n var idx = window.location.pathname.indexOf(marker);\n return idx > 0 ? window.location.pathname.slice(0, idx) : '';\n }\n function __anPath(path) {\n return __anBasePath() + path;\n }\n var __AN_PUBLIC_OAUTH_ORIGIN = ${JSON.stringify(publicOAuthOrigin)};\n var __AN_WORKSPACE_GATEWAY_RETURN_ORIGIN = ${JSON.stringify(workspaceGatewayReturnOrigin)};\n var __AN_GOOGLE_AUTH_MODE = ${JSON.stringify(googleAuthMode)};\n function __anConfiguredOAuthOrigin() {\n if (!__AN_PUBLIC_OAUTH_ORIGIN) return '';\n try {\n var origin = new URL(__AN_PUBLIC_OAUTH_ORIGIN).origin;\n return origin && origin !== window.location.origin ? origin : '';\n } catch(e) {\n return '';\n }\n }\n function __anAuthPath(path) {\n var origin = __anIsBuilderPreview() ? __anConfiguredOAuthOrigin() : '';\n return origin ? origin + path : __anPath(path);\n }\n function __anGoogleAuthUrlPath() {\n return __anIsBuilderPreview()\n ? __anAuthPath('/_agent-native/google/auth-url')\n : __anPath('/_agent-native/google/auth-url');\n }\n function __anBuilderPreviewReturnOrigin() {\n var candidates = [window.location.href, document.referrer || ''];\n try {\n if (window.location.ancestorOrigins) {\n for (var j = 0; j < window.location.ancestorOrigins.length; j++) {\n candidates.push(window.location.ancestorOrigins[j]);\n }\n }\n } catch(e) {}\n for (var i = 0; i < candidates.length; i++) {\n try {\n var url = new URL(candidates[i]);\n var host = url.hostname.toLowerCase();\n var isPreviewHost =\n host === 'builderio.xyz' || host.slice(-14) === '.builderio.xyz' ||\n host === 'builderio.dev' || host.slice(-14) === '.builderio.dev' ||\n host === 'builder.codes' || host.slice(-14) === '.builder.codes' ||\n host === 'builder.my' || host.slice(-11) === '.builder.my';\n if (url.protocol === 'https:' && isPreviewHost) return url.origin;\n } catch(e) {}\n }\n return '';\n }\n function __anWorkspaceGatewayReturnOrigin() {\n var previewOrigin = __anBuilderPreviewReturnOrigin();\n if (previewOrigin) return previewOrigin;\n if (__AN_WORKSPACE_GATEWAY_RETURN_ORIGIN) return __AN_WORKSPACE_GATEWAY_RETURN_ORIGIN;\n return __anIsBuilderDesktop() ? 'http://127.0.0.1:8080' : '';\n }\n function __anNormalizeWorkspaceReturnPath(ret) {\n try {\n var url = new URL(ret || '/', window.location.origin);\n var path = url.pathname || '/';\n if (path === '/dispatch/dispatch') {\n path = '/dispatch';\n } else if (path.indexOf('/dispatch/') === 0) {\n var rest = path.slice('/dispatch/'.length);\n var first = rest.split('/')[0];\n var dispatchRoutes = {\n overview: true, apps: true, metrics: true, vault: true,\n integrations: true, messaging: true, workspace: true,\n agents: true, destinations: true, identities: true,\n approvals: true, audit: true, team: true, 'thread-debug': true,\n 'new-app': true\n };\n if (first === 'dispatch') {\n path = '/dispatch' + rest.slice(first.length);\n } else if (first && !dispatchRoutes[first]) {\n path = '/' + rest;\n }\n }\n return path + url.search + url.hash;\n } catch(e) {\n return ret || '/';\n }\n }\n function __anOAuthReturnTarget(ret) {\n var path = __anNormalizeWorkspaceReturnPath(ret);\n var origin = __anWorkspaceGatewayReturnOrigin();\n return origin ? origin + path : path;\n }\n function __anSessionBridgeUrl(ret, sessionToken) {\n try {\n var url = new URL(ret || window.location.pathname + window.location.search, window.location.origin);\n url.searchParams.set('_session', sessionToken);\n return url.pathname + url.search + url.hash;\n } catch(e) {\n var sep = (ret || '/').indexOf('?') === -1 ? '?' : '&';\n return (ret || '/') + sep + '_session=' + encodeURIComponent(sessionToken);\n }\n }\n function __anFinishOAuthExchange(ret, flowId, sessionToken) {\n if (__anIsBuilderPreview()) {\n if (sessionToken) {\n __anSetOAuthDebug('OAuth exchange redeemed; applying session bridge to embedded app', flowId);\n window.location.replace(__anSessionBridgeUrl(ret, sessionToken));\n return;\n }\n __anSetOAuthDebug('OAuth exchange redeemed; reloading the embedded app', flowId);\n window.location.reload();\n return;\n }\n __anSetOAuthDebug('OAuth exchange redeemed; returning to the app', flowId);\n __anRedirectToSignedInApp(ret);\n }\n function __anGetReturnPath() {\n try {\n var inner = new URLSearchParams(window.location.search).get('return');\n if (inner) return inner;\n } catch(e) {}\n return window.location.pathname + window.location.search;\n }\n function __anMountedPathname(pathname) {\n var base = __anBasePath();\n if (base && pathname.indexOf(base + '/') === 0) return pathname.slice(base.length);\n if (base && pathname === base) return '/';\n return pathname || '/';\n }\n function __anIsAuthEntryPath(pathname) {\n var p = __anMountedPathname(pathname);\n return p === '/login' || p === '/signup' || p === '/_agent-native/sign-in';\n }\n function __anGetSignedInReturnPath() {\n try {\n var inner = new URLSearchParams(window.location.search).get('return');\n if (inner) return inner;\n } catch(e) {}\n if (__anIsAuthEntryPath(window.location.pathname)) return __anPath('/');\n return window.location.pathname + window.location.search + window.location.hash;\n }\n function __anWithAuthCacheBypass(ret) {\n try {\n var url = new URL(ret || __anPath('/'), window.location.origin);\n url.searchParams.set('${AUTH_REDIRECT_QUERY_PARAM}', Date.now().toString(36));\n return url.pathname + url.search + url.hash;\n } catch(e) {\n var fallback = ret || __anPath('/');\n var hashIndex = fallback.indexOf('#');\n var beforeHash = hashIndex === -1 ? fallback : fallback.slice(0, hashIndex);\n var hash = hashIndex === -1 ? '' : fallback.slice(hashIndex);\n var sep = beforeHash.indexOf('?') === -1 ? '?' : '&';\n return beforeHash + sep + '${AUTH_REDIRECT_QUERY_PARAM}=' + Date.now().toString(36) + hash;\n }\n }\n function __anRedirectToSignedInApp(ret) {\n window.location.replace(__anWithAuthCacheBypass(ret || __anGetSignedInReturnPath()));\n }\n (function __anRedirectIfAlreadySignedIn() {\n fetch(__anPath('/_agent-native/auth/session'), {\n headers: { 'Accept': 'application/json' },\n credentials: 'include',\n cache: 'no-store',\n }).then(function(res) {\n if (!res.ok) return null;\n return res.json().catch(function() { return null; });\n }).then(function(data) {\n if (data && data.email && !data.error) __anRedirectToSignedInApp();\n }).catch(function() {});\n })();\n var __anBuilderPreviewSeen = false;\n function __anRememberBuilderPreview() {\n __anBuilderPreviewSeen = true;\n try { sessionStorage.setItem('__an_builder_preview_seen', '1'); } catch(e) {}\n }\n function __anHasBuilderPreviewSignal() {\n try {\n var params = new URLSearchParams(window.location.search);\n if (params.has('builder.preview') || params.has('builder.frameEditing') || params.has('__builder_editing__')) return true;\n } catch(e) {}\n return false;\n }\n function __anIsBuilderPreview() {\n if (__anBuilderPreviewSeen) return true;\n if (__anHasBuilderPreviewSignal()) {\n __anRememberBuilderPreview();\n return true;\n }\n try {\n if (sessionStorage.getItem('__an_builder_preview_seen') === '1') {\n __anBuilderPreviewSeen = true;\n return true;\n }\n } catch(e) {}\n try {\n var ref = document.referrer || '';\n var fromBuilder = ref.indexOf('builder.io') !== -1 || ref.indexOf('builder.my') !== -1 || ref.indexOf('builderio.xyz') !== -1 || ref.indexOf('builderio.dev') !== -1 || ref.indexOf('builder.codes') !== -1;\n if (fromBuilder) __anRememberBuilderPreview();\n return fromBuilder;\n } catch(e) {\n return false;\n }\n }\n __anIsBuilderPreview();\n function __anIsBuilderDesktop() {\n try {\n var ua = navigator.userAgent || '';\n return ua.indexOf('Electron') !== -1 && ua.indexOf('AgentNativeDesktop') === -1;\n } catch(e) {\n return false;\n }\n }\n function __anIsAgentNativeDesktop() {\n try {\n return (navigator.userAgent || '').indexOf('AgentNativeDesktop') !== -1;\n } catch(e) {\n return false;\n }\n }\n function __anIsInFrame() {\n try {\n return window.self !== window.top;\n } catch(e) {\n return true;\n }\n }\n function __anIsElectron() {\n try {\n return (navigator.userAgent || '').indexOf('Electron') !== -1;\n } catch(e) {\n return false;\n }\n }\n function __anResolveAuthFlow() {\n if (__anIsBuilderPreview()) return __anIsInFrame() ? 'popup' : 'redirect';\n // Per-session override for ad-hoc testing outside Builder: append\n // ?authMode=popup or ?authMode=redirect to the sign-in URL.\n try {\n var qp = new URLSearchParams(window.location.search).get('authMode');\n if (qp === 'popup' || qp === 'redirect') return qp;\n } catch(e) {}\n var mode = __AN_GOOGLE_AUTH_MODE || 'auto';\n if (mode === 'popup') return 'popup';\n if (mode === 'redirect') return 'redirect';\n return __anIsAgentNativeDesktop() ? 'redirect' : 'popup';\n }\n var __anOAuthPollTimer = null;\n var __anOAuthPollCount = 0;\n function __anNewOAuthFlowId() {\n try {\n if (window.crypto && typeof window.crypto.randomUUID === 'function') {\n return window.crypto.randomUUID();\n }\n } catch(e) {}\n return 'builder-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2);\n }\n function __anFlowDebugId(flowId) {\n return flowId ? String(flowId).slice(-10) : '';\n }\n function __anSetOAuthDebug(message, flowId) {\n var text = message + (flowId ? ' (flow ' + __anFlowDebugId(flowId) + ')' : '');\n try {\n console.info('[agent-native][google-oauth] ' + text);\n } catch(e) {}\n // Only surface the debug overlay when explicitly opted in via #oauth-debug\n // hash or ?oauth_debug=1 query — otherwise it leaks raw flow IDs and\n // diagnostic strings into the user-facing sign-in screen.\n var showDebugOverlay = false;\n try {\n var loc = window.location || {};\n showDebugOverlay =\n (typeof loc.hash === 'string' && loc.hash.indexOf('oauth-debug') !== -1) ||\n (typeof loc.search === 'string' && loc.search.indexOf('oauth_debug=1') !== -1);\n } catch(e) {}\n var debug = document.getElementById('google-debug');\n if (debug) {\n debug.textContent = text;\n if (showDebugOverlay) debug.classList.add('show');\n }\n }\n function __anShowOAuthError(err, btn, message) {\n if (__anOAuthPollTimer) {\n clearInterval(__anOAuthPollTimer);\n __anOAuthPollTimer = null;\n }\n err.textContent = message;\n err.classList.add('show');\n btn.disabled = false;\n }\n function __anHandlePopupOAuthFailure(ret, btn, err, flowId, redirectReason, builderFrameMessage) {\n if (__anIsBuilderPreview() && __anIsInFrame()) {\n __anShowOAuthError(err, btn, builderFrameMessage + ' Allow popups for this site and try again (flow ' + __anFlowDebugId(flowId) + ').');\n return;\n }\n __anStartRedirectOAuth(ret, btn, err, flowId, redirectReason);\n }\n function __anStartRedirectOAuth(ret, btn, err, flowId, reason) {\n var params = new URLSearchParams();\n var oauthReturn = __anIsBuilderPreview() ? __anOAuthReturnTarget(ret) : ret;\n if (oauthReturn) params.set('return', oauthReturn);\n params.set('redirect', '1');\n __anSetOAuthDebug(reason || 'Opening Google sign-in redirect', flowId);\n try {\n __anOpenOAuthUrl(__anGoogleAuthUrlPath() + '?' + params.toString());\n } catch(e) {\n __anShowOAuthError(err, btn, 'Could not start Google sign-in redirect' + (flowId ? ' for flow ' + __anFlowDebugId(flowId) : '') + ': ' + (e && e.message ? e.message : 'unknown error'));\n }\n }\n function __anWaitForOAuthExchange(flowId, ret, btn, err) {\n var started = Date.now();\n var timeoutMs = 5 * 60 * 1000;\n __anOAuthPollCount = 0;\n async function check() {\n __anOAuthPollCount++;\n try {\n var res = await fetch(__anPath('/_agent-native/auth/desktop-exchange') + '?flow_id=' + encodeURIComponent(flowId), { credentials: 'include' });\n var data = await res.json().catch(function() { return {}; });\n if (data && (data.email || data.token)) {\n if (__anOAuthPollTimer) clearInterval(__anOAuthPollTimer);\n __anOAuthPollTimer = null;\n __anFinishOAuthExchange(ret, flowId, data.token);\n return;\n }\n if (data && data.error) {\n __anSetOAuthDebug('OAuth exchange returned an error: ' + (data.message || data.error), flowId);\n __anShowOAuthError(err, btn, data.message || data.error);\n return;\n }\n if (data && data.pending && (__anOAuthPollCount === 1 || __anOAuthPollCount % 5 === 0)) {\n __anSetOAuthDebug('Waiting for the Google callback; polling attempt ' + __anOAuthPollCount, flowId);\n }\n } catch(e) {\n if (__anOAuthPollCount === 1 || __anOAuthPollCount % 5 === 0) {\n __anSetOAuthDebug('Could not reach the OAuth exchange endpoint: ' + (e && e.message ? e.message : 'network error'), flowId);\n }\n }\n if (Date.now() - started > timeoutMs) {\n __anShowOAuthError(err, btn, 'Google sign-in did not finish. Flow ' + __anFlowDebugId(flowId) + ' never reached this app. Check the Google OAuth redirect URI and server logs for [agent-native][google-oauth].');\n }\n }\n if (__anOAuthPollTimer) clearInterval(__anOAuthPollTimer);\n __anOAuthPollTimer = setInterval(check, 1000);\n setTimeout(check, 500);\n }\n function __anStartPopupOAuth(ret, btn, err) {\n var flowId = __anNewOAuthFlowId();\n var oauthReturn = __anIsBuilderPreview() ? __anOAuthReturnTarget(ret) : ret;\n var params = new URLSearchParams();\n if (oauthReturn) params.set('return', oauthReturn);\n params.set('desktop', '1');\n params.set('flow_id', flowId);\n params.set('redirect', '1');\n var url = __anGoogleAuthUrlPath() + '?' + params.toString();\n try { sessionStorage.setItem('__an_signin', '1'); } catch(e) {}\n __anSetOAuthDebug('Opening Google sign-in popup', flowId);\n try {\n var popup = window.open('', '_blank', 'width=640,height=760');\n if (!popup) {\n __anHandlePopupOAuthFailure(ret, btn, err, flowId, 'Google popup was blocked; falling back to redirect', 'Google popup was blocked.');\n return;\n }\n try { popup.opener = null; } catch(e) {}\n try {\n popup.location.href = url;\n } catch(e) {\n try { popup.close(); } catch(closeErr) {}\n __anHandlePopupOAuthFailure(ret, btn, err, flowId, 'Could not navigate Google popup; falling back to redirect', 'Could not navigate Google popup.');\n return;\n }\n __anSetOAuthDebug('Google popup opened; waiting for callback', flowId);\n } catch(e) {\n __anHandlePopupOAuthFailure(ret, btn, err, flowId, 'Could not open Google popup; falling back to redirect', 'Could not open Google popup.');\n return;\n }\n __anWaitForOAuthExchange(flowId, ret, btn, err);\n }\n function __anStartNativeDesktopOAuth(ret, btn, err) {\n var flowId = __anNewOAuthFlowId();\n var params = new URLSearchParams();\n if (ret) params.set('return', ret);\n params.set('desktop', '1');\n params.set('flow_id', flowId);\n params.set('redirect', '1');\n var url = __anGoogleAuthUrlPath() + '?' + params.toString();\n __anSetOAuthDebug('Opening Google sign-in in system browser', flowId);\n __anOpenOAuthUrl(url);\n __anWaitForOAuthExchange(flowId, ret, btn, err);\n }\n function __anOpenOAuthUrl(url) {\n try { sessionStorage.setItem('__an_signin', '1'); } catch(e) {}\n window.location.href = url;\n }\n (function revealLocalNote() {\n var h = location.hostname;\n if (h === 'localhost' || h === '127.0.0.1' || h === '::1' || h.endsWith('.local')) {\n var n = document.getElementById('local-note');\n if (n) n.classList.add('show');\n }\n })();\n (function revealUpgradeNote() {\n var shouldShow = false;\n try {\n var params = new URLSearchParams(location.search);\n shouldShow = params.get('signin') === '1' || params.get('upgrade-from-local') === '1';\n } catch(e) {}\n if (!shouldShow) {\n try { shouldShow = localStorage.getItem('an_migrate_from_local') === '1'; } catch(e) {}\n }\n if (!shouldShow) return;\n var n = document.getElementById('upgrade-note');\n if (!n) return;\n n.textContent = n.getAttribute('data-upgrade-copy') || 'Continue signing in to migrate local data.';\n n.classList.add('show');\n })();\n${\n googleOnly\n ? \"\"\n : ` var TAB_STORAGE_KEY = 'an.onboarding.tab';\n var tabs = document.querySelectorAll('.tab');\n var forms = document.querySelectorAll('.form');\n var subtitles = { signup: 'Create an account to get started', login: 'Sign in to your account' };\n var headings = { signup: 'Welcome', login: 'Welcome back' };\n var pendingSignupEmail = '';\n var pendingSignupPassword = '';\n var verificationCheckInFlight = false;\n function setActiveTab(name, opts) {\n if (name !== 'signup' && name !== 'login') return;\n var form = document.getElementById(name + '-form');\n if (!form) return;\n var card = document.querySelector('.card');\n if (card) card.classList.remove('verifying');\n tabs.forEach(function(x) { x.classList.remove('active'); });\n forms.forEach(function(x) { x.classList.remove('active'); });\n var btn = document.querySelector('.tab[data-tab=\"' + name + '\"]');\n if (btn) btn.classList.add('active');\n form.classList.add('active');\n var sub = document.getElementById('subtitle');\n if (sub && subtitles[name]) sub.textContent = subtitles[name];\n var heading = document.getElementById('heading');\n if (heading && headings[name]) heading.textContent = headings[name];\n if (opts && opts.persist) {\n try { localStorage.setItem(TAB_STORAGE_KEY, name); } catch (e) {}\n }\n }\n function showVerificationStep(email, password) {\n pendingSignupEmail = email || '';\n pendingSignupPassword = password || '';\n tabs.forEach(function(x) { x.classList.remove('active'); });\n forms.forEach(function(x) { x.classList.remove('active'); });\n var card = document.querySelector('.card');\n if (card) card.classList.add('verifying');\n var step = document.getElementById('verification-step');\n if (step) step.classList.add('active');\n var emailNode = document.getElementById('verify-email');\n if (emailNode) emailNode.textContent = pendingSignupEmail;\n var heading = document.getElementById('heading');\n if (heading) heading.textContent = 'Check your email';\n var sub = document.getElementById('subtitle');\n if (sub) sub.textContent = 'Finish creating your account';\n var msg = document.getElementById('verify-msg');\n if (msg) {\n msg.classList.remove('show', 'error', 'success');\n msg.textContent = '';\n }\n try { localStorage.setItem(TAB_STORAGE_KEY, 'signup'); } catch (e) {}\n }\n function getVerificationMessageNode() {\n var verifyStep = document.getElementById('verification-step');\n if (verifyStep && verifyStep.classList.contains('active')) {\n return document.getElementById('verify-msg');\n }\n return document.getElementById('l-msg') || document.getElementById('verify-msg');\n }\n function isVerificationStepActive() {\n var verifyStep = document.getElementById('verification-step');\n return !!(verifyStep && verifyStep.classList.contains('active'));\n }\n function getPendingSignupEmail() {\n var signupEmail = document.getElementById('s-email');\n var loginEmail = document.getElementById('l-email');\n return (pendingSignupEmail || (signupEmail && signupEmail.value) || (loginEmail && loginEmail.value) || '').trim();\n }\n function getPendingSignupPassword() {\n var signupPassword = document.getElementById('s-pass');\n return pendingSignupPassword || (signupPassword && signupPassword.value) || '';\n }\n function movePendingSignupToLogin(message) {\n var email = getPendingSignupEmail();\n setActiveTab('login', { persist: true });\n var loginEmail = document.getElementById('l-email');\n var loginPassword = document.getElementById('l-pass');\n var msg = document.getElementById('l-msg');\n if (loginEmail && email) loginEmail.value = email;\n if (msg) {\n msg.textContent = message || 'Sign in to continue.';\n msg.classList.remove('error');\n msg.classList.add('show', 'success');\n }\n setTimeout(function() { if (loginPassword) loginPassword.focus(); }, 0);\n }\n async function signInWithPendingSignup() {\n var email = getPendingSignupEmail();\n var password = getPendingSignupPassword();\n if (!email || !password) {\n return { ok: false, needsManualSignIn: true };\n }\n var res = await fetch(__anPath('/_agent-native/auth/login'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email: email, password: password }),\n });\n if (res.ok) {\n __anRedirectToSignedInApp();\n return { ok: true };\n }\n var data = await res.json().catch(function() { return {}; });\n var error = (data && (data.error || data.message)) || 'Could not finish sign-in automatically.';\n return {\n ok: false,\n error: error,\n isWaitingForVerification: /not verified|verification/i.test(error),\n };\n }\n async function checkVerificationSession(fallbackText, opts) {\n opts = opts || {};\n if (verificationCheckInFlight) return;\n verificationCheckInFlight = true;\n var msg = getVerificationMessageNode();\n var continueBtn = document.getElementById('verify-continue');\n if (continueBtn && !opts.silent) {\n continueBtn.disabled = true;\n continueBtn.textContent = 'Checking...';\n }\n if (msg && !opts.silent) {\n msg.textContent = 'Checking your verification...';\n msg.classList.remove('error');\n msg.classList.add('show', 'success');\n }\n try {\n var res = await fetch(__anPath('/_agent-native/auth/session'), {\n headers: { 'Accept': 'application/json' },\n });\n var data = await res.json().catch(function() { return {}; });\n if (res.ok && data && data.email && !data.error) {\n __anRedirectToSignedInApp();\n return;\n }\n var loginResult = await signInWithPendingSignup();\n if (loginResult.ok) return;\n if (loginResult.needsManualSignIn) {\n if (!opts.silent) {\n movePendingSignupToLogin(fallbackText || 'Enter your password after verifying your email.');\n }\n return;\n }\n if (loginResult.error && !loginResult.isWaitingForVerification) {\n if (!opts.silent) {\n movePendingSignupToLogin('We could not finish sign-in automatically. Sign in to continue.');\n }\n return;\n }\n if (msg && !opts.silent) {\n msg.textContent = fallbackText || 'Still waiting on verification. Click the link in your email, then try Continue again.';\n msg.classList.remove('success');\n msg.classList.add('show', 'error');\n }\n } catch (err) {\n if (msg && !opts.silent) {\n msg.textContent = 'Could not check verification. Please try again.';\n msg.classList.remove('success');\n msg.classList.add('show', 'error');\n }\n } finally {\n verificationCheckInFlight = false;\n if (continueBtn && !opts.silent) {\n continueBtn.disabled = false;\n continueBtn.textContent = 'Continue';\n }\n }\n }\n function maybeCompleteVerificationAfterReturn() {\n if (!isVerificationStepActive()) return;\n checkVerificationSession(null, { silent: true });\n }\n async function resendVerificationEmail() {\n var btn = document.getElementById('resend-verification');\n var msg = document.getElementById('verify-msg');\n var email = pendingSignupEmail || document.getElementById('s-email').value;\n if (!email) return;\n var original = btn ? btn.textContent : '';\n if (btn) {\n btn.disabled = true;\n btn.textContent = 'Sending...';\n }\n if (msg) msg.classList.remove('show', 'error', 'success');\n try {\n var res = await fetch(__anPath('/_agent-native/auth/ba/send-verification-email'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email: email, callbackURL: __anGetReturnPath() }),\n });\n if (res.ok) {\n if (msg) {\n msg.textContent = 'Sent a fresh verification link.';\n msg.classList.add('show', 'success');\n }\n if (btn) btn.textContent = 'Sent';\n setTimeout(function() {\n if (btn) {\n btn.disabled = false;\n btn.textContent = original;\n }\n }, 1600);\n return;\n }\n var data = await res.json().catch(function() { return {}; });\n if (msg) {\n msg.textContent = (data && (data.message || data.error)) || 'Could not resend the verification email.';\n msg.classList.add('show', 'error');\n }\n if (btn) {\n btn.disabled = false;\n btn.textContent = original;\n }\n } catch (err) {\n if (msg) {\n msg.textContent = 'Network error. Please try again.';\n msg.classList.add('show', 'error');\n }\n if (btn) {\n btn.disabled = false;\n btn.textContent = original;\n }\n }\n }\n (function initActiveTab() {\n var initial = 'signup';\n try {\n var params = new URLSearchParams(location.search);\n var qp = params.get('tab');\n var path = location.pathname;\n while (path.length > 1 && path.charAt(path.length - 1) === '/') path = path.slice(0, -1);\n if (qp === 'login' || qp === 'signup') {\n initial = qp;\n } else if (params.has('verified')) {\n initial = 'login';\n } else if (path === '/login' || path.endsWith('/login')) {\n initial = 'login';\n } else if (path === '/signup' || path.endsWith('/signup')) {\n initial = 'signup';\n } else {\n var stored = localStorage.getItem(TAB_STORAGE_KEY);\n if (stored === 'login' || stored === 'signup') initial = stored;\n }\n } catch (e) {}\n setActiveTab(initial, { persist: false });\n try {\n if (new URLSearchParams(location.search).has('verified')) {\n var msg = document.getElementById('l-msg');\n if (msg) {\n msg.textContent = 'Email verified. Finishing sign-in...';\n msg.classList.remove('error');\n msg.classList.add('show', 'success');\n }\n checkVerificationSession('Email verified. Sign in to continue.');\n }\n } catch (e) {}\n })();\n tabs.forEach(function(t) { t.addEventListener('click', function() {\n setActiveTab(t.dataset.tab, { persist: true });\n }); });\n\n document.getElementById('signup-form').addEventListener('submit', async function(e) {\n e.preventDefault();\n var form = e.currentTarget;\n var btn = form.querySelector('button[type=\"submit\"]');\n var msg = document.getElementById('s-msg');\n msg.classList.remove('show', 'error', 'success');\n var pass = document.getElementById('s-pass').value;\n var pass2 = document.getElementById('s-pass2').value;\n if (pass !== pass2) {\n msg.textContent = 'Passwords do not match';\n msg.classList.add('show', 'error');\n return;\n }\n var originalLabel = btn.textContent;\n btn.disabled = true;\n btn.textContent = 'Creating account…';\n try {\n var email = document.getElementById('s-email').value;\n var res = await fetch(__anPath('/_agent-native/auth/register'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n email: email,\n password: pass,\n callbackURL: __anGetReturnPath(),\n }),\n });\n var data = await res.json().catch(function() { return {}; });\n if (res.ok) {\n // If email verification is required, the server won't return a session.\n // Try logging in — if it fails (unverified), show a \"check your email\" message.\n var loginRes = await fetch(__anPath('/_agent-native/auth/login'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email: email, password: pass }),\n });\n if (loginRes.ok) {\n msg.textContent = 'Account created — signing you in…';\n msg.classList.add('show', 'success');\n __anRedirectToSignedInApp();\n return;\n }\n btn.disabled = false;\n btn.textContent = originalLabel;\n showVerificationStep(email, pass);\n return;\n }\n msg.textContent = data.error || 'Registration failed';\n msg.classList.add('show', 'error');\n btn.disabled = false;\n btn.textContent = originalLabel;\n } catch (err) {\n msg.textContent = 'Network error — please try again';\n msg.classList.add('show', 'error');\n btn.disabled = false;\n btn.textContent = originalLabel;\n }\n });\n\n var verifyContinue = document.getElementById('verify-continue');\n if (verifyContinue) verifyContinue.addEventListener('click', function(e) {\n e.preventDefault();\n checkVerificationSession();\n });\n window.addEventListener('focus', maybeCompleteVerificationAfterReturn);\n document.addEventListener('visibilitychange', function() {\n if (document.visibilityState === 'visible') maybeCompleteVerificationAfterReturn();\n });\n var resendBtn = document.getElementById('resend-verification');\n if (resendBtn) resendBtn.addEventListener('click', function(e) {\n e.preventDefault();\n resendVerificationEmail();\n });\n var backToSignup = document.getElementById('back-to-signup');\n if (backToSignup) backToSignup.addEventListener('click', function(e) {\n e.preventDefault();\n setActiveTab('signup', { persist: true });\n var email = document.getElementById('s-email');\n setTimeout(function() { if (email) email.focus(); }, 0);\n });\n\n var forgotLink = document.getElementById('forgot-link');\n var backToLogin = document.getElementById('back-to-login');\n if (forgotLink) forgotLink.addEventListener('click', function(e) {\n e.preventDefault();\n document.getElementById('login-form').classList.remove('active');\n document.getElementById('forgot-form').classList.add('active');\n var sub = document.getElementById('subtitle');\n if (sub) sub.textContent = 'Reset your password';\n var heading = document.getElementById('heading');\n if (heading) heading.textContent = 'Reset password';\n var fEmail = document.getElementById('f-email');\n var lEmail = document.getElementById('l-email');\n if (lEmail && lEmail.value) fEmail.value = lEmail.value;\n setTimeout(function() { fEmail.focus(); }, 0);\n });\n if (backToLogin) backToLogin.addEventListener('click', function(e) {\n e.preventDefault();\n document.getElementById('forgot-form').classList.remove('active');\n document.getElementById('login-form').classList.add('active');\n var sub = document.getElementById('subtitle');\n if (sub) sub.textContent = subtitles.login;\n var heading = document.getElementById('heading');\n if (heading) heading.textContent = headings.login;\n });\n\n var forgotForm = document.getElementById('forgot-form');\n if (forgotForm) forgotForm.addEventListener('submit', async function(e) {\n e.preventDefault();\n var btn = e.currentTarget.querySelector('button[type=\"submit\"]');\n var msg = document.getElementById('f-msg');\n msg.classList.remove('show', 'error', 'success');\n var original = btn.textContent;\n btn.disabled = true;\n btn.textContent = 'Sending…';\n try {\n var email = document.getElementById('f-email').value;\n var res = await fetch(__anPath('/_agent-native/auth/ba/request-password-reset'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email: email }),\n });\n if (res.ok) {\n msg.textContent = 'If that email exists, a reset link is on its way.';\n msg.classList.add('show', 'success');\n btn.textContent = 'Sent';\n return;\n }\n var data = await res.json().catch(function() { return {}; });\n msg.textContent = (data && (data.message || data.error)) || 'Could not send reset email.';\n msg.classList.add('show', 'error');\n btn.disabled = false;\n btn.textContent = original;\n } catch (err) {\n msg.textContent = 'Network error — please try again';\n msg.classList.add('show', 'error');\n btn.disabled = false;\n btn.textContent = original;\n }\n });\n\n document.getElementById('login-form').addEventListener('submit', async function(e) {\n e.preventDefault();\n var form = e.currentTarget;\n var btn = form.querySelector('button[type=\"submit\"]');\n var msg = document.getElementById('l-msg');\n msg.classList.remove('show', 'success');\n msg.classList.add('error');\n var originalLabel = btn.textContent;\n btn.disabled = true;\n btn.textContent = 'Signing in…';\n try {\n var res = await fetch(__anPath('/_agent-native/auth/login'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n email: document.getElementById('l-email').value,\n password: document.getElementById('l-pass').value,\n }),\n });\n if (res.ok) {\n __anRedirectToSignedInApp();\n return;\n }\n var data = await res.json().catch(function() { return {}; });\n msg.textContent = data.error || 'Invalid email or password';\n msg.classList.add('show');\n btn.disabled = false;\n btn.textContent = originalLabel;\n } catch (err) {\n msg.textContent = 'Network error — please try again';\n msg.classList.add('show');\n btn.disabled = false;\n btn.textContent = originalLabel;\n }\n });\n`\n}\n${\n renderGoogleButton\n ? `\n async function signInWithGoogle() {\n if (__anShouldShowGoogleNotice()) {\n __anShowGoogleNotice();\n return;\n }\n return __anStartGoogleSignIn();\n }\n async function __anStartGoogleSignIn() {\n var btn = document.getElementById('google-btn');\n var err = document.getElementById('google-err');\n var ret = __anGetReturnPath();\n btn.disabled = true;\n err.classList.remove('show');\n if (__anResolveAuthFlow() === 'popup') {\n __anStartPopupOAuth(ret, btn, err);\n return;\n }\n if (__anIsAgentNativeDesktop()) {\n __anStartNativeDesktopOAuth(ret, btn, err);\n return;\n }\n if (__anIsBuilderPreview()) {\n var flowId = __anNewOAuthFlowId();\n __anStartRedirectOAuth(ret, btn, err, flowId, 'Opening Google sign-in redirect from Builder preview');\n return;\n }\n try {\n var authUrl = __anGoogleAuthUrlPath() + '?return=' + encodeURIComponent(ret);\n var res = await fetch(authUrl);\n var data = await res.json();\n if (data.url) {\n __anOpenOAuthUrl(data.url);\n } else {\n err.textContent = data.message || 'Google OAuth is not configured.';\n err.classList.add('show');\n btn.disabled = false;\n }\n } catch (e) {\n err.textContent = 'Failed to connect. Please try again.';\n err.classList.add('show');\n btn.disabled = false;\n }\n }`\n : \"\"\n}\n${\n googleSignInNotice\n ? `\n window.__anGoogleNoticeAccepted = false;\n function __anShouldShowGoogleNotice() {\n var notice = document.getElementById('google-preflight');\n if (!notice || window.__anGoogleNoticeAccepted) return false;\n var host = notice.getAttribute('data-host');\n return !host || window.location.hostname === host;\n }\n function __anSetGoogleNoticeOpen(open) {\n var notice = document.getElementById('google-preflight');\n var trigger = document.getElementById('google-btn');\n if (!notice) return;\n if (open) {\n notice.classList.add('show');\n if (trigger) trigger.setAttribute('aria-expanded', 'true');\n } else {\n notice.classList.remove('show');\n if (trigger) trigger.setAttribute('aria-expanded', 'false');\n }\n }\n function __anShowGoogleNotice() {\n var notice = document.getElementById('google-preflight');\n if (!notice) return;\n __anSetGoogleNoticeOpen(true);\n var continueBtn = document.getElementById('google-preflight-continue');\n if (continueBtn) continueBtn.focus();\n }\n function __anHideGoogleNotice() {\n __anSetGoogleNoticeOpen(false);\n }\n function __anChooseRunLocalFromGoogleNotice() {\n var panel = document.getElementById('google-preflight-run-local-panel');\n if (!panel) {\n __anHideGoogleNotice();\n return;\n }\n panel.removeAttribute('hidden');\n var copy = document.getElementById('copy-google-preflight-run-local');\n if (copy) copy.focus();\n }\n function __anAcceptGoogleNotice() {\n window.__anGoogleNoticeAccepted = true;\n __anHideGoogleNotice();\n __anStartGoogleSignIn();\n }\n (function __anInstallGoogleNoticeDismissal() {\n document.addEventListener('keydown', function(event) {\n if (event.key === 'Escape') __anHideGoogleNotice();\n });\n document.addEventListener('click', function(event) {\n var notice = document.getElementById('google-preflight');\n if (!notice || !notice.classList.contains('show')) return;\n var wrapper = document.getElementById('google-signin');\n if (wrapper && wrapper.contains(event.target)) return;\n __anHideGoogleNotice();\n });\n })();`\n : `\n function __anShouldShowGoogleNotice() { return false; }`\n}\n${starfieldScript}\n${\n runLocalCommand\n ? `\n function __anSetRunLocalCommandOpen(open) {\n var panel = document.getElementById('run-local-panel');\n var button = document.getElementById('run-local-button');\n if (!panel || !button) return;\n if (open) {\n panel.removeAttribute('hidden');\n } else {\n panel.setAttribute('hidden', '');\n }\n button.setAttribute('aria-expanded', String(open));\n }\n function __anToggleRunLocalCommand() {\n var panel = document.getElementById('run-local-panel');\n if (!panel) return;\n __anSetRunLocalCommandOpen(panel.hasAttribute('hidden'));\n }\n function __anCopyCommandFromPanel(panelId, buttonId) {\n var panel = document.getElementById(panelId);\n var button = document.getElementById(buttonId);\n if (!panel || !button) return;\n var command = panel.getAttribute('data-command') || '';\n var original = button.textContent || 'Copy command';\n function markCopied() {\n button.textContent = 'Copied';\n setTimeout(function() { button.textContent = original; }, 1600);\n }\n if (navigator.clipboard && navigator.clipboard.writeText) {\n navigator.clipboard.writeText(command).then(markCopied).catch(function() {});\n }\n }\n function __anCopyRunLocalCommand() {\n __anCopyCommandFromPanel('run-local-panel', 'copy-run-local');\n }\n function __anCopyGoogleNoticeRunLocalCommand() {\n __anCopyCommandFromPanel('google-preflight-run-local-panel', 'copy-google-preflight-run-local');\n }`\n : \"\"\n}\n</script>\n</body>\n</html>`;\n}\n\n/** @deprecated Use getOnboardingHtml() instead */\nexport const ONBOARDING_HTML = getOnboardingHtml();\n\n/**\n * HTML for the password reset page — shown when the user clicks the link in\n * their reset email. Posts `{ newPassword, token }` to Better Auth's\n * `/reset-password` endpoint, then redirects to the login page.\n */\nexport function getResetPasswordHtml(): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\">\n<title>Reset password</title>\n<link rel=\"icon\" type=\"image/svg+xml\" href=\"${withAppBasePath(\"/favicon.svg\")}\">\n<link rel=\"apple-touch-icon\" href=\"${withAppBasePath(\"/icon-180.svg\")}\">\n<style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n body { font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; background: #0a0a0a; color: #e5e5e5; display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 1rem; }\n .card { width: 100%; max-width: 400px; padding: 2rem; background: #141414; border: 1px solid rgba(255,255,255,0.08); border-radius: 12px; }\n h1 { font-size: 1.25rem; font-weight: 600; margin-bottom: 0.25rem; color: #fff; }\n .subtitle { font-size: 0.8125rem; color: #888; margin-bottom: 1.5rem; }\n label { display: block; font-size: 0.8125rem; color: #888; margin-bottom: 0.375rem; }\n input { width: 100%; padding: 0.5rem 0.75rem; background: transparent; border: 1px solid rgba(255,255,255,0.12); border-radius: 6px; color: #e5e5e5; font-size: 0.875rem; outline: none; margin-bottom: 0.875rem; }\n input:focus { border-color: rgba(255,255,255,0.3); box-shadow: 0 0 0 1px rgba(255,255,255,0.1); }\n input::placeholder { color: #555; }\n button[type=\"submit\"] { width: 100%; margin-top: 0.25rem; padding: 0.5rem; background: #fff; color: #000; border: none; border-radius: 6px; font-size: 0.875rem; font-weight: 500; cursor: pointer; }\n button[type=\"submit\"]:hover { background: #e5e5e5; }\n button[type=\"submit\"]:disabled { opacity: 0.5; cursor: not-allowed; }\n .msg { margin-top: 0.75rem; font-size: 0.8125rem; display: none; }\n .msg.error { color: #f87171; }\n .msg.success { color: #4ade80; }\n .msg.show { display: block; }\n .back { display: inline-block; margin-top: 1rem; font-size: 0.75rem; color: #888; text-decoration: none; }\n .back:hover { color: #bbb; }\n</style>\n</head>\n<body>\n<div class=\"card\">\n <h1>Choose a new password</h1>\n <p class=\"subtitle\">Set a new password for your account.</p>\n <form id=\"reset-form\">\n <label for=\"p1\">New password</label>\n <input id=\"p1\" type=\"password\" autocomplete=\"new-password\" autofocus placeholder=\"At least 8 characters\" required minlength=\"8\" />\n <label for=\"p2\">Confirm password</label>\n <input id=\"p2\" type=\"password\" autocomplete=\"new-password\" placeholder=\"Confirm password\" required minlength=\"8\" />\n <button type=\"submit\">Save new password</button>\n <p class=\"msg\" id=\"msg\"></p>\n </form>\n <a class=\"back\" id=\"back-link\" href=\"/\">Back to sign in</a>\n</div>\n<script>\n (function() {\n // Derive the app's base path so apps mounted under a prefix\n // (e.g. /mail, /calendar) get sent home instead of to the root domain.\n var RESET_PATH = '/_agent-native/auth/reset';\n var pathname = window.location.pathname;\n var idx = pathname.indexOf(RESET_PATH);\n var basePath = (idx >= 0 ? pathname.slice(0, idx) : '') || '';\n var homeHref = basePath + '/';\n var backLink = document.getElementById('back-link');\n if (backLink) backLink.setAttribute('href', homeHref);\n var params = new URLSearchParams(location.search);\n var token = params.get('token') || '';\n var msg = document.getElementById('msg');\n if (!token) {\n msg.textContent = 'Missing or invalid reset token. Request a new reset link.';\n msg.classList.add('show', 'error');\n document.getElementById('reset-form').style.display = 'none';\n return;\n }\n document.getElementById('reset-form').addEventListener('submit', async function(e) {\n e.preventDefault();\n var btn = e.currentTarget.querySelector('button[type=\"submit\"]');\n var p1 = document.getElementById('p1').value;\n var p2 = document.getElementById('p2').value;\n msg.classList.remove('show', 'error', 'success');\n if (p1 !== p2) {\n msg.textContent = 'Passwords do not match';\n msg.classList.add('show', 'error');\n return;\n }\n var original = btn.textContent;\n btn.disabled = true;\n btn.textContent = 'Saving…';\n try {\n var res = await fetch(basePath + '/_agent-native/auth/ba/reset-password', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ newPassword: p1, token: token }),\n });\n if (res.ok) {\n msg.textContent = 'Password updated — redirecting to sign in…';\n msg.classList.add('show', 'success');\n setTimeout(function() { window.location.href = homeHref; }, 1200);\n return;\n }\n var data = await res.json().catch(function() { return {}; });\n msg.textContent = (data && (data.message || data.error)) || 'Reset failed. The link may have expired — request a new one.';\n msg.classList.add('show', 'error');\n btn.disabled = false;\n btn.textContent = original;\n } catch (err) {\n msg.textContent = 'Network error — please try again';\n msg.classList.add('show', 'error');\n btn.disabled = false;\n btn.textContent = original;\n }\n });\n })();\n</script>\n</body>\n</html>`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"onboarding-html.js","sourceRoot":"","sources":["../../src/server/onboarding-html.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * First-run onboarding page for agent-native apps.\n *\n * Shown when Better Auth is active and the user isn't signed in.\n * Provides a path to create or sign into an account from day one.\n *\n * After first account exists, this page acts as a normal login page.\n */\n\nimport { getPublicOAuthOrigin } from \"./oauth-public-origin.js\";\nimport {\n resolveGoogleAuthMode,\n type GoogleAuthMode,\n} from \"./google-auth-mode.js\";\nimport { getWorkspaceGatewayReturnOrigin } from \"./oauth-return-url.js\";\nimport { identitySsoLoginButtonHtml } from \"./identity-sso-store.js\";\nimport {\n resolveBuiltInAuthMarketing,\n type AuthMarketingContent,\n} from \"./auth-marketing.js\";\nimport { AUTH_REDIRECT_QUERY_PARAM } from \"../shared/auth-redirect-url.js\";\nimport {\n AGENT_NATIVE_SOCIAL_IMAGE_ALT,\n AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT,\n AGENT_NATIVE_SOCIAL_IMAGE_PATH,\n AGENT_NATIVE_SOCIAL_IMAGE_TYPE,\n AGENT_NATIVE_SOCIAL_IMAGE_WIDTH,\n withAgentNativeSocialImageCacheBuster,\n} from \"../shared/social-meta.js\";\nimport { normalizeAppBasePath } from \"./app-base-path.js\";\n\nfunction hasGoogleOAuth(): boolean {\n return !!(process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET);\n}\n\nfunction getConnectionLabel(): string {\n const url = process.env.DATABASE_URL || \"\";\n if (!url) return \"SQLite (local file)\";\n if (url.startsWith(\"postgres://\") || url.startsWith(\"postgresql://\")) {\n if (url.includes(\"neon.tech\")) return \"Neon Postgres\";\n if (url.includes(\"supabase\")) return \"Supabase Postgres\";\n return \"Postgres\";\n }\n if (url.startsWith(\"file:\")) return \"SQLite (local file)\";\n if (url.startsWith(\"libsql://\") || url.includes(\"turso.io\")) return \"Turso\";\n return \"SQL database\";\n}\n\nfunction withAppBasePath(path: string): string {\n const cleanPath = path.startsWith(\"/\") ? path : `/${path}`;\n const basePath = normalizeAppBasePath(\n process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH,\n );\n return `${basePath}${cleanPath}`;\n}\n\nexport interface OnboardingHtmlOptions {\n /**\n * Hide email/password forms and show ONLY the Google sign-in button.\n * Useful for templates (mail, calendar) where Google is required anyway.\n * If Google OAuth env vars are not configured, an error message is shown.\n */\n googleOnly?: boolean;\n /**\n * Product marketing content shown alongside the sign-in form.\n * When provided, the page uses a split layout: marketing on the left,\n * sign-in form on the right (stacked on mobile).\n */\n marketing?: {\n appName: string;\n tagline: string;\n description?: string;\n features?: string[];\n runLocalCommand?: string;\n };\n /**\n * Request context used only to recover branded first-party marketing when a\n * default auth guard serves before a template-specific auth plugin.\n */\n requestHost?: string;\n requestPath?: string;\n requestOrigin?: string;\n /**\n * Optional preflight copy shown before redirecting through Google sign-in.\n * Use this when a hosted app needs to warn about provider-specific consent\n * screens while leaving self-hosted deployments untouched.\n */\n googleSignInNotice?: {\n host?: string;\n title: string;\n body: string | string[];\n continueLabel?: string;\n cancelLabel?: string;\n };\n /**\n * Google sign-in flow: `'popup'`, `'redirect'`, or `'auto'` (default).\n * Falls back to `GOOGLE_AUTH_MODE` env var, then `'auto'`. Builder web\n * iframes use popup; Builder desktop preview/editor surfaces use redirect.\n */\n googleAuthMode?: GoogleAuthMode;\n}\n\nexport function getOnboardingHtml(opts: OnboardingHtmlOptions = {}): string {\n const showGoogle = hasGoogleOAuth();\n const googleOnly = !!opts.googleOnly;\n // In a Google-only app, Google is the sole sign-in method, so always render\n // a working button — never gate it on env vars detected at render time. The\n // login page is a public, CDN-cacheable shell served to everyone (per-user\n // and per-config state is resolved client-side after load), so baking a\n // \"not configured\" message in here would freeze that error into the cache\n // for every visitor. A genuinely misconfigured server instead surfaces a\n // clear error at click time via the auth API.\n const renderGoogleButton = showGoogle || googleOnly;\n const appBasePath = normalizeAppBasePath(\n process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH,\n );\n const publicOAuthOrigin = getPublicOAuthOrigin();\n const workspaceGatewayReturnOrigin = getWorkspaceGatewayReturnOrigin();\n const googleAuthMode = resolveGoogleAuthMode(opts.googleAuthMode);\n\n const marketing: AuthMarketingContent | undefined =\n opts.marketing ??\n resolveBuiltInAuthMarketing({\n requestHost: opts.requestHost,\n requestPath: opts.requestPath,\n });\n const hasMarketing = !!marketing;\n const runLocalCommand = marketing?.runLocalCommand?.trim();\n const brandMarkSrc = withAppBasePath(\"/agent-native-icon-dark.svg\");\n const socialImageUrl = withAgentNativeSocialImageCacheBuster(\n opts.requestOrigin\n ? `${opts.requestOrigin}${withAppBasePath(AGENT_NATIVE_SOCIAL_IMAGE_PATH)}`\n : withAppBasePath(AGENT_NATIVE_SOCIAL_IMAGE_PATH),\n );\n const esc = (s: string) =>\n s\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\n const googleSignInNotice = opts.googleSignInNotice;\n const googleNoticeBodyParts = googleSignInNotice\n ? (Array.isArray(googleSignInNotice.body)\n ? googleSignInNotice.body\n : [googleSignInNotice.body]\n ).filter((body) => body.trim().length > 0)\n : [];\n const googleNoticeBodyHtml = googleNoticeBodyParts\n .map(\n (body, index) =>\n `<p class=\"google-preflight-copy\"${index === 0 ? ' id=\"google-preflight-copy\"' : \"\"}>${esc(body)}</p>`,\n )\n .join(\"\\n\");\n const googleNoticeRunLocalHtml = runLocalCommand\n ? `\n <button type=\"button\" class=\"btn-secondary google-preflight-local\" id=\"google-preflight-run-local\" onclick=\"__anChooseRunLocalFromGoogleNotice()\">${esc(googleSignInNotice?.cancelLabel ?? \"Run locally\")}</button>`\n : `\n <button type=\"button\" class=\"btn-secondary\" onclick=\"__anHideGoogleNotice()\">${esc(googleSignInNotice?.cancelLabel ?? \"Close\")}</button>`;\n const googleNoticeRunLocalPanelHtml = runLocalCommand\n ? `\n <div class=\"google-preflight-command\" id=\"google-preflight-run-local-panel\" hidden data-command=\"${esc(runLocalCommand)}\">\n <p class=\"google-preflight-command-label\">Use your own Google OAuth client:</p>\n <code>${esc(runLocalCommand)}</code>\n <button type=\"button\" class=\"copy-run-local\" id=\"copy-google-preflight-run-local\" onclick=\"__anCopyGoogleNoticeRunLocalCommand()\">Copy command</button>\n </div>`\n : \"\";\n const googleNoticeHtml =\n renderGoogleButton && googleSignInNotice\n ? `\n <div\n class=\"google-preflight\"\n id=\"google-preflight\"\n data-host=\"${esc(googleSignInNotice.host ?? \"\")}\"\n role=\"dialog\"\n aria-labelledby=\"google-preflight-title\"\n aria-describedby=\"google-preflight-copy\"\n tabindex=\"-1\"\n >\n <div class=\"google-preflight-heading\">\n <p class=\"google-preflight-title\" id=\"google-preflight-title\">${esc(googleSignInNotice.title)}</p>\n <button type=\"button\" class=\"google-preflight-close\" aria-label=\"Close Google sign-in choices\" onclick=\"__anHideGoogleNotice()\">×</button>\n </div>\n${googleNoticeBodyHtml}\n <div class=\"google-preflight-actions\">\n <button type=\"button\" class=\"btn-primary\" id=\"google-preflight-continue\" onclick=\"__anAcceptGoogleNotice()\">${esc(googleSignInNotice.continueLabel ?? \"Continue\")}</button>\n${googleNoticeRunLocalHtml}\n </div>\n${googleNoticeRunLocalPanelHtml}\n </div>`\n : \"\";\n const identitySsoHtml = identitySsoLoginButtonHtml();\n const identitySsoScript = identitySsoHtml\n ? `\n function __anIdentitySsoUrl() {\n var params = new URLSearchParams();\n params.set('return', __anGetReturnPath());\n return __anPath('/_agent-native/identity/login') + '?' + params.toString();\n }\n function __anStartIdentitySso(event) {\n if (event && event.preventDefault) event.preventDefault();\n window.location.href = __anIdentitySsoUrl();\n return false;\n }\n (function __anPrepareIdentitySsoButton() {\n var identity = document.getElementById('identity-sso-btn');\n if (!identity) return;\n identity.setAttribute('href', __anIdentitySsoUrl());\n identity.addEventListener('click', __anStartIdentitySso);\n })();`\n : \"\";\n\n const marketingStyles = hasMarketing\n ? `\n body.has-marketing { padding: 0; position: relative; overflow-x: hidden; }\n #starfield {\n position: fixed;\n inset: 0;\n width: 100%;\n height: 100%;\n opacity: 0.35;\n pointer-events: none;\n z-index: 0;\n }\n @media (prefers-reduced-motion: reduce) {\n #starfield { opacity: 0.18; }\n }\n .split {\n position: relative;\n z-index: 1;\n display: flex;\n min-height: 100vh;\n width: 100%;\n max-width: 1100px;\n margin: 0 auto;\n }\n .marketing-panel {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n padding: 3rem 3.5rem;\n }\n .marketing-content { max-width: 480px; }\n .app-name {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n font-size: 2rem;\n font-weight: 700;\n color: #fff;\n margin-bottom: 0.625rem;\n letter-spacing: -0.02em;\n }\n .app-name img.brand-mark {\n height: 2.21375rem;\n width: auto;\n display: block;\n flex-shrink: 0;\n }\n .app-tagline {\n font-size: 1.25rem;\n color: #a1a1aa;\n line-height: 1.6;\n margin-bottom: 2rem;\n }\n .app-desc {\n font-size: 1rem;\n color: #71717a;\n line-height: 1.6;\n margin-bottom: 2rem;\n }\n .feature-list {\n list-style: none;\n display: flex;\n flex-direction: column;\n gap: 0.875rem;\n }\n .feature-list li {\n display: flex;\n align-items: flex-start;\n gap: 0.625rem;\n font-size: 1rem;\n color: #a1a1aa;\n line-height: 1.5;\n }\n .feature-list li::before {\n content: '';\n flex-shrink: 0;\n width: 8px;\n height: 8px;\n margin-top: 6px;\n border-radius: 50%;\n background: #3f3f46;\n border: 1px solid #52525b;\n }\n .oss-link {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n font-size: 0.8125rem;\n font-weight: 600;\n color: #00B5FF;\n text-decoration: none;\n transition: color 0.15s ease;\n }\n .oss-link:hover { color: #33C4FF; }\n .oss-link svg { width: 15px; height: 15px; flex-shrink: 0; }\n .marketing-actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0.75rem;\n margin-top: 2rem;\n }\n .run-local-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-height: 2.25rem;\n padding: 0.5rem 0.875rem;\n background: rgba(255,255,255,0.08);\n color: #fff;\n border: 1px solid rgba(255,255,255,0.14);\n border-radius: 8px;\n font-size: 0.8125rem;\n font-weight: 500;\n cursor: pointer;\n }\n .run-local-button:hover {\n background: rgba(255,255,255,0.12);\n border-color: rgba(255,255,255,0.24);\n }\n .run-local-panel {\n max-width: 480px;\n margin-top: 0.75rem;\n padding: 0.75rem;\n background: rgba(20,20,20,0.86);\n border: 1px solid rgba(255,255,255,0.1);\n border-radius: 10px;\n box-shadow: 0 14px 36px rgba(0,0,0,0.28);\n }\n .run-local-panel[hidden] { display: none; }\n .run-local-panel code {\n display: block;\n overflow-x: auto;\n padding-bottom: 0.125rem;\n color: #e5e5e5;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", monospace;\n font-size: 0.75rem;\n line-height: 1.5;\n white-space: nowrap;\n }\n .copy-run-local {\n margin-top: 0.625rem;\n padding: 0.375rem 0.625rem;\n background: transparent;\n color: #a1a1aa;\n border: 1px solid rgba(255,255,255,0.12);\n border-radius: 6px;\n font-size: 0.75rem;\n cursor: pointer;\n }\n .copy-run-local:hover { color: #fff; border-color: rgba(255,255,255,0.22); }\n .form-panel {\n flex: 0 0 440px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 2rem;\n }\n .form-panel .card { max-width: 400px; }\n .form-panel .local-note { max-width: 400px; }\n @media (max-width: 900px) {\n .split { flex-direction: column; min-height: auto; }\n .marketing-panel { padding: 2rem 1.5rem 1.5rem; }\n .app-name { font-size: 1.375rem; }\n .app-name img.brand-mark { height: 1.58125rem; }\n .app-tagline { font-size: 1rem; margin-bottom: 1rem; }\n .app-desc { margin-bottom: 1rem; }\n .feature-list { gap: 0.5rem; }\n .form-panel { flex: none; padding: 1.5rem 1rem; }\n }\n`\n : \"\";\n\n const marketingPanelHtml = hasMarketing\n ? `<canvas id=\"starfield\"></canvas>\n<div class=\"split\">\n <div class=\"marketing-panel\">\n <div class=\"marketing-content\">\n <h2 class=\"app-name\">\n <img class=\"brand-mark\" src=\"${esc(brandMarkSrc)}\" alt=\"\" aria-hidden=\"true\" />\n <span>${esc(marketing!.appName)}</span>\n </h2>\n <p class=\"app-tagline\">${esc(marketing!.tagline)}</p>\n${marketing!.description ? ` <p class=\"app-desc\">${esc(marketing!.description)}</p>\\n` : \"\"}${\n marketing!.features?.length\n ? ` <ul class=\"feature-list\">\\n${marketing!.features.map((f) => ` <li>${esc(f)}</li>`).join(\"\\n\")}\\n </ul>\\n`\n : \"\"\n } <div class=\"marketing-actions\">\n${runLocalCommand ? ` <button type=\"button\" class=\"run-local-button\" id=\"run-local-button\" aria-expanded=\"false\" aria-controls=\"run-local-panel\" onclick=\"__anToggleRunLocalCommand()\">Run Locally</button>\\n` : \"\"} <a class=\"oss-link\" href=\"https://github.com/BuilderIO/agent-native\" target=\"_blank\" rel=\"noreferrer\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 19c-4.3 1.4-4.3-2.5-6-3m12 5v-3.5c0-1 .1-1.4-.5-2 2.8-.3 5.5-1.4 5.5-6a4.6 4.6 0 00-1.3-3.2 4.2 4.2 0 00-.1-3.2s-1.1-.3-3.5 1.3a12.3 12.3 0 00-6.2 0C6.5 2.8 5.4 3.1 5.4 3.1a4.2 4.2 0 00-.1 3.2A4.6 4.6 0 004 9.5c0 4.6 2.7 5.7 5.5 6-.6.6-.6 1.2-.5 2V21\"/></svg>\n 100% free and open source\n </a>\n </div>\n${\n runLocalCommand\n ? ` <div class=\"run-local-panel\" id=\"run-local-panel\" hidden data-command=\"${esc(runLocalCommand)}\">\n <code>${esc(runLocalCommand)}</code>\n <button type=\"button\" class=\"copy-run-local\" id=\"copy-run-local\" onclick=\"__anCopyRunLocalCommand()\">Copy command</button>\n </div>\\n`\n : \"\"\n}\n </div>\n </div>\n <div class=\"form-panel\">`\n : \"\";\n\n const marketingCloseHtml = hasMarketing ? `\\n </div>\\n</div>` : \"\";\n\n const starfieldScript = hasMarketing\n ? `\n (function initStarfield() {\n var canvas = document.getElementById('starfield');\n if (!canvas) return;\n var gl = canvas.getContext('webgl', { alpha: false, antialias: false });\n if (!gl) return;\n\n var vs = gl.createShader(gl.VERTEX_SHADER);\n gl.shaderSource(vs, 'attribute vec2 position;void main(){gl_Position=vec4(position,0.0,1.0);}');\n gl.compileShader(vs);\n\n var fs = gl.createShader(gl.FRAGMENT_SHADER);\n gl.shaderSource(fs, [\n 'precision highp float;',\n 'uniform float iTime;uniform vec2 iResolution;uniform vec3 uPointer;',\n '#define S(a,b,t) smoothstep(a,b,t)',\n '#define NUM_LAYERS 4.',\n 'float N21(vec2 p){vec3 a=fract(vec3(p.xyx)*vec3(213.897,653.453,253.098));a+=dot(a,a.yzx+79.76);return fract((a.x+a.y)*a.z);}',\n 'vec2 GetPos(vec2 id,vec2 offs,float t){float n=N21(id+offs);float n1=fract(n*10.);float n2=fract(n*100.);float a=t+n;return offs+vec2(sin(a*n1),cos(a*n2))*.4;}',\n 'vec2 Attract(vec2 p,vec2 cursor,float strength){vec2 delta=cursor-p;float d=length(delta);float pull=1.-smoothstep(.08,1.9,d);pull=pull*pull*(3.-2.*pull);return p+delta*pull*.095*strength;}',\n 'float df_line(vec2 a,vec2 b,vec2 p){vec2 pa=p-a,ba=b-a;float h=clamp(dot(pa,ba)/dot(ba,ba),0.,1.);return length(pa-ba*h);}',\n 'float line(vec2 a,vec2 b,vec2 uv){float r1=.025;float r2=.006;float d=df_line(a,b,uv);float d2=length(a-b);float fade=S(1.5,.5,d2);fade+=S(.05,.02,abs(d2-.75));return S(r1,r2,d)*fade;}',\n 'float NetLayer(vec2 st,float n,float t,vec2 pointer,float pointerStrength){',\n ' vec2 cell=floor(st);vec2 id=cell+n;vec2 cursor=pointer-cell;st=fract(st)-.5;',\n ' vec2 p0=Attract(GetPos(id,vec2(-1,-1),t),cursor,pointerStrength);vec2 p1=Attract(GetPos(id,vec2(0,-1),t),cursor,pointerStrength);vec2 p2=Attract(GetPos(id,vec2(1,-1),t),cursor,pointerStrength);',\n ' vec2 p3=Attract(GetPos(id,vec2(-1,0),t),cursor,pointerStrength);vec2 p4=Attract(GetPos(id,vec2(0,0),t),cursor,pointerStrength);vec2 p5=Attract(GetPos(id,vec2(1,0),t),cursor,pointerStrength);',\n ' vec2 p6=Attract(GetPos(id,vec2(-1,1),t),cursor,pointerStrength);vec2 p7=Attract(GetPos(id,vec2(0,1),t),cursor,pointerStrength);vec2 p8=Attract(GetPos(id,vec2(1,1),t),cursor,pointerStrength);',\n ' float m=0.;float sparkle=0.;float d;float s;float pulse;',\n ' m+=line(p4,p0,st);d=length(st-p0);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p0.x)+fract(p0.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p4,p1,st);d=length(st-p1);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p1.x)+fract(p1.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p4,p2,st);d=length(st-p2);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p2.x)+fract(p2.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p4,p3,st);d=length(st-p3);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p3.x)+fract(p3.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p4,p4,st);d=length(st-p4);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p4.x)+fract(p4.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p4,p5,st);d=length(st-p5);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p5.x)+fract(p5.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p4,p6,st);d=length(st-p6);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p6.x)+fract(p6.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p4,p7,st);d=length(st-p7);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p7.x)+fract(p7.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p4,p8,st);d=length(st-p8);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p8.x)+fract(p8.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',\n ' m+=line(p1,p3,st);m+=line(p1,p5,st);m+=line(p7,p5,st);m+=line(p7,p3,st);',\n ' float sPhase=(sin(t+n)+sin(t*.1))*.25+.5;sPhase+=pow(sin(t*.1)*.5+.5,50.)*5.;m+=sparkle*sPhase;',\n ' return m;',\n '}',\n 'void mainImage(out vec4 fragColor,in vec2 fragCoord){',\n ' vec2 uv=(fragCoord-iResolution.xy*.5)/iResolution.y;',\n ' float t=iTime*.03;float s=sin(t);float c=cos(t);mat2 rot=mat2(c,-s,s,c);vec2 st=uv*rot;vec2 pointerUv=(uPointer.xy-iResolution.xy*.5)/iResolution.y;',\n ' float m=0.;',\n ' for(float i=0.;i<1.;i+=1./NUM_LAYERS){float z=fract(t+i);float size=mix(15.,1.,z);float fade=S(0.,.6,z)*S(1.,.8,z);vec2 pointerSt=pointerUv*rot*size;vec2 layerSt=st*size;float warp=1.-smoothstep(.15,2.7,length(layerSt-pointerSt));warp=warp*warp*(3.-2.*warp)*uPointer.z;layerSt-=(pointerSt-layerSt)*warp*.035;m+=fade*NetLayer(layerSt,i,iTime*0.3,pointerSt,uPointer.z);}',\n ' float cursorLift=1.-smoothstep(.04,.48,length(uv-pointerUv));cursorLift=cursorLift*cursorLift*(3.-2.*cursorLift)*uPointer.z;m*=1.+cursorLift*1.6;',\n ' vec3 col=vec3(0.35)*m;col*=1.-dot(uv,uv);',\n ' float tt=min(iTime,5.0);col*=S(0.,20.,tt);',\n ' col=clamp(col,0.,1.);fragColor=vec4(col,1.);',\n '}',\n 'void main(){mainImage(gl_FragColor,gl_FragCoord.xy);}'\n ].join('\\\\n'));\n gl.compileShader(fs);\n\n var prog = gl.createProgram();\n gl.attachShader(prog, vs);\n gl.attachShader(prog, fs);\n gl.linkProgram(prog);\n gl.useProgram(prog);\n\n var buf = gl.createBuffer();\n gl.bindBuffer(gl.ARRAY_BUFFER, buf);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]), gl.STATIC_DRAW);\n var pos = gl.getAttribLocation(prog, 'position');\n gl.enableVertexAttribArray(pos);\n gl.vertexAttribPointer(pos, 2, gl.FLOAT, false, 0, 0);\n\n var uTime = gl.getUniformLocation(prog, 'iTime');\n var uRes = gl.getUniformLocation(prog, 'iResolution');\n var uPointer = gl.getUniformLocation(prog, 'uPointer');\n var reducedMotionQuery = window.matchMedia ? window.matchMedia('(prefers-reduced-motion: reduce)') : null;\n var reducedMotion = reducedMotionQuery ? reducedMotionQuery.matches : false;\n var pointerDpr = 1, hasPointer = false;\n var pointerX = 0, pointerY = 0, pointerStrength = 0;\n var targetX = 0, targetY = 0, targetStrength = 0;\n\n function resize() {\n var w = window.innerWidth, h = window.innerHeight;\n pointerDpr = Math.min(window.devicePixelRatio, 1.5);\n canvas.width = w * pointerDpr; canvas.height = h * pointerDpr;\n gl.viewport(0, 0, canvas.width, canvas.height);\n if (!hasPointer) {\n pointerX = targetX = canvas.width * 0.5;\n pointerY = targetY = canvas.height * 0.5;\n }\n }\n function onPointerMove(event) {\n var rect = canvas.getBoundingClientRect();\n var x = event.clientX - rect.left;\n var y = event.clientY - rect.top;\n hasPointer = true;\n targetX = x * pointerDpr;\n targetY = (rect.height - y) * pointerDpr;\n targetStrength = x >= 0 && x <= rect.width && y >= 0 && y <= rect.height ? 1 : 0;\n }\n function fadePointer() {\n targetStrength = 0;\n }\n function easePointer(allowPointer) {\n if (!allowPointer) {\n pointerStrength = 0;\n return;\n }\n pointerX += (targetX - pointerX) * 0.22;\n pointerY += (targetY - pointerY) * 0.22;\n pointerStrength += (targetStrength - pointerStrength) * 0.14;\n if (pointerStrength < 0.001 && targetStrength === 0) pointerStrength = 0;\n }\n resize();\n window.addEventListener('resize', resize);\n window.addEventListener('pointermove', onPointerMove, { passive: true });\n window.addEventListener('mousemove', onPointerMove, { passive: true });\n document.addEventListener('pointerleave', fadePointer, { passive: true });\n window.addEventListener('blur', fadePointer);\n\n var start = performance.now(), last = 0, raf = 0, reducedMotionStaticTime = 20;\n function draw(timeSeconds, allowPointer) {\n easePointer(allowPointer !== false && !reducedMotion);\n gl.uniform1f(uTime, timeSeconds);\n gl.uniform2f(uRes, canvas.width, canvas.height);\n gl.uniform3f(uPointer, pointerX, pointerY, pointerStrength);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n }\n function render(now) {\n if (reducedMotion) {\n raf = 0;\n return;\n }\n raf = requestAnimationFrame(render);\n if (now - last < 33) return;\n last = now;\n draw((now - start) * 0.001);\n }\n function startAnimation() {\n if (!raf) raf = requestAnimationFrame(render);\n }\n function stopAnimation() {\n if (raf) {\n cancelAnimationFrame(raf);\n raf = 0;\n }\n }\n function onReducedMotionChange() {\n reducedMotion = reducedMotionQuery ? reducedMotionQuery.matches : false;\n if (reducedMotion) {\n stopAnimation();\n last = 0;\n draw(reducedMotionStaticTime, false);\n } else {\n startAnimation();\n }\n }\n draw(reducedMotion ? reducedMotionStaticTime : 0, !reducedMotion);\n if (reducedMotionQuery) {\n if (reducedMotionQuery.addEventListener) {\n reducedMotionQuery.addEventListener('change', onReducedMotionChange);\n } else {\n reducedMotionQuery.addListener(onReducedMotionChange);\n }\n }\n if (!reducedMotion) startAnimation();\n })();`\n : \"\";\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\">\n<title>${hasMarketing ? esc(marketing!.appName) + \" — Sign in\" : \"Welcome\"}</title>\n<link rel=\"icon\" type=\"image/svg+xml\" href=\"${withAppBasePath(\"/favicon.svg\")}\">\n<link rel=\"apple-touch-icon\" href=\"${withAppBasePath(\"/icon-180.svg\")}\">\n${\n hasMarketing\n ? `<meta name=\"description\" content=\"${esc(marketing!.tagline)}\">\n<meta property=\"og:title\" content=\"${esc(marketing!.appName)}\">\n<meta property=\"og:description\" content=\"${esc(marketing!.tagline)}\">\n<meta property=\"og:image\" content=\"${esc(socialImageUrl)}\">\n<meta property=\"og:image:secure_url\" content=\"${esc(socialImageUrl)}\">\n<meta property=\"og:image:type\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_TYPE}\">\n<meta property=\"og:image:width\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_WIDTH}\">\n<meta property=\"og:image:height\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT}\">\n<meta property=\"og:image:alt\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_ALT}\">\n<meta name=\"twitter:card\" content=\"summary_large_image\">\n<meta name=\"twitter:image\" content=\"${esc(socialImageUrl)}\">\n<meta name=\"twitter:image:alt\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_ALT}\">`\n : \"\"\n}\n<style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n background: #0a0a0a;\n color: #e5e5e5;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n padding: 1rem;\n }\n .card {\n width: 100%;\n max-width: 400px;\n padding: 2rem;\n background: #141414;\n border: 1px solid rgba(255,255,255,0.08);\n border-radius: 12px;\n }\n h1 { font-size: 1.25rem; font-weight: 600; margin-bottom: 0.25rem; color: #fff; }\n .subtitle { font-size: 0.8125rem; color: #888; margin-bottom: 1.5rem; }\n .tabs {\n display: inline-flex;\n width: 100%;\n padding: 4px;\n margin-bottom: 1.5rem;\n background: rgba(255,255,255,0.06);\n border-radius: 8px;\n }\n .tab {\n flex: 1;\n padding: 0.5rem 0.75rem;\n background: none;\n border: none;\n color: #888;\n font-size: 0.8125rem;\n font-weight: 500;\n cursor: pointer;\n border-radius: 6px;\n }\n .tab.active {\n background: #3a3a3a;\n color: #fff;\n box-shadow: 0 1px 2px rgba(0,0,0,0.3);\n }\n .tab:hover:not(.active) { color: #bbb; }\n .form { display: none; }\n .form.active { display: block; }\n .card.verifying .tabs,\n .card.verifying #google-btn,\n .card.verifying #google-err,\n .card.verifying #auth-divider,\n .card.verifying #upgrade-note {\n display: none;\n }\n label { display: block; font-size: 0.8125rem; color: #888; margin-bottom: 0.375rem; }\n input {\n width: 100%;\n padding: 0.5rem 0.75rem;\n background: transparent;\n border: 1px solid rgba(255,255,255,0.12);\n border-radius: 6px;\n color: #e5e5e5;\n font-size: 0.875rem;\n outline: none;\n margin-bottom: 0.875rem;\n }\n input:focus { border-color: rgba(255,255,255,0.3); box-shadow: 0 0 0 1px rgba(255,255,255,0.1); }\n input::placeholder { color: #555; }\n button[type=\"submit\"], .btn-primary {\n width: 100%;\n margin-top: 0.25rem;\n padding: 0.5rem;\n background: #fff;\n color: #000;\n border: none;\n border-radius: 6px;\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n }\n button[type=\"submit\"]:hover, .btn-primary:hover { background: #e5e5e5; }\n button[type=\"submit\"]:disabled { opacity: 0.5; cursor: not-allowed; }\n .btn-secondary {\n width: 100%;\n margin-top: 0.75rem;\n padding: 0.5rem;\n background: transparent;\n color: #888;\n border: 1px solid rgba(255,255,255,0.1);\n border-radius: 6px;\n font-size: 0.8125rem;\n cursor: pointer;\n }\n .btn-secondary:hover { color: #bbb; border-color: rgba(255,255,255,0.2); }\n .msg { margin-top: 0.75rem; font-size: 0.8125rem; display: none; }\n .msg.error { color: #f87171; }\n .msg.success { color: #4ade80; }\n .msg.show { display: block; }\n .step-progress {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 0.5rem;\n margin-bottom: 1.25rem;\n }\n .progress-step {\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.375rem;\n color: #666;\n font-size: 0.6875rem;\n line-height: 1.2;\n text-align: center;\n }\n .progress-step::before {\n content: '';\n position: absolute;\n top: 11px;\n left: calc(-50% + 16px);\n width: calc(100% - 32px);\n height: 1px;\n background: rgba(255,255,255,0.1);\n }\n .progress-step:first-child::before { display: none; }\n .progress-step span {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 999px;\n border: 1px solid rgba(255,255,255,0.14);\n background: #151515;\n color: #777;\n font-size: 0.6875rem;\n font-weight: 600;\n }\n .progress-step strong { font-weight: 500; }\n .progress-step.complete,\n .progress-step.current { color: #e5e5e5; }\n .progress-step.complete span {\n background: #d9f99d;\n border-color: #d9f99d;\n color: #111;\n }\n .progress-step.current span {\n background: #fff;\n border-color: #fff;\n color: #000;\n box-shadow: 0 0 0 4px rgba(255,255,255,0.08);\n }\n .verification-panel {\n padding: 1rem;\n margin-bottom: 0.875rem;\n background: rgba(255,255,255,0.04);\n border: 1px solid rgba(255,255,255,0.08);\n border-radius: 8px;\n }\n .verification-kicker {\n margin-bottom: 0.5rem;\n color: #bef264;\n font-size: 0.75rem;\n font-weight: 500;\n }\n .verification-copy {\n color: #d4d4d8;\n font-size: 0.875rem;\n line-height: 1.55;\n }\n .verification-copy strong {\n color: #fff;\n font-weight: 600;\n word-break: break-word;\n }\n .verification-note {\n margin-top: 0.75rem;\n color: #71717a;\n font-size: 0.75rem;\n line-height: 1.45;\n }\n .inline-actions {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.75rem;\n margin-top: 0.75rem;\n }\n .link-button {\n padding: 0.25rem 0;\n background: none;\n border: none;\n color: #888;\n cursor: pointer;\n font-size: 0.75rem;\n text-decoration: underline;\n text-underline-offset: 2px;\n }\n .link-button:hover { color: #bbb; }\n .link-button:disabled { cursor: wait; opacity: 0.5; }\n .divider {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n margin: 1.25rem 0;\n font-size: 0.75rem;\n color: #555;\n }\n .divider::before, .divider::after {\n content: '';\n flex: 1;\n height: 1px;\n background: rgba(255,255,255,0.08);\n }\n .upgrade-note {\n margin-bottom: 1rem;\n padding: 0.75rem;\n border: 1px solid rgba(255,255,255,0.08);\n border-radius: 8px;\n background: rgba(255,255,255,0.03);\n font-size: 0.75rem;\n line-height: 1.5;\n color: #a1a1aa;\n display: none;\n }\n .upgrade-note.show { display: block; }\n .btn-google {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.625rem;\n padding: 0.5rem;\n background: #fff;\n color: #000;\n border: none;\n border-radius: 6px;\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n }\n .btn-google:hover { background: #e5e5e5; }\n .btn-google:disabled { opacity: 0.5; cursor: wait; }\n .btn-google svg { width: 18px; height: 18px; flex-shrink: 0; }\n .google-signin {\n position: relative;\n width: 100%;\n }\n .google-error { margin-top: 0.5rem; font-size: 0.8125rem; color: #f87171; display: none; }\n .google-error.show { display: block; }\n .google-debug {\n display: none;\n margin-top: 0.5rem;\n font-size: 0.6875rem;\n line-height: 1.45;\n color: #777;\n word-break: break-word;\n }\n .google-debug.show { display: block; }\n .google-preflight {\n display: none;\n position: absolute;\n top: calc(100% + 0.625rem);\n left: 0;\n right: 0;\n z-index: 20;\n padding: 0.875rem;\n border: 1px solid rgba(255,255,255,0.12);\n border-radius: 10px;\n background: #1b1b1b;\n box-shadow: 0 18px 50px rgba(0,0,0,0.48);\n }\n .google-preflight.show { display: block; }\n .google-preflight::before {\n content: '';\n position: absolute;\n top: -6px;\n left: 50%;\n width: 10px;\n height: 10px;\n transform: translateX(-50%) rotate(45deg);\n background: #1b1b1b;\n border-left: 1px solid rgba(255,255,255,0.12);\n border-top: 1px solid rgba(255,255,255,0.12);\n }\n .google-preflight-heading {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 0.75rem;\n margin-bottom: 0.375rem;\n }\n .google-preflight-title {\n color: #fff;\n font-size: 0.8125rem;\n font-weight: 600;\n }\n .google-preflight-close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.5rem;\n height: 1.5rem;\n margin: -0.25rem -0.25rem 0 0;\n background: transparent;\n border: none;\n border-radius: 999px;\n color: #888;\n cursor: pointer;\n font-size: 1.125rem;\n line-height: 1;\n }\n .google-preflight-close:hover { color: #fff; background: rgba(255,255,255,0.07); }\n .google-preflight-copy {\n color: #b4b4b8;\n font-size: 0.75rem;\n line-height: 1.55;\n }\n .google-preflight-copy + .google-preflight-copy { margin-top: 0.5rem; }\n .google-preflight-actions {\n display: flex;\n gap: 0.5rem;\n margin-top: 0.875rem;\n }\n .google-preflight-actions .btn-primary,\n .google-preflight-actions .btn-secondary {\n flex: 1;\n width: auto;\n margin-top: 0;\n }\n .google-preflight-command {\n margin-top: 0.75rem;\n padding: 0.75rem;\n border: 1px solid rgba(255,255,255,0.1);\n border-radius: 8px;\n background: rgba(0,0,0,0.24);\n }\n .google-preflight-command[hidden] { display: none; }\n .google-preflight-command-label {\n margin-bottom: 0.5rem;\n color: #d4d4d8;\n font-size: 0.75rem;\n font-weight: 500;\n }\n .google-preflight-command code {\n display: block;\n overflow-x: auto;\n color: #e5e5e5;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", monospace;\n font-size: 0.71875rem;\n line-height: 1.45;\n white-space: nowrap;\n }\n @media (max-width: 480px) {\n .google-preflight {\n position: static;\n margin-top: 0.625rem;\n }\n .google-preflight::before { display: none; }\n .google-preflight-actions { flex-direction: column; }\n .google-preflight-actions .btn-primary,\n .google-preflight-actions .btn-secondary { width: 100%; }\n }\n .local-note {\n display: none;\n max-width: 400px;\n width: 100%;\n margin-top: 1rem;\n padding: 0.625rem 0.875rem;\n font-size: 0.6875rem;\n line-height: 1.5;\n color: #666;\n border: 1px dashed rgba(255,255,255,0.08);\n border-radius: 8px;\n text-align: center;\n }\n .local-note.show { display: block; }\n .local-note strong { color: #999; font-weight: 500; }\n .local-note a { color: #888; text-decoration: none; }\n .local-note a:hover { color: #bbb; }\n${marketingStyles}\n</style>\n</head>\n<body${hasMarketing ? ' class=\"has-marketing\"' : \"\"}>\n${marketingPanelHtml}\n<div class=\"card\">\n <h1 id=\"heading\">${googleOnly ? \"Sign in\" : \"Welcome\"}</h1>\n <p class=\"subtitle\" id=\"subtitle\">${googleOnly ? \"Use your workspace Google account to continue\" : \"Create an account to get started\"}</p>\n <p\n class=\"upgrade-note\"\n id=\"upgrade-note\"\n data-upgrade-copy=\"Continue signing in to attach this app to your account and migrate local data.\"\n ></p>\n${identitySsoHtml}\n${\n renderGoogleButton\n ? `\n <div class=\"google-signin\" id=\"google-signin\">\n <button class=\"btn-google\" id=\"google-btn\" onclick=\"signInWithGoogle()\"${googleSignInNotice ? ' aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"google-preflight\"' : \"\"}>\n <svg viewBox=\"0 0 24 24\"><path fill=\"#4285F4\" d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z\"/><path fill=\"#34A853\" d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\"/><path fill=\"#FBBC05\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\"/><path fill=\"#EA4335\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\"/></svg>\n Sign in with Google\n </button>\n <p class=\"google-error\" id=\"google-err\"></p>\n <p class=\"google-debug\" id=\"google-debug\"></p>\n${googleNoticeHtml}\n </div>\n${googleOnly ? \"\" : `\\n <div class=\"divider\" id=\"auth-divider\">or</div>\\n`}\n`\n : \"\"\n}\n${\n googleOnly\n ? \"\"\n : ` <div class=\"tabs\">\n <button class=\"tab\" data-tab=\"signup\">Create account</button>\n <button class=\"tab\" data-tab=\"login\">Sign in</button>\n </div>\n\n <form id=\"signup-form\" class=\"form\">\n <label for=\"s-email\">Email</label>\n <input id=\"s-email\" type=\"email\" autocomplete=\"email\" autofocus placeholder=\"you@example.com\" required />\n <label for=\"s-pass\">Password</label>\n <input id=\"s-pass\" type=\"password\" autocomplete=\"new-password\" placeholder=\"At least 8 characters\" required minlength=\"8\" />\n <label for=\"s-pass2\">Confirm password</label>\n <input id=\"s-pass2\" type=\"password\" autocomplete=\"new-password\" placeholder=\"Confirm password\" required minlength=\"8\" />\n <button type=\"submit\">Create account</button>\n <p class=\"msg\" id=\"s-msg\"></p>\n </form>\n\n <div id=\"verification-step\" class=\"form verification-step\" aria-live=\"polite\">\n <div class=\"step-progress\" aria-label=\"Signup progress\">\n <div class=\"progress-step complete\"><span>1</span><strong>Account</strong></div>\n <div class=\"progress-step current\"><span>2</span><strong>Verify</strong></div>\n <div class=\"progress-step\"><span>3</span><strong>Start</strong></div>\n </div>\n <div class=\"verification-panel\">\n <p class=\"verification-kicker\">Verification email sent</p>\n <p class=\"verification-copy\">We sent a secure link to <strong id=\"verify-email\"></strong>. Click it, return here, and this app will finish signing you in automatically.</p>\n <p class=\"verification-note\">You can keep this tab open. If it has not refreshed after you come back, use Continue.</p>\n </div>\n <button type=\"button\" class=\"btn-primary\" id=\"verify-continue\">Continue</button>\n <div class=\"inline-actions\">\n <button type=\"button\" class=\"link-button\" id=\"resend-verification\">Resend email</button>\n <button type=\"button\" class=\"link-button\" id=\"back-to-signup\">Back</button>\n </div>\n <p class=\"msg\" id=\"verify-msg\"></p>\n </div>\n\n <form id=\"login-form\" class=\"form\">\n <label for=\"l-email\">Email</label>\n <input id=\"l-email\" type=\"email\" autocomplete=\"email\" placeholder=\"you@example.com\" required />\n <label for=\"l-pass\">Password</label>\n <input id=\"l-pass\" type=\"password\" autocomplete=\"current-password\" placeholder=\"Enter password\" required />\n <button type=\"submit\">Sign in</button>\n <p class=\"msg error\" id=\"l-msg\"></p>\n <p style=\"margin-top:0.75rem;font-size:0.75rem;text-align:right\">\n <a href=\"#\" id=\"forgot-link\" style=\"color:#888;text-decoration:underline;text-underline-offset:2px\">Forgot password?</a>\n </p>\n </form>\n\n <form id=\"forgot-form\" class=\"form\">\n <label for=\"f-email\">Email</label>\n <input id=\"f-email\" type=\"email\" autocomplete=\"email\" placeholder=\"you@example.com\" required />\n <button type=\"submit\">Send reset link</button>\n <p class=\"msg\" id=\"f-msg\"></p>\n <p style=\"margin-top:0.75rem;font-size:0.75rem;text-align:center\">\n <a href=\"#\" id=\"back-to-login\" style=\"color:#888;text-decoration:underline;text-underline-offset:2px\">Back to sign in</a>\n </p>\n </form>`\n}\n</div>\n<p class=\"local-note\" id=\"local-note\">\n Your account is stored in this app's own DB (<strong>${getConnectionLabel()}</strong>), not a third-party service.\n</p>${marketingCloseHtml}\n<script>\n function __anBasePath() {\n var configured = ${JSON.stringify(appBasePath)};\n if (configured) return configured;\n var marker = '/_agent-native';\n var idx = window.location.pathname.indexOf(marker);\n return idx > 0 ? window.location.pathname.slice(0, idx) : '';\n }\n function __anPath(path) {\n return __anBasePath() + path;\n }\n var __AN_PUBLIC_OAUTH_ORIGIN = ${JSON.stringify(publicOAuthOrigin)};\n var __AN_WORKSPACE_GATEWAY_RETURN_ORIGIN = ${JSON.stringify(workspaceGatewayReturnOrigin)};\n var __AN_GOOGLE_AUTH_MODE = ${JSON.stringify(googleAuthMode)};\n function __anConfiguredOAuthOrigin() {\n if (!__AN_PUBLIC_OAUTH_ORIGIN) return '';\n try {\n var origin = new URL(__AN_PUBLIC_OAUTH_ORIGIN).origin;\n return origin && origin !== window.location.origin ? origin : '';\n } catch(e) {\n return '';\n }\n }\n function __anAuthPath(path) {\n var origin = __anIsBuilderPreview() ? __anConfiguredOAuthOrigin() : '';\n return origin ? origin + path : __anPath(path);\n }\n function __anGoogleAuthUrlPath() {\n return __anIsBuilderPreview()\n ? __anAuthPath('/_agent-native/google/auth-url')\n : __anPath('/_agent-native/google/auth-url');\n }\n function __anBuilderPreviewReturnOrigin() {\n var candidates = [window.location.href, document.referrer || ''];\n try {\n if (window.location.ancestorOrigins) {\n for (var j = 0; j < window.location.ancestorOrigins.length; j++) {\n candidates.push(window.location.ancestorOrigins[j]);\n }\n }\n } catch(e) {}\n for (var i = 0; i < candidates.length; i++) {\n try {\n var url = new URL(candidates[i]);\n var host = url.hostname.toLowerCase();\n var isPreviewHost =\n host === 'builderio.xyz' || host.slice(-14) === '.builderio.xyz' ||\n host === 'builderio.dev' || host.slice(-14) === '.builderio.dev' ||\n host === 'builder.codes' || host.slice(-14) === '.builder.codes' ||\n host === 'builder.my' || host.slice(-11) === '.builder.my';\n if (url.protocol === 'https:' && isPreviewHost) return url.origin;\n } catch(e) {}\n }\n return '';\n }\n function __anWorkspaceGatewayReturnOrigin() {\n var previewOrigin = __anBuilderPreviewReturnOrigin();\n if (previewOrigin) return previewOrigin;\n if (__AN_WORKSPACE_GATEWAY_RETURN_ORIGIN) return __AN_WORKSPACE_GATEWAY_RETURN_ORIGIN;\n return __anIsBuilderDesktop() ? 'http://127.0.0.1:8080' : '';\n }\n function __anNormalizeWorkspaceReturnPath(ret) {\n try {\n var url = new URL(ret || '/', window.location.origin);\n var path = url.pathname || '/';\n if (path === '/dispatch/dispatch') {\n path = '/dispatch';\n } else if (path.indexOf('/dispatch/') === 0) {\n var rest = path.slice('/dispatch/'.length);\n var first = rest.split('/')[0];\n var dispatchRoutes = {\n overview: true, apps: true, metrics: true, vault: true,\n integrations: true, messaging: true, workspace: true,\n agents: true, destinations: true, identities: true,\n approvals: true, audit: true, team: true, 'thread-debug': true,\n 'new-app': true\n };\n if (first === 'dispatch') {\n path = '/dispatch' + rest.slice(first.length);\n } else if (first && !dispatchRoutes[first]) {\n path = '/' + rest;\n }\n }\n return path + url.search + url.hash;\n } catch(e) {\n return ret || '/';\n }\n }\n function __anOAuthReturnTarget(ret) {\n var path = __anNormalizeWorkspaceReturnPath(ret);\n var origin = __anWorkspaceGatewayReturnOrigin();\n return origin ? origin + path : path;\n }\n function __anSessionBridgeUrl(ret, sessionToken) {\n try {\n var url = new URL(ret || window.location.pathname + window.location.search, window.location.origin);\n url.searchParams.set('_session', sessionToken);\n return url.pathname + url.search + url.hash;\n } catch(e) {\n var sep = (ret || '/').indexOf('?') === -1 ? '?' : '&';\n return (ret || '/') + sep + '_session=' + encodeURIComponent(sessionToken);\n }\n }\n function __anFinishOAuthExchange(ret, flowId, sessionToken) {\n if (__anIsBuilderPreview()) {\n if (sessionToken) {\n __anSetOAuthDebug('OAuth exchange redeemed; applying session bridge to embedded app', flowId);\n window.location.replace(__anSessionBridgeUrl(ret, sessionToken));\n return;\n }\n __anSetOAuthDebug('OAuth exchange redeemed; reloading the embedded app', flowId);\n window.location.reload();\n return;\n }\n __anSetOAuthDebug('OAuth exchange redeemed; returning to the app', flowId);\n __anRedirectToSignedInApp(ret);\n }\n function __anHasControlCharacter(value) {\n for (var i = 0; i < value.length; i++) {\n if (value.charCodeAt(i) < 32) return true;\n }\n return false;\n }\n function __anNormalizeReturnPath(raw) {\n var value = typeof raw === 'string' ? raw : '';\n if (!value || __anHasControlCharacter(value)) return '';\n if (value.charAt(0) === '\\\\\\\\') return '';\n if (value.charAt(0) === '/' && (value.charAt(1) === '/' || value.charAt(1) === '\\\\\\\\')) return '';\n try {\n var url = new URL(value, window.location.origin);\n if (url.origin !== window.location.origin) return '';\n return url.pathname + url.search + url.hash;\n } catch(e) {\n return '';\n }\n }\n function __anCurrentReturnPath() {\n return window.location.pathname + window.location.search + window.location.hash;\n }\n function __anGetReturnPath() {\n try {\n var inner = new URLSearchParams(window.location.search).get('return');\n var normalized = __anNormalizeReturnPath(inner);\n if (normalized) return normalized;\n } catch(e) {}\n return __anCurrentReturnPath();\n }\n function __anMountedPathname(pathname) {\n var base = __anBasePath();\n if (base && pathname.indexOf(base + '/') === 0) return pathname.slice(base.length);\n if (base && pathname === base) return '/';\n return pathname || '/';\n }\n function __anIsAuthEntryPath(pathname) {\n var p = __anMountedPathname(pathname);\n return p === '/login' || p === '/signup' || p === '/_agent-native/sign-in';\n }\n function __anGetSignedInReturnPath() {\n try {\n var inner = new URLSearchParams(window.location.search).get('return');\n var normalized = __anNormalizeReturnPath(inner);\n if (normalized) return normalized;\n } catch(e) {}\n if (__anIsAuthEntryPath(window.location.pathname)) return __anPath('/');\n return __anCurrentReturnPath();\n }\n function __anWithAuthCacheBypass(ret) {\n try {\n var url = new URL(ret || __anPath('/'), window.location.origin);\n url.searchParams.set('${AUTH_REDIRECT_QUERY_PARAM}', Date.now().toString(36));\n return url.pathname + url.search + url.hash;\n } catch(e) {\n var fallback = ret || __anPath('/');\n var hashIndex = fallback.indexOf('#');\n var beforeHash = hashIndex === -1 ? fallback : fallback.slice(0, hashIndex);\n var hash = hashIndex === -1 ? '' : fallback.slice(hashIndex);\n var sep = beforeHash.indexOf('?') === -1 ? '?' : '&';\n return beforeHash + sep + '${AUTH_REDIRECT_QUERY_PARAM}=' + Date.now().toString(36) + hash;\n }\n }\n function __anRedirectToSignedInApp(ret) {\n window.location.replace(__anWithAuthCacheBypass(ret || __anGetSignedInReturnPath()));\n }\n${identitySsoScript}\n (function __anRedirectIfAlreadySignedIn() {\n fetch(__anPath('/_agent-native/auth/session'), {\n headers: { 'Accept': 'application/json' },\n credentials: 'include',\n cache: 'no-store',\n }).then(function(res) {\n if (!res.ok) return null;\n return res.json().catch(function() { return null; });\n }).then(function(data) {\n if (data && data.email && !data.error) __anRedirectToSignedInApp();\n }).catch(function() {});\n })();\n var __anBuilderPreviewSeen = false;\n function __anRememberBuilderPreview() {\n __anBuilderPreviewSeen = true;\n try { sessionStorage.setItem('__an_builder_preview_seen', '1'); } catch(e) {}\n }\n function __anHasBuilderPreviewSignal() {\n try {\n var params = new URLSearchParams(window.location.search);\n if (params.has('builder.preview') || params.has('builder.frameEditing') || params.has('__builder_editing__')) return true;\n } catch(e) {}\n return false;\n }\n function __anIsBuilderPreview() {\n if (__anBuilderPreviewSeen) return true;\n if (__anHasBuilderPreviewSignal()) {\n __anRememberBuilderPreview();\n return true;\n }\n try {\n if (sessionStorage.getItem('__an_builder_preview_seen') === '1') {\n __anBuilderPreviewSeen = true;\n return true;\n }\n } catch(e) {}\n try {\n var ref = document.referrer || '';\n var fromBuilder = ref.indexOf('builder.io') !== -1 || ref.indexOf('builder.my') !== -1 || ref.indexOf('builderio.xyz') !== -1 || ref.indexOf('builderio.dev') !== -1 || ref.indexOf('builder.codes') !== -1;\n if (fromBuilder) __anRememberBuilderPreview();\n return fromBuilder;\n } catch(e) {\n return false;\n }\n }\n __anIsBuilderPreview();\n function __anIsBuilderDesktop() {\n try {\n var ua = navigator.userAgent || '';\n return ua.indexOf('Electron') !== -1 && ua.indexOf('AgentNativeDesktop') === -1;\n } catch(e) {\n return false;\n }\n }\n function __anIsAgentNativeDesktop() {\n try {\n return (navigator.userAgent || '').indexOf('AgentNativeDesktop') !== -1;\n } catch(e) {\n return false;\n }\n }\n function __anIsInFrame() {\n try {\n return window.self !== window.top;\n } catch(e) {\n return true;\n }\n }\n function __anIsElectron() {\n try {\n return (navigator.userAgent || '').indexOf('Electron') !== -1;\n } catch(e) {\n return false;\n }\n }\n function __anResolveAuthFlow() {\n if (__anIsBuilderPreview()) return __anIsInFrame() ? 'popup' : 'redirect';\n // Per-session override for ad-hoc testing outside Builder: append\n // ?authMode=popup or ?authMode=redirect to the sign-in URL.\n try {\n var qp = new URLSearchParams(window.location.search).get('authMode');\n if (qp === 'popup' || qp === 'redirect') return qp;\n } catch(e) {}\n var mode = __AN_GOOGLE_AUTH_MODE || 'auto';\n if (mode === 'popup') return 'popup';\n if (mode === 'redirect') return 'redirect';\n return __anIsAgentNativeDesktop() ? 'redirect' : 'popup';\n }\n var __anOAuthPollTimer = null;\n var __anOAuthPollCount = 0;\n function __anNewOAuthFlowId() {\n try {\n if (window.crypto && typeof window.crypto.randomUUID === 'function') {\n return window.crypto.randomUUID();\n }\n } catch(e) {}\n return 'builder-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2);\n }\n function __anFlowDebugId(flowId) {\n return flowId ? String(flowId).slice(-10) : '';\n }\n function __anSetOAuthDebug(message, flowId) {\n var text = message + (flowId ? ' (flow ' + __anFlowDebugId(flowId) + ')' : '');\n try {\n console.info('[agent-native][google-oauth] ' + text);\n } catch(e) {}\n // Only surface the debug overlay when explicitly opted in via #oauth-debug\n // hash or ?oauth_debug=1 query — otherwise it leaks raw flow IDs and\n // diagnostic strings into the user-facing sign-in screen.\n var showDebugOverlay = false;\n try {\n var loc = window.location || {};\n showDebugOverlay =\n (typeof loc.hash === 'string' && loc.hash.indexOf('oauth-debug') !== -1) ||\n (typeof loc.search === 'string' && loc.search.indexOf('oauth_debug=1') !== -1);\n } catch(e) {}\n var debug = document.getElementById('google-debug');\n if (debug) {\n debug.textContent = text;\n if (showDebugOverlay) debug.classList.add('show');\n }\n }\n function __anShowOAuthError(err, btn, message) {\n if (__anOAuthPollTimer) {\n clearInterval(__anOAuthPollTimer);\n __anOAuthPollTimer = null;\n }\n err.textContent = message;\n err.classList.add('show');\n btn.disabled = false;\n }\n function __anHandlePopupOAuthFailure(ret, btn, err, flowId, redirectReason, builderFrameMessage) {\n if (__anIsBuilderPreview() && __anIsInFrame()) {\n __anShowOAuthError(err, btn, builderFrameMessage + ' Allow popups for this site and try again (flow ' + __anFlowDebugId(flowId) + ').');\n return;\n }\n __anStartRedirectOAuth(ret, btn, err, flowId, redirectReason);\n }\n function __anStartRedirectOAuth(ret, btn, err, flowId, reason) {\n var params = new URLSearchParams();\n var oauthReturn = __anIsBuilderPreview() ? __anOAuthReturnTarget(ret) : ret;\n if (oauthReturn) params.set('return', oauthReturn);\n params.set('redirect', '1');\n __anSetOAuthDebug(reason || 'Opening Google sign-in redirect', flowId);\n try {\n __anOpenOAuthUrl(__anGoogleAuthUrlPath() + '?' + params.toString());\n } catch(e) {\n __anShowOAuthError(err, btn, 'Could not start Google sign-in redirect' + (flowId ? ' for flow ' + __anFlowDebugId(flowId) : '') + ': ' + (e && e.message ? e.message : 'unknown error'));\n }\n }\n function __anWaitForOAuthExchange(flowId, ret, btn, err) {\n var started = Date.now();\n var timeoutMs = 5 * 60 * 1000;\n __anOAuthPollCount = 0;\n async function check() {\n __anOAuthPollCount++;\n try {\n var res = await fetch(__anPath('/_agent-native/auth/desktop-exchange') + '?flow_id=' + encodeURIComponent(flowId), { credentials: 'include' });\n var data = await res.json().catch(function() { return {}; });\n if (data && (data.email || data.token)) {\n if (__anOAuthPollTimer) clearInterval(__anOAuthPollTimer);\n __anOAuthPollTimer = null;\n __anFinishOAuthExchange(ret, flowId, data.token);\n return;\n }\n if (data && data.error) {\n __anSetOAuthDebug('OAuth exchange returned an error: ' + (data.message || data.error), flowId);\n __anShowOAuthError(err, btn, data.message || data.error);\n return;\n }\n if (data && data.pending && (__anOAuthPollCount === 1 || __anOAuthPollCount % 5 === 0)) {\n __anSetOAuthDebug('Waiting for the Google callback; polling attempt ' + __anOAuthPollCount, flowId);\n }\n } catch(e) {\n if (__anOAuthPollCount === 1 || __anOAuthPollCount % 5 === 0) {\n __anSetOAuthDebug('Could not reach the OAuth exchange endpoint: ' + (e && e.message ? e.message : 'network error'), flowId);\n }\n }\n if (Date.now() - started > timeoutMs) {\n __anShowOAuthError(err, btn, 'Google sign-in did not finish. Flow ' + __anFlowDebugId(flowId) + ' never reached this app. Check the Google OAuth redirect URI and server logs for [agent-native][google-oauth].');\n }\n }\n if (__anOAuthPollTimer) clearInterval(__anOAuthPollTimer);\n __anOAuthPollTimer = setInterval(check, 1000);\n setTimeout(check, 500);\n }\n function __anStartPopupOAuth(ret, btn, err) {\n var flowId = __anNewOAuthFlowId();\n var oauthReturn = __anIsBuilderPreview() ? __anOAuthReturnTarget(ret) : ret;\n var params = new URLSearchParams();\n if (oauthReturn) params.set('return', oauthReturn);\n params.set('desktop', '1');\n params.set('flow_id', flowId);\n params.set('redirect', '1');\n var url = __anGoogleAuthUrlPath() + '?' + params.toString();\n try { sessionStorage.setItem('__an_signin', '1'); } catch(e) {}\n __anSetOAuthDebug('Opening Google sign-in popup', flowId);\n try {\n var popup = window.open('', '_blank', 'width=640,height=760');\n if (!popup) {\n __anHandlePopupOAuthFailure(ret, btn, err, flowId, 'Google popup was blocked; falling back to redirect', 'Google popup was blocked.');\n return;\n }\n try { popup.opener = null; } catch(e) {}\n try {\n popup.location.href = url;\n } catch(e) {\n try { popup.close(); } catch(closeErr) {}\n __anHandlePopupOAuthFailure(ret, btn, err, flowId, 'Could not navigate Google popup; falling back to redirect', 'Could not navigate Google popup.');\n return;\n }\n __anSetOAuthDebug('Google popup opened; waiting for callback', flowId);\n } catch(e) {\n __anHandlePopupOAuthFailure(ret, btn, err, flowId, 'Could not open Google popup; falling back to redirect', 'Could not open Google popup.');\n return;\n }\n __anWaitForOAuthExchange(flowId, ret, btn, err);\n }\n function __anStartNativeDesktopOAuth(ret, btn, err) {\n var flowId = __anNewOAuthFlowId();\n var params = new URLSearchParams();\n if (ret) params.set('return', ret);\n params.set('desktop', '1');\n params.set('flow_id', flowId);\n params.set('redirect', '1');\n var url = __anGoogleAuthUrlPath() + '?' + params.toString();\n __anSetOAuthDebug('Opening Google sign-in in system browser', flowId);\n __anOpenOAuthUrl(url);\n __anWaitForOAuthExchange(flowId, ret, btn, err);\n }\n function __anOpenOAuthUrl(url) {\n try { sessionStorage.setItem('__an_signin', '1'); } catch(e) {}\n window.location.href = url;\n }\n (function revealLocalNote() {\n var h = location.hostname;\n if (h === 'localhost' || h === '127.0.0.1' || h === '::1' || h.endsWith('.local')) {\n var n = document.getElementById('local-note');\n if (n) n.classList.add('show');\n }\n })();\n (function revealUpgradeNote() {\n var shouldShow = false;\n try {\n var params = new URLSearchParams(location.search);\n shouldShow = params.get('signin') === '1' || params.get('upgrade-from-local') === '1';\n } catch(e) {}\n if (!shouldShow) {\n try { shouldShow = localStorage.getItem('an_migrate_from_local') === '1'; } catch(e) {}\n }\n if (!shouldShow) return;\n var n = document.getElementById('upgrade-note');\n if (!n) return;\n n.textContent = n.getAttribute('data-upgrade-copy') || 'Continue signing in to migrate local data.';\n n.classList.add('show');\n })();\n${\n googleOnly\n ? \"\"\n : ` var TAB_STORAGE_KEY = 'an.onboarding.tab';\n var tabs = document.querySelectorAll('.tab');\n var forms = document.querySelectorAll('.form');\n var subtitles = { signup: 'Create an account to get started', login: 'Sign in to your account' };\n var headings = { signup: 'Welcome', login: 'Welcome back' };\n var pendingSignupEmail = '';\n var pendingSignupPassword = '';\n var verificationCheckInFlight = false;\n function setActiveTab(name, opts) {\n if (name !== 'signup' && name !== 'login') return;\n var form = document.getElementById(name + '-form');\n if (!form) return;\n var card = document.querySelector('.card');\n if (card) card.classList.remove('verifying');\n tabs.forEach(function(x) { x.classList.remove('active'); });\n forms.forEach(function(x) { x.classList.remove('active'); });\n var btn = document.querySelector('.tab[data-tab=\"' + name + '\"]');\n if (btn) btn.classList.add('active');\n form.classList.add('active');\n var sub = document.getElementById('subtitle');\n if (sub && subtitles[name]) sub.textContent = subtitles[name];\n var heading = document.getElementById('heading');\n if (heading && headings[name]) heading.textContent = headings[name];\n if (opts && opts.persist) {\n try { localStorage.setItem(TAB_STORAGE_KEY, name); } catch (e) {}\n }\n }\n function showVerificationStep(email, password) {\n pendingSignupEmail = email || '';\n pendingSignupPassword = password || '';\n tabs.forEach(function(x) { x.classList.remove('active'); });\n forms.forEach(function(x) { x.classList.remove('active'); });\n var card = document.querySelector('.card');\n if (card) card.classList.add('verifying');\n var step = document.getElementById('verification-step');\n if (step) step.classList.add('active');\n var emailNode = document.getElementById('verify-email');\n if (emailNode) emailNode.textContent = pendingSignupEmail;\n var heading = document.getElementById('heading');\n if (heading) heading.textContent = 'Check your email';\n var sub = document.getElementById('subtitle');\n if (sub) sub.textContent = 'Finish creating your account';\n var msg = document.getElementById('verify-msg');\n if (msg) {\n msg.classList.remove('show', 'error', 'success');\n msg.textContent = '';\n }\n try { localStorage.setItem(TAB_STORAGE_KEY, 'signup'); } catch (e) {}\n }\n function getVerificationMessageNode() {\n var verifyStep = document.getElementById('verification-step');\n if (verifyStep && verifyStep.classList.contains('active')) {\n return document.getElementById('verify-msg');\n }\n return document.getElementById('l-msg') || document.getElementById('verify-msg');\n }\n function isVerificationStepActive() {\n var verifyStep = document.getElementById('verification-step');\n return !!(verifyStep && verifyStep.classList.contains('active'));\n }\n function getPendingSignupEmail() {\n var signupEmail = document.getElementById('s-email');\n var loginEmail = document.getElementById('l-email');\n return (pendingSignupEmail || (signupEmail && signupEmail.value) || (loginEmail && loginEmail.value) || '').trim();\n }\n function getPendingSignupPassword() {\n var signupPassword = document.getElementById('s-pass');\n return pendingSignupPassword || (signupPassword && signupPassword.value) || '';\n }\n function movePendingSignupToLogin(message) {\n var email = getPendingSignupEmail();\n setActiveTab('login', { persist: true });\n var loginEmail = document.getElementById('l-email');\n var loginPassword = document.getElementById('l-pass');\n var msg = document.getElementById('l-msg');\n if (loginEmail && email) loginEmail.value = email;\n if (msg) {\n msg.textContent = message || 'Sign in to continue.';\n msg.classList.remove('error');\n msg.classList.add('show', 'success');\n }\n setTimeout(function() { if (loginPassword) loginPassword.focus(); }, 0);\n }\n async function signInWithPendingSignup() {\n var email = getPendingSignupEmail();\n var password = getPendingSignupPassword();\n if (!email || !password) {\n return { ok: false, needsManualSignIn: true };\n }\n var res = await fetch(__anPath('/_agent-native/auth/login'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email: email, password: password }),\n });\n if (res.ok) {\n __anRedirectToSignedInApp();\n return { ok: true };\n }\n var data = await res.json().catch(function() { return {}; });\n var error = (data && (data.error || data.message)) || 'Could not finish sign-in automatically.';\n return {\n ok: false,\n error: error,\n isWaitingForVerification: /not verified|verification/i.test(error),\n };\n }\n async function checkVerificationSession(fallbackText, opts) {\n opts = opts || {};\n if (verificationCheckInFlight) return;\n verificationCheckInFlight = true;\n var msg = getVerificationMessageNode();\n var continueBtn = document.getElementById('verify-continue');\n if (continueBtn && !opts.silent) {\n continueBtn.disabled = true;\n continueBtn.textContent = 'Checking...';\n }\n if (msg && !opts.silent) {\n msg.textContent = 'Checking your verification...';\n msg.classList.remove('error');\n msg.classList.add('show', 'success');\n }\n try {\n var res = await fetch(__anPath('/_agent-native/auth/session'), {\n headers: { 'Accept': 'application/json' },\n });\n var data = await res.json().catch(function() { return {}; });\n if (res.ok && data && data.email && !data.error) {\n __anRedirectToSignedInApp();\n return;\n }\n var loginResult = await signInWithPendingSignup();\n if (loginResult.ok) return;\n if (loginResult.needsManualSignIn) {\n if (!opts.silent) {\n movePendingSignupToLogin(fallbackText || 'Enter your password after verifying your email.');\n }\n return;\n }\n if (loginResult.error && !loginResult.isWaitingForVerification) {\n if (!opts.silent) {\n movePendingSignupToLogin('We could not finish sign-in automatically. Sign in to continue.');\n }\n return;\n }\n if (msg && !opts.silent) {\n msg.textContent = fallbackText || 'Still waiting on verification. Click the link in your email, then try Continue again.';\n msg.classList.remove('success');\n msg.classList.add('show', 'error');\n }\n } catch (err) {\n if (msg && !opts.silent) {\n msg.textContent = 'Could not check verification. Please try again.';\n msg.classList.remove('success');\n msg.classList.add('show', 'error');\n }\n } finally {\n verificationCheckInFlight = false;\n if (continueBtn && !opts.silent) {\n continueBtn.disabled = false;\n continueBtn.textContent = 'Continue';\n }\n }\n }\n function maybeCompleteVerificationAfterReturn() {\n if (!isVerificationStepActive()) return;\n checkVerificationSession(null, { silent: true });\n }\n async function resendVerificationEmail() {\n var btn = document.getElementById('resend-verification');\n var msg = document.getElementById('verify-msg');\n var email = pendingSignupEmail || document.getElementById('s-email').value;\n if (!email) return;\n var original = btn ? btn.textContent : '';\n if (btn) {\n btn.disabled = true;\n btn.textContent = 'Sending...';\n }\n if (msg) msg.classList.remove('show', 'error', 'success');\n try {\n var res = await fetch(__anPath('/_agent-native/auth/ba/send-verification-email'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email: email, callbackURL: __anGetReturnPath() }),\n });\n if (res.ok) {\n if (msg) {\n msg.textContent = 'Sent a fresh verification link.';\n msg.classList.add('show', 'success');\n }\n if (btn) btn.textContent = 'Sent';\n setTimeout(function() {\n if (btn) {\n btn.disabled = false;\n btn.textContent = original;\n }\n }, 1600);\n return;\n }\n var data = await res.json().catch(function() { return {}; });\n if (msg) {\n msg.textContent = (data && (data.message || data.error)) || 'Could not resend the verification email.';\n msg.classList.add('show', 'error');\n }\n if (btn) {\n btn.disabled = false;\n btn.textContent = original;\n }\n } catch (err) {\n if (msg) {\n msg.textContent = 'Network error. Please try again.';\n msg.classList.add('show', 'error');\n }\n if (btn) {\n btn.disabled = false;\n btn.textContent = original;\n }\n }\n }\n (function initActiveTab() {\n var initial = 'signup';\n try {\n var params = new URLSearchParams(location.search);\n var qp = params.get('tab');\n var path = location.pathname;\n while (path.length > 1 && path.charAt(path.length - 1) === '/') path = path.slice(0, -1);\n if (qp === 'login' || qp === 'signup') {\n initial = qp;\n } else if (params.has('verified')) {\n initial = 'login';\n } else if (path === '/login' || path.endsWith('/login')) {\n initial = 'login';\n } else if (path === '/signup' || path.endsWith('/signup')) {\n initial = 'signup';\n } else {\n var stored = localStorage.getItem(TAB_STORAGE_KEY);\n if (stored === 'login' || stored === 'signup') initial = stored;\n }\n } catch (e) {}\n setActiveTab(initial, { persist: false });\n try {\n if (new URLSearchParams(location.search).has('verified')) {\n var msg = document.getElementById('l-msg');\n if (msg) {\n msg.textContent = 'Email verified. Finishing sign-in...';\n msg.classList.remove('error');\n msg.classList.add('show', 'success');\n }\n checkVerificationSession('Email verified. Sign in to continue.');\n }\n } catch (e) {}\n })();\n tabs.forEach(function(t) { t.addEventListener('click', function() {\n setActiveTab(t.dataset.tab, { persist: true });\n }); });\n\n document.getElementById('signup-form').addEventListener('submit', async function(e) {\n e.preventDefault();\n var form = e.currentTarget;\n var btn = form.querySelector('button[type=\"submit\"]');\n var msg = document.getElementById('s-msg');\n msg.classList.remove('show', 'error', 'success');\n var pass = document.getElementById('s-pass').value;\n var pass2 = document.getElementById('s-pass2').value;\n if (pass !== pass2) {\n msg.textContent = 'Passwords do not match';\n msg.classList.add('show', 'error');\n return;\n }\n var originalLabel = btn.textContent;\n btn.disabled = true;\n btn.textContent = 'Creating account…';\n try {\n var email = document.getElementById('s-email').value;\n var res = await fetch(__anPath('/_agent-native/auth/register'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n email: email,\n password: pass,\n callbackURL: __anGetReturnPath(),\n }),\n });\n var data = await res.json().catch(function() { return {}; });\n if (res.ok) {\n // If email verification is required, the server won't return a session.\n // Try logging in — if it fails (unverified), show a \"check your email\" message.\n var loginRes = await fetch(__anPath('/_agent-native/auth/login'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email: email, password: pass }),\n });\n if (loginRes.ok) {\n msg.textContent = 'Account created — signing you in…';\n msg.classList.add('show', 'success');\n __anRedirectToSignedInApp();\n return;\n }\n btn.disabled = false;\n btn.textContent = originalLabel;\n showVerificationStep(email, pass);\n return;\n }\n msg.textContent = data.error || 'Registration failed';\n msg.classList.add('show', 'error');\n btn.disabled = false;\n btn.textContent = originalLabel;\n } catch (err) {\n msg.textContent = 'Network error — please try again';\n msg.classList.add('show', 'error');\n btn.disabled = false;\n btn.textContent = originalLabel;\n }\n });\n\n var verifyContinue = document.getElementById('verify-continue');\n if (verifyContinue) verifyContinue.addEventListener('click', function(e) {\n e.preventDefault();\n checkVerificationSession();\n });\n window.addEventListener('focus', maybeCompleteVerificationAfterReturn);\n document.addEventListener('visibilitychange', function() {\n if (document.visibilityState === 'visible') maybeCompleteVerificationAfterReturn();\n });\n var resendBtn = document.getElementById('resend-verification');\n if (resendBtn) resendBtn.addEventListener('click', function(e) {\n e.preventDefault();\n resendVerificationEmail();\n });\n var backToSignup = document.getElementById('back-to-signup');\n if (backToSignup) backToSignup.addEventListener('click', function(e) {\n e.preventDefault();\n setActiveTab('signup', { persist: true });\n var email = document.getElementById('s-email');\n setTimeout(function() { if (email) email.focus(); }, 0);\n });\n\n var forgotLink = document.getElementById('forgot-link');\n var backToLogin = document.getElementById('back-to-login');\n if (forgotLink) forgotLink.addEventListener('click', function(e) {\n e.preventDefault();\n document.getElementById('login-form').classList.remove('active');\n document.getElementById('forgot-form').classList.add('active');\n var sub = document.getElementById('subtitle');\n if (sub) sub.textContent = 'Reset your password';\n var heading = document.getElementById('heading');\n if (heading) heading.textContent = 'Reset password';\n var fEmail = document.getElementById('f-email');\n var lEmail = document.getElementById('l-email');\n if (lEmail && lEmail.value) fEmail.value = lEmail.value;\n setTimeout(function() { fEmail.focus(); }, 0);\n });\n if (backToLogin) backToLogin.addEventListener('click', function(e) {\n e.preventDefault();\n document.getElementById('forgot-form').classList.remove('active');\n document.getElementById('login-form').classList.add('active');\n var sub = document.getElementById('subtitle');\n if (sub) sub.textContent = subtitles.login;\n var heading = document.getElementById('heading');\n if (heading) heading.textContent = headings.login;\n });\n\n var forgotForm = document.getElementById('forgot-form');\n if (forgotForm) forgotForm.addEventListener('submit', async function(e) {\n e.preventDefault();\n var btn = e.currentTarget.querySelector('button[type=\"submit\"]');\n var msg = document.getElementById('f-msg');\n msg.classList.remove('show', 'error', 'success');\n var original = btn.textContent;\n btn.disabled = true;\n btn.textContent = 'Sending…';\n try {\n var email = document.getElementById('f-email').value;\n var res = await fetch(__anPath('/_agent-native/auth/ba/request-password-reset'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email: email }),\n });\n if (res.ok) {\n msg.textContent = 'If that email exists, a reset link is on its way.';\n msg.classList.add('show', 'success');\n btn.textContent = 'Sent';\n return;\n }\n var data = await res.json().catch(function() { return {}; });\n msg.textContent = (data && (data.message || data.error)) || 'Could not send reset email.';\n msg.classList.add('show', 'error');\n btn.disabled = false;\n btn.textContent = original;\n } catch (err) {\n msg.textContent = 'Network error — please try again';\n msg.classList.add('show', 'error');\n btn.disabled = false;\n btn.textContent = original;\n }\n });\n\n document.getElementById('login-form').addEventListener('submit', async function(e) {\n e.preventDefault();\n var form = e.currentTarget;\n var btn = form.querySelector('button[type=\"submit\"]');\n var msg = document.getElementById('l-msg');\n msg.classList.remove('show', 'success');\n msg.classList.add('error');\n var originalLabel = btn.textContent;\n btn.disabled = true;\n btn.textContent = 'Signing in…';\n try {\n var res = await fetch(__anPath('/_agent-native/auth/login'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n email: document.getElementById('l-email').value,\n password: document.getElementById('l-pass').value,\n }),\n });\n if (res.ok) {\n __anRedirectToSignedInApp();\n return;\n }\n var data = await res.json().catch(function() { return {}; });\n msg.textContent = data.error || 'Invalid email or password';\n msg.classList.add('show');\n btn.disabled = false;\n btn.textContent = originalLabel;\n } catch (err) {\n msg.textContent = 'Network error — please try again';\n msg.classList.add('show');\n btn.disabled = false;\n btn.textContent = originalLabel;\n }\n });\n`\n}\n${\n renderGoogleButton\n ? `\n async function signInWithGoogle() {\n if (__anShouldShowGoogleNotice()) {\n __anShowGoogleNotice();\n return;\n }\n return __anStartGoogleSignIn();\n }\n async function __anStartGoogleSignIn() {\n var btn = document.getElementById('google-btn');\n var err = document.getElementById('google-err');\n var ret = __anGetReturnPath();\n btn.disabled = true;\n err.classList.remove('show');\n if (__anResolveAuthFlow() === 'popup') {\n __anStartPopupOAuth(ret, btn, err);\n return;\n }\n if (__anIsAgentNativeDesktop()) {\n __anStartNativeDesktopOAuth(ret, btn, err);\n return;\n }\n if (__anIsBuilderPreview()) {\n var flowId = __anNewOAuthFlowId();\n __anStartRedirectOAuth(ret, btn, err, flowId, 'Opening Google sign-in redirect from Builder preview');\n return;\n }\n try {\n var authUrl = __anGoogleAuthUrlPath() + '?return=' + encodeURIComponent(ret);\n var res = await fetch(authUrl);\n var data = await res.json();\n if (data.url) {\n __anOpenOAuthUrl(data.url);\n } else {\n err.textContent = data.message || 'Google OAuth is not configured.';\n err.classList.add('show');\n btn.disabled = false;\n }\n } catch (e) {\n err.textContent = 'Failed to connect. Please try again.';\n err.classList.add('show');\n btn.disabled = false;\n }\n }`\n : \"\"\n}\n${\n googleSignInNotice\n ? `\n window.__anGoogleNoticeAccepted = false;\n function __anShouldShowGoogleNotice() {\n var notice = document.getElementById('google-preflight');\n if (!notice || window.__anGoogleNoticeAccepted) return false;\n var host = notice.getAttribute('data-host');\n return !host || window.location.hostname === host;\n }\n function __anSetGoogleNoticeOpen(open) {\n var notice = document.getElementById('google-preflight');\n var trigger = document.getElementById('google-btn');\n if (!notice) return;\n if (open) {\n notice.classList.add('show');\n if (trigger) trigger.setAttribute('aria-expanded', 'true');\n } else {\n notice.classList.remove('show');\n if (trigger) trigger.setAttribute('aria-expanded', 'false');\n }\n }\n function __anShowGoogleNotice() {\n var notice = document.getElementById('google-preflight');\n if (!notice) return;\n __anSetGoogleNoticeOpen(true);\n var continueBtn = document.getElementById('google-preflight-continue');\n if (continueBtn) continueBtn.focus();\n }\n function __anHideGoogleNotice() {\n __anSetGoogleNoticeOpen(false);\n }\n function __anChooseRunLocalFromGoogleNotice() {\n var panel = document.getElementById('google-preflight-run-local-panel');\n if (!panel) {\n __anHideGoogleNotice();\n return;\n }\n panel.removeAttribute('hidden');\n var copy = document.getElementById('copy-google-preflight-run-local');\n if (copy) copy.focus();\n }\n function __anAcceptGoogleNotice() {\n window.__anGoogleNoticeAccepted = true;\n __anHideGoogleNotice();\n __anStartGoogleSignIn();\n }\n (function __anInstallGoogleNoticeDismissal() {\n document.addEventListener('keydown', function(event) {\n if (event.key === 'Escape') __anHideGoogleNotice();\n });\n document.addEventListener('click', function(event) {\n var notice = document.getElementById('google-preflight');\n if (!notice || !notice.classList.contains('show')) return;\n var wrapper = document.getElementById('google-signin');\n if (wrapper && wrapper.contains(event.target)) return;\n __anHideGoogleNotice();\n });\n })();`\n : `\n function __anShouldShowGoogleNotice() { return false; }`\n}\n${starfieldScript}\n${\n runLocalCommand\n ? `\n function __anSetRunLocalCommandOpen(open) {\n var panel = document.getElementById('run-local-panel');\n var button = document.getElementById('run-local-button');\n if (!panel || !button) return;\n if (open) {\n panel.removeAttribute('hidden');\n } else {\n panel.setAttribute('hidden', '');\n }\n button.setAttribute('aria-expanded', String(open));\n }\n function __anToggleRunLocalCommand() {\n var panel = document.getElementById('run-local-panel');\n if (!panel) return;\n __anSetRunLocalCommandOpen(panel.hasAttribute('hidden'));\n }\n function __anCopyCommandFromPanel(panelId, buttonId) {\n var panel = document.getElementById(panelId);\n var button = document.getElementById(buttonId);\n if (!panel || !button) return;\n var command = panel.getAttribute('data-command') || '';\n var original = button.textContent || 'Copy command';\n function markCopied() {\n button.textContent = 'Copied';\n setTimeout(function() { button.textContent = original; }, 1600);\n }\n if (navigator.clipboard && navigator.clipboard.writeText) {\n navigator.clipboard.writeText(command).then(markCopied).catch(function() {});\n }\n }\n function __anCopyRunLocalCommand() {\n __anCopyCommandFromPanel('run-local-panel', 'copy-run-local');\n }\n function __anCopyGoogleNoticeRunLocalCommand() {\n __anCopyCommandFromPanel('google-preflight-run-local-panel', 'copy-google-preflight-run-local');\n }`\n : \"\"\n}\n</script>\n</body>\n</html>`;\n}\n\n/** @deprecated Use getOnboardingHtml() instead */\nexport const ONBOARDING_HTML = getOnboardingHtml();\n\n/**\n * HTML for the password reset page — shown when the user clicks the link in\n * their reset email. Posts `{ newPassword, token }` to Better Auth's\n * `/reset-password` endpoint, then redirects to the login page.\n */\nexport function getResetPasswordHtml(): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\">\n<title>Reset password</title>\n<link rel=\"icon\" type=\"image/svg+xml\" href=\"${withAppBasePath(\"/favicon.svg\")}\">\n<link rel=\"apple-touch-icon\" href=\"${withAppBasePath(\"/icon-180.svg\")}\">\n<style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n body { font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; background: #0a0a0a; color: #e5e5e5; display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 1rem; }\n .card { width: 100%; max-width: 400px; padding: 2rem; background: #141414; border: 1px solid rgba(255,255,255,0.08); border-radius: 12px; }\n h1 { font-size: 1.25rem; font-weight: 600; margin-bottom: 0.25rem; color: #fff; }\n .subtitle { font-size: 0.8125rem; color: #888; margin-bottom: 1.5rem; }\n label { display: block; font-size: 0.8125rem; color: #888; margin-bottom: 0.375rem; }\n input { width: 100%; padding: 0.5rem 0.75rem; background: transparent; border: 1px solid rgba(255,255,255,0.12); border-radius: 6px; color: #e5e5e5; font-size: 0.875rem; outline: none; margin-bottom: 0.875rem; }\n input:focus { border-color: rgba(255,255,255,0.3); box-shadow: 0 0 0 1px rgba(255,255,255,0.1); }\n input::placeholder { color: #555; }\n button[type=\"submit\"] { width: 100%; margin-top: 0.25rem; padding: 0.5rem; background: #fff; color: #000; border: none; border-radius: 6px; font-size: 0.875rem; font-weight: 500; cursor: pointer; }\n button[type=\"submit\"]:hover { background: #e5e5e5; }\n button[type=\"submit\"]:disabled { opacity: 0.5; cursor: not-allowed; }\n .msg { margin-top: 0.75rem; font-size: 0.8125rem; display: none; }\n .msg.error { color: #f87171; }\n .msg.success { color: #4ade80; }\n .msg.show { display: block; }\n .back { display: inline-block; margin-top: 1rem; font-size: 0.75rem; color: #888; text-decoration: none; }\n .back:hover { color: #bbb; }\n</style>\n</head>\n<body>\n<div class=\"card\">\n <h1>Choose a new password</h1>\n <p class=\"subtitle\">Set a new password for your account.</p>\n <form id=\"reset-form\">\n <label for=\"p1\">New password</label>\n <input id=\"p1\" type=\"password\" autocomplete=\"new-password\" autofocus placeholder=\"At least 8 characters\" required minlength=\"8\" />\n <label for=\"p2\">Confirm password</label>\n <input id=\"p2\" type=\"password\" autocomplete=\"new-password\" placeholder=\"Confirm password\" required minlength=\"8\" />\n <button type=\"submit\">Save new password</button>\n <p class=\"msg\" id=\"msg\"></p>\n </form>\n <a class=\"back\" id=\"back-link\" href=\"/\">Back to sign in</a>\n</div>\n<script>\n (function() {\n // Derive the app's base path so apps mounted under a prefix\n // (e.g. /mail, /calendar) get sent home instead of to the root domain.\n var RESET_PATH = '/_agent-native/auth/reset';\n var pathname = window.location.pathname;\n var idx = pathname.indexOf(RESET_PATH);\n var basePath = (idx >= 0 ? pathname.slice(0, idx) : '') || '';\n var homeHref = basePath + '/';\n var backLink = document.getElementById('back-link');\n if (backLink) backLink.setAttribute('href', homeHref);\n var params = new URLSearchParams(location.search);\n var token = params.get('token') || '';\n var msg = document.getElementById('msg');\n if (!token) {\n msg.textContent = 'Missing or invalid reset token. Request a new reset link.';\n msg.classList.add('show', 'error');\n document.getElementById('reset-form').style.display = 'none';\n return;\n }\n document.getElementById('reset-form').addEventListener('submit', async function(e) {\n e.preventDefault();\n var btn = e.currentTarget.querySelector('button[type=\"submit\"]');\n var p1 = document.getElementById('p1').value;\n var p2 = document.getElementById('p2').value;\n msg.classList.remove('show', 'error', 'success');\n if (p1 !== p2) {\n msg.textContent = 'Passwords do not match';\n msg.classList.add('show', 'error');\n return;\n }\n var original = btn.textContent;\n btn.disabled = true;\n btn.textContent = 'Saving…';\n try {\n var res = await fetch(basePath + '/_agent-native/auth/ba/reset-password', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ newPassword: p1, token: token }),\n });\n if (res.ok) {\n msg.textContent = 'Password updated — redirecting to sign in…';\n msg.classList.add('show', 'success');\n setTimeout(function() { window.location.href = homeHref; }, 1200);\n return;\n }\n var data = await res.json().catch(function() { return {}; });\n msg.textContent = (data && (data.message || data.error)) || 'Reset failed. The link may have expired — request a new one.';\n msg.classList.add('show', 'error');\n btn.disabled = false;\n btn.textContent = original;\n } catch (err) {\n msg.textContent = 'Network error — please try again';\n msg.classList.add('show', 'error');\n btn.disabled = false;\n btn.textContent = original;\n }\n });\n })();\n</script>\n</body>\n</html>`;\n}\n"]}
|
package/dist/styles/blocks.css
CHANGED
|
@@ -1342,6 +1342,19 @@
|
|
|
1342
1342
|
max-width: 100%;
|
|
1343
1343
|
}
|
|
1344
1344
|
|
|
1345
|
+
/* Base padding so primitive text never touches the box edge, even when an author
|
|
1346
|
+
* diagram omits its own padding. The wildcard selectors mirror the theme-color
|
|
1347
|
+
* rules above so every box/card/panel variant authors use is covered. Author CSS
|
|
1348
|
+
* (higher specificity, scoped to the diagram instance) still overrides this when
|
|
1349
|
+
* it sets padding explicitly. */
|
|
1350
|
+
.plan-diagram-frame :is(.diagram-node, .diagram-box, [class*="box"]) {
|
|
1351
|
+
padding: 8px 12px;
|
|
1352
|
+
}
|
|
1353
|
+
.plan-diagram-frame
|
|
1354
|
+
:is(.diagram-card, .diagram-panel, [class*="card"], [class*="panel"]) {
|
|
1355
|
+
padding: 14px 16px;
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1345
1358
|
.plan-diagram-frame :is(.diagram-node, .diagram-box, .diagram-card) small {
|
|
1346
1359
|
display: block;
|
|
1347
1360
|
max-width: 100%;
|
|
@@ -1383,15 +1396,24 @@
|
|
|
1383
1396
|
}
|
|
1384
1397
|
|
|
1385
1398
|
.plan-diagram-frame[data-style="sketchy"] :is(.diagram-node, .diagram-box) {
|
|
1386
|
-
padding-inline:
|
|
1399
|
+
padding-inline: 12px;
|
|
1387
1400
|
}
|
|
1388
1401
|
|
|
1389
|
-
.plan-diagram-frame
|
|
1402
|
+
.plan-diagram-frame
|
|
1403
|
+
:is(.diagram-pill, [class*="pill"], [class*="badge"], [class*="chip"]) {
|
|
1390
1404
|
display: inline-flex;
|
|
1391
1405
|
align-items: center;
|
|
1406
|
+
justify-content: center;
|
|
1407
|
+
/* A pill hugs its label. `fit-content` is a definite cross size, so a flex
|
|
1408
|
+
* column with the default `align-items: stretch` no longer blows the pill out
|
|
1409
|
+
* to full width (the number chips and short status labels stay pill-shaped).
|
|
1410
|
+
* The wildcard selectors match the theme-color rules so every pill/badge/chip
|
|
1411
|
+
* variant used across the docs diagrams stays pill-shaped, not a full bar. */
|
|
1412
|
+
width: fit-content;
|
|
1413
|
+
max-width: 100%;
|
|
1392
1414
|
border: 1px solid var(--wf-line);
|
|
1393
1415
|
border-radius: 999px;
|
|
1394
|
-
padding:
|
|
1416
|
+
padding: 3px 11px;
|
|
1395
1417
|
color: var(--wf-ink);
|
|
1396
1418
|
background: var(--wf-paper);
|
|
1397
1419
|
}
|