{"release_id":"01a1c502-4ad1-0000-ec62-adc54d3c69aa","chunk_id":"01a1c502-4cfb-7c82-8ad7-aec9f71af88d","file":"67.Dck5eLJ_.mjs","ignoreList":[],"mappings":"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","names":["next","$.derived","$$props","onMount","onDestroy","step","$.state","email","otpCode","emailSending","otpVerifying","emailError","otpError","otpCooldown","cooldownInterval","startOtpCooldown","$.set","$.get","callAction","action","fields","body","v","res","deserialize","submitEmail","analytics.trackSignInStart","result","d","resendOtp","backHref","afterNavigate","from","path","verifyOtp","createSupabaseBrowserClient","supabase","error","analytics.trackSignInComplete","goto","$.head","$$anchor","$0","isStudioHost","page","STUDIO_BRAND","section","root_2","div","div_1","OAuthButtonRow","node_1","div_2","div_3","input","$.sibling","$.child","$.remove_input_defaults","p","root_3","p_1","root_4","$$render","consequent","alternate","div_4","button","text_1","$.reset","a","$.set_attribute","e","$$value","$.delegated","section_1","root_5","div_5","p_2","strong","div_6","input_1","node_3","p_3","root_6","p_4","root_7","consequent_2","alternate_1","div_7","button_1","text_4","div_8","span","root_8","button_2","root_9","consequent_3","alternate_2","button_3","node_4","consequent_1","alternate_3"],"sources":["../../../../../../src/routes/auth/sign-in/+page.svelte"],"sourcesContent":["<script lang=\"ts\">\n\timport { goto, afterNavigate } from '$app/navigation';\n\timport { deserialize } from '$app/forms';\n\timport { onMount, onDestroy } from 'svelte';\n\timport * as analytics from '$lib/analytics';\n\timport OAuthButtonRow from '$lib/components/auth/OAuthButtonRow.svelte';\n\timport { page } from '$app/state';\n\timport { isStudioHost, STUDIO_BRAND } from '$lib/studio-host';\n\n\tlet { data } = $props();\n\tconst next = $derived(data.next || '/');\n\n\t// RAT-294 follow-up: the auth flow is a focus page — body.fit-screen\n\t// drops main's mobile padding-bottom (68px nav clearance) so the\n\t// min-h-svh section below sits flush with the viewport instead of\n\t// pushing 68px past it (which made the page scrollable for no reason).\n\t// BottomNav hides itself on /auth/* via its own pathname guard.\n\tonMount(() => {\n\t\tdocument.body.classList.add('fit-screen');\n\t});\n\tonDestroy(() => {\n\t\tif (typeof document !== 'undefined') document.body.classList.remove('fit-screen');\n\t});\n\n\t// RAT-158: supabase-js is ~50-100KB and only used inside verifyOtp(). Static\n\t// import on the sign-in entry blew INP p75 to 1178ms because the whole bundle\n\t// parses on first paint. Dynamic-import on demand so the email step has zero\n\t// supabase cost. Same pattern as /auth/callback.\n\n\ttype Step = 'email' | 'otp';\n\tlet step = $state<Step>('email');\n\n\tlet email = $state('');\n\tlet otpCode = $state('');\n\tlet emailSending = $state(false);\n\tlet otpVerifying = $state(false);\n\tlet emailError = $state('');\n\tlet otpError = $state('');\n\tlet otpCooldown = $state(0);\n\tlet cooldownInterval: ReturnType<typeof setInterval> | undefined;\n\n\tfunction startOtpCooldown() {\n\t\totpCooldown = 60;\n\t\tif (cooldownInterval) clearInterval(cooldownInterval);\n\t\tcooldownInterval = setInterval(() => {\n\t\t\totpCooldown--;\n\t\t\tif (otpCooldown <= 0 && cooldownInterval) clearInterval(cooldownInterval);\n\t\t}, 1000);\n\t}\n\n\tasync function callAction(action: string, fields: Record<string, string>) {\n\t\tconst body = new FormData();\n\t\tfor (const [k, v] of Object.entries(fields)) body.append(k, v);\n\t\tconst res = await fetch(`/auth/sign-in?/${action}`, { method: 'POST', body });\n\t\treturn deserialize(await res.text());\n\t}\n\n\tasync function submitEmail() {\n\t\temailError = '';\n\t\tif (!email || !email.includes('@')) { emailError = 'enter a valid email.'; return; }\n\t\tanalytics.trackSignInStart();\n\t\temailSending = true;\n\t\tconst result = await callAction('sendOtp', { email });\n\t\temailSending = false;\n\t\tif (result.type === 'success') {\n\t\t\tstartOtpCooldown();\n\t\t\tstep = 'otp';\n\t\t} else if (result.type === 'failure') {\n\t\t\tconst d = result.data as Record<string, unknown> | undefined;\n\t\t\temailError = (d?.error as string) || 'something went wrong.';\n\t\t}\n\t}\n\n\tasync function resendOtp() {\n\t\totpError = '';\n\t\tconst result = await callAction('resendOtp', { email });\n\t\tif (result.type === 'success') startOtpCooldown();\n\t\telse if (result.type === 'failure') {\n\t\t\tconst d = result.data as Record<string, unknown> | undefined;\n\t\t\totpError = (d?.error as string) || 'failed to resend.';\n\t\t}\n\t}\n\n\t// \"← go back\" returns the user to the section that bounced them here, not\n\t// the homepage. history.back() lands on the entry before sign-in — the\n\t// referring grid (/roleplay, /r, a chat inbox) — which is never gated, so\n\t// it can't loop. We can't link `next`: that's the gated route that bounced\n\t// them, so it would just redirect straight back to this page. A hardcoded\n\t// \"/\" was the old behaviour and dumped every bounced visitor on the\n\t// homepage — the abandonment the sign-in funnel data flagged. Fall back to\n\t// \"/\" only when there's no in-app referrer to return to (direct hit, an\n\t// external link, or an auth bounce we shouldn't loop into).\n\t//\n\t// Where we came from has to come from SvelteKit's own navigation, not\n\t// `document.referrer`. The referrer is fixed at document load and never\n\t// updates on a client-side nav, so on the two paths that actually matter it\n\t// answers the wrong question: an in-app link leaves it pointing at whatever\n\t// loaded the tab, and a gated route's server 303 leaves it pointing at the\n\t// external site the visitor arrived from. Both fall straight through to \"/\",\n\t// which is the behaviour this was meant to replace.\n\t//\n\t// Holding a resolved href (rather than calling history.back()) also fixes the\n\t// dead tap: a tab whose first document is this page has nothing to go back\n\t// to, and back() there does nothing at all.\n\tlet backHref = $state('/');\n\tafterNavigate(({ from }) => {\n\t\tconst path = from?.url.pathname;\n\t\tif (!path || path.startsWith('/auth/')) return; // no loops back into the gate\n\t\tbackHref = path + (from?.url.search ?? '');\n\t});\n\n\tasync function verifyOtp() {\n\t\totpError = '';\n\t\tif (!otpCode || otpCode.length < 6) { otpError = 'enter the 6-digit code.'; return; }\n\t\totpVerifying = true;\n\t\tconst { createSupabaseBrowserClient } = await import('$lib/supabase');\n\t\tconst supabase = createSupabaseBrowserClient();\n\t\tconst { error } = await supabase.auth.verifyOtp({ email, token: otpCode, type: 'email' });\n\t\totpVerifying = false;\n\t\tif (error) { otpError = 'invalid or expired code. check your email and try again.'; return; }\n\t\tanalytics.trackSignInComplete();\n\t\tgoto(next, { invalidateAll: true });\n\t}\n</script>\n\n<svelte:head>\n\t<title>sign in — {isStudioHost(page.url.hostname) ? STUDIO_BRAND : 'ratemyd.'}</title>\n</svelte:head>\n\n{#if step === 'email'}\n<!-- ============ EMAIL ============ -->\n<section class=\"relative flex min-h-svh flex-col items-center justify-center overflow-hidden px-5\">\n\t<div class=\"pointer-events-none absolute inset-0 bg-[linear-gradient(rgba(255,255,255,.006)_1px,transparent_1px),linear-gradient(90deg,rgba(255,255,255,.006)_1px,transparent_1px)] bg-[size:60px_60px]\"></div>\n\n\t<div class=\"relative w-full max-w-md text-center\">\n\t\t<h2 class=\"font-display text-[clamp(1.8rem,5vw,3rem)] font-bold leading-[0.95] tracking-tighter\">\n\t\t\tsign in<br /><span class=\"text-muted\">to continue.</span>\n\t\t</h2>\n\n\t\t<p class=\"mx-auto mt-4 max-w-xs text-sm leading-relaxed text-muted\">\n\t\t\tone tap with google, or use email below.\n\t\t</p>\n\n\t\t<!-- RAT-165: OAuth quick-in. Shown above email so the one-tap path wins\n\t\t     visually. Reddit second (cohort target) but pinned alongside Google. -->\n\t\t<div class=\"mt-8\">\n\t\t\t<OAuthButtonRow {next} />\n\t\t</div>\n\n\t\t<div class=\"mx-auto mt-6 max-w-xs\">\n\t\t\t<div class=\"relative\">\n\t\t\t\t<svg class=\"absolute left-3.5 top-1/2 h-4 w-4 -translate-y-1/2 text-muted/40\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\"/><path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\"/></svg>\n\t\t\t\t<input\n\t\t\t\t\ttype=\"email\"\n\t\t\t\t\tbind:value={email}\n\t\t\t\t\tplaceholder=\"you@brave.com\"\n\t\t\t\t\tdisabled={emailSending}\n\t\t\t\t\tclass=\"w-full rounded-xl border border-border bg-surface py-3 pl-10 pr-4 text-sm text-text placeholder:text-muted/30 focus:border-coral focus:outline-none disabled:opacity-50\"\n\t\t\t\t\tonkeydown={(e) => { if (e.key === 'Enter') submitEmail(); }}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t{#if emailError}\n\t\t\t\t<p class=\"mt-2 text-[11px] text-coral\">{emailError}</p>\n\t\t\t{:else}\n\t\t\t\t<p class=\"mt-2 text-[11px] text-muted/40\">we'll send a 6-digit code. no password needed.</p>\n\t\t\t{/if}\n\t\t</div>\n\n\t\t<div class=\"mt-8 flex flex-col items-center gap-3\">\n\t\t\t<button\n\t\t\t\tclass=\"w-full max-w-xs rounded-xl bg-coral px-7 py-3.5 font-display text-base font-semibold text-white transition-all hover:bg-coral-dark disabled:opacity-50\"\n\t\t\t\tonclick={submitEmail}\n\t\t\t\tdisabled={emailSending}\n\t\t\t>\n\t\t\t\t{emailSending ? 'sending...' : 'send code'}\n\t\t\t</button>\n\t\t\t<!-- Returns to the page that bounced the user, not the homepage — see\n\t\t\t     backHref. Not {next}: that's the gated route, so linking it would\n\t\t\t     loop straight back here. A real <a> so cmd/middle-click still opens\n\t\t\t     a tab and it survives with JS off. -->\n\t\t\t<a\n\t\t\t\thref={backHref}\n\t\t\t\tclass=\"cursor-pointer text-xs font-medium text-muted no-underline transition-colors hover:text-text\"\n\t\t\t>\n\t\t\t\t← go back\n\t\t\t</a>\n\t\t</div>\n\t</div>\n</section>\n\n{:else}\n<!-- ============ OTP ============ -->\n<section class=\"relative flex min-h-svh flex-col items-center justify-center overflow-hidden px-5\">\n\t<div class=\"pointer-events-none absolute inset-0 bg-[linear-gradient(rgba(255,255,255,.006)_1px,transparent_1px),linear-gradient(90deg,rgba(255,255,255,.006)_1px,transparent_1px)] bg-[size:60px_60px]\"></div>\n\n\t<div class=\"relative w-full max-w-md text-center\">\n\t\t<h2 class=\"font-display text-[clamp(1.8rem,5vw,3rem)] font-bold leading-[0.95] tracking-tighter\">\n\t\t\tenter the code.<br /><span class=\"text-coral\">check your inbox.</span>\n\t\t</h2>\n\n\t\t<p class=\"mx-auto mt-4 max-w-sm text-sm leading-relaxed text-muted\">\n\t\t\twe sent a 6-digit code to <strong class=\"text-text break-all\">{email}</strong>\n\t\t</p>\n\n\t\t<div class=\"mx-auto mt-8 max-w-[200px]\">\n\t\t\t<input\n\t\t\t\ttype=\"text\"\n\t\t\t\tinputmode=\"numeric\"\n\t\t\t\tautocomplete=\"one-time-code\"\n\t\t\t\tmaxlength=\"6\"\n\t\t\t\tbind:value={otpCode}\n\t\t\t\tplaceholder=\"000000\"\n\t\t\t\tdisabled={otpVerifying}\n\t\t\t\tclass=\"w-full rounded-xl border border-border bg-surface py-3.5 text-center font-display text-2xl font-bold tracking-[0.3em] text-text placeholder:text-muted/20 focus:border-coral focus:outline-none disabled:opacity-50\"\n\t\t\t\tonkeydown={(e) => { if (e.key === 'Enter') verifyOtp(); }}\n\t\t\t/>\n\t\t\t{#if otpError}\n\t\t\t\t<p class=\"mt-2 text-[11px] text-coral\">{otpError}</p>\n\t\t\t{:else}\n\t\t\t\t<p class=\"mt-2 text-[11px] text-muted/40\">check your inbox (or spam)</p>\n\t\t\t{/if}\n\t\t</div>\n\n\t\t<div class=\"mt-8 flex flex-col items-center gap-3\">\n\t\t\t<button\n\t\t\t\tclass=\"w-full max-w-xs rounded-xl bg-coral px-7 py-3.5 font-display text-base font-semibold text-white transition-all hover:bg-coral-dark disabled:opacity-50\"\n\t\t\t\tonclick={verifyOtp}\n\t\t\t\tdisabled={otpVerifying || otpCode.length < 6}\n\t\t\t>\n\t\t\t\t{otpVerifying ? 'verifying...' : 'verify'}\n\t\t\t</button>\n\t\t\t<div class=\"flex items-center gap-3\">\n\t\t\t\t{#if otpCooldown > 0}\n\t\t\t\t\t<span class=\"text-xs text-muted/40\">resend in {otpCooldown}s</span>\n\t\t\t\t{:else}\n\t\t\t\t\t<button class=\"cursor-pointer text-xs font-medium text-muted transition-colors hover:text-text\" onclick={resendOtp}>resend code</button>\n\t\t\t\t{/if}\n\t\t\t\t<span class=\"text-muted/20\">|</span>\n\t\t\t\t<button class=\"cursor-pointer text-xs font-medium text-muted transition-colors hover:text-text\" onclick={() => (step = 'email')}>different email</button>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</section>\n{/if}\n"],"version":3}