// frontend/auth.jsx — ClerkJS bootstrap + sign-in gate. // Uses the no-bundler ClerkJS browser script (see index.html), initializes // window.Clerk, and exposes: // - : renders children if signed in, sign-in UI otherwise // - window.getAuthToken(): Promise for api.jsx to attach Bearer // - window.clerkAppearance: shared theming object consumed by TopBar's // UserButton mount so the signed-in chrome matches the sign-in card. // - window.signOut(): wrapper around Clerk.signOut for imperative use. // // Auth is required only when window.__CLERK_PUBLISHABLE_KEY is set. If it's // empty, the gate passes through (useful for local dev without Clerk). const { useEffect, useState, useRef, useMemo } = React; const CLERK_KEY = window.__CLERK_PUBLISHABLE_KEY || ""; const AUTH_ENABLED = Boolean(CLERK_KEY); // ─── Clerk appearance ──────────────────────────────────────────────── // Single source of truth for Clerk theming; reused for and // . Variables map to Clerk's internal design tokens; elements // override specific internal classes when variables aren't enough. const clerkAppearance = { variables: { colorPrimary: "#FF5631", colorText: "#24140D", colorTextSecondary: "#6B5147", colorTextOnPrimaryBackground: "#F9FAF6", colorBackground: "#FFFFFF", colorInputBackground: "#F9FAF6", colorInputText: "#24140D", colorNeutral: "#24140D", colorDanger: "#DC2626", colorSuccess: "#16A34A", colorWarning: "#D97706", fontFamily: "'Instrument Sans', Arial, sans-serif", fontFamilyButtons: "'Instrument Sans', Arial, sans-serif", fontSize: "14px", fontWeight: { normal: 400, medium: 500, bold: 600 }, borderRadius: "7px", spacingUnit: "1rem", }, elements: { rootBox: { width: "100%" }, card: { background: "#FFFFFF", border: "1px solid rgba(36,20,13,0.08)", borderRadius: "14px", boxShadow: "0 1px 2px rgba(36,20,13,0.04), 0 18px 48px -12px rgba(36,20,13,0.18)", padding: "36px 32px 28px", }, headerTitle: { fontWeight: 500, fontSize: "22px", letterSpacing: "-0.015em", color: "#24140D", }, headerSubtitle: { color: "#6B5147", fontSize: "13px" }, formFieldLabel: { color: "#24140D", fontSize: "12px", fontWeight: 500, letterSpacing: "0.01em", }, formFieldInput: { background: "#F9FAF6", border: "1px solid rgba(36,20,13,0.14)", borderRadius: "7px", color: "#24140D", padding: "10px 12px", fontSize: "14px", transition: "border-color 120ms ease, box-shadow 120ms ease", "&:hover": { borderColor: "rgba(36,20,13,0.24)" }, "&:focus": { borderColor: "#FF5631", boxShadow: "0 0 0 3px rgba(255,86,49,0.15)", outline: "none", }, }, formButtonPrimary: { background: "#FF5631", color: "#F9FAF6", textTransform: "none", fontSize: "13px", fontWeight: 600, letterSpacing: "0.01em", borderRadius: "7px", padding: "11px 16px", boxShadow: "0 4px 16px rgba(255,86,49,0.28)", transition: "background 120ms ease, transform 120ms ease", "&:hover": { background: "#E84A28", boxShadow: "0 6px 20px rgba(255,86,49,0.32)" }, "&:focus": { background: "#E84A28" }, "&:active": { background: "#D04021", transform: "translateY(1px)" }, }, footer: { background: "transparent" }, footerAction: { color: "#6B5147", fontSize: "13px" }, footerActionText: { color: "#6B5147" }, footerActionLink: { color: "#FF5631", fontWeight: 500, "&:hover": { color: "#D04021", textDecoration: "underline" }, }, identityPreviewEditButton: { color: "#FF5631" }, formResendCodeLink: { color: "#FF5631" }, socialButtonsBlockButton: { borderColor: "rgba(36,20,13,0.12)", color: "#24140D", "&:hover": { background: "#F9FAF6", borderColor: "rgba(36,20,13,0.20)" }, }, socialButtonsBlockButtonText: { color: "#24140D", fontWeight: 500 }, dividerLine: { background: "rgba(36,20,13,0.10)" }, dividerText: { color: "#9A8A82", fontSize: "11px" }, alternativeMethodsBlockButton: { borderColor: "rgba(36,20,13,0.12)", color: "#24140D", "&:hover": { background: "#F9FAF6" }, }, logoBox: { display: "none" }, // custom Vecton logo is rendered above the card // UserButton surfaces userButtonAvatarBox: { width: "32px", height: "32px", boxShadow: "0 0 0 1px rgba(36,20,13,0.10)", }, userButtonTrigger: { borderRadius: "9999px", "&:focus": { boxShadow: "0 0 0 3px rgba(255,86,49,0.20)" }, }, userButtonPopoverCard: { border: "1px solid rgba(36,20,13,0.08)", borderRadius: "12px", boxShadow: "0 18px 40px -10px rgba(36,20,13,0.20)", }, userButtonPopoverActionButton: { color: "#24140D", "&:hover": { background: "#F9FAF6" }, }, userButtonPopoverActionButtonIcon: { color: "#6B5147" }, userPreviewMainIdentifier: { color: "#24140D", fontWeight: 500 }, userPreviewSecondaryIdentifier: { color: "#6B5147" }, }, layout: { logoPlacement: "none", socialButtonsPlacement: "top", socialButtonsVariant: "blockButton", showOptionalFields: true, }, }; window.clerkAppearance = clerkAppearance; // Wait for Clerk to finish loading. The