diff --git a/.markdownlint.yaml b/.markdownlint.yaml index 03369b8..1255d4a 100644 --- a/.markdownlint.yaml +++ b/.markdownlint.yaml @@ -8,3 +8,4 @@ MD033: false # Allow inline HTML (
, , etc.) MD036: false # Allow emphasis (bold/italic) without treating it as heading MD040: false # Fenced code blocks don't need language specified MD041: false # First line doesn't need to be h1 +MD029: false # Allow any ordered list style (1/2/3 or continuous numbering) diff --git a/CLAUDE.md b/CLAUDE.md index 7d19afd..b035d8c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,9 +9,10 @@ The project uses British English - strictly. - **React Compiler** enabled for automatic optimisations - **TypeScript 5** with strict mode - **Tailwind CSS v4** with PostCSS -- **CI/CD** Vitest, PlayWright, GitHub Actions, Vercel +- **CI/CD** Vitest, Playwright, GitHub Actions, Vercel - **Biome** for linting/formatting (replaces ESLint + Prettier) - **Lefthook** for Git hooks (pre-commit: lint, typecheck, unit tests; pre-push: E2E tests) +- **Clerk** for authentication (installed via shadcn/ui CLI with `@clerk/themes`) ## Key Commands @@ -38,7 +39,15 @@ vercel whoami # Verify CLI is authenticated - Tailwind v4 uses `@import "tailwindcss"` syntax (not `@tailwind` directives) - Next.js 16 Dynamic route `params` is a Promise - must await: `{ params }: { params: Promise<{ id: string }> }` -- Next.js 16 Middleware renamed to Proxy - `middleware.ts` β†’ `proxy.ts`, export `proxy()` not `middleware()` +- Next.js 16 Middleware renamed to Proxy - `middleware.ts` β†’ `proxy.ts` (but still uses `clerkMiddleware()` function) + +## Authentication (Clerk) + +- ClerkProvider: `components/clerk-provider.tsx` (applies shadcn theme + Inter font) +- Auth routes: `app/(auth)/sign-in/[[...sign-in]]`, `app/(auth)/sign-up/[[...sign-up]]` +- Sign In: `components/auth/clerk-signin.tsx` β€” client component with theme-aware logo +- Sign Up: `components/auth/clerk-signup.tsx` β€” static logo +- Proxy: `proxy.ts` with `clerkMiddleware()` (not middleware.ts) ## Common Additions for New Projects diff --git a/app/(auth)/sign-in/[[...sign-in]]/page.tsx b/app/(auth)/sign-in/[[...sign-in]]/page.tsx index bfb8f0e..703415d 100644 --- a/app/(auth)/sign-in/[[...sign-in]]/page.tsx +++ b/app/(auth)/sign-in/[[...sign-in]]/page.tsx @@ -1,12 +1,12 @@ -import { SignIn } from "@clerk/nextjs"; import { connection } from "next/server"; +import { ClerkSignIn } from "@/components/auth/clerk-signin"; export default async function SignInPage() { await connection(); return (
- +
); } diff --git a/app/(auth)/sign-up/[[...sign-up]]/page.tsx b/app/(auth)/sign-up/[[...sign-up]]/page.tsx index b1d6aac..feee066 100644 --- a/app/(auth)/sign-up/[[...sign-up]]/page.tsx +++ b/app/(auth)/sign-up/[[...sign-up]]/page.tsx @@ -1,57 +1,12 @@ -import { SignUp } from "@clerk/nextjs"; -import { ChartLine, Clock, ShieldCheck, Sparkles } from "lucide-react"; import { connection } from "next/server"; +import { ClerkSignUp } from "@/components/auth/clerk-signup"; export default async function SignUpPage() { await connection(); + return ( -
-
-
    -
  • -
    -
    -

    - Add authentication and user management to your app with just a few - lines of code. -

    -
  • -
  • -
    -
    -

    - Add intuitive UIs designed to decrease friction for your users. -

    -
  • -
  • -
    -
    -

    - Enable features like two-step verification and enjoy automatic - security updates. -

    -
  • -
  • -
    -
    -

    - Theme our pre-built components, or integrate with our easy-to-use - APIs. -

    -
  • -
-
-
- -
+
+
); } diff --git a/app/globals.css b/app/globals.css index 5f8c12b..ccf5d7f 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,3 +1,4 @@ +@layer theme, base, clerk, components, utilities; /* Must be at top */ @import "tailwindcss"; @import "tw-animate-css"; @import "@clerk/themes/shadcn.css"; @@ -57,7 +58,7 @@ --background: oklch(0.994 0 0); /* #FDFDFD */ --foreground: oklch(0.129 0.042 264.695); - --card: oklch(1 0 0); + --card: oklch(0.9722 0.0034 247.86); /* #F4F6F8 */ --card-foreground: oklch(0.129 0.042 264.695); --popover: oklch(1 0 0); --popover-foreground: oklch(0.129 0.042 264.695); @@ -86,13 +87,22 @@ --sidebar-accent-foreground: oklch(0.208 0.042 265.755); --sidebar-border: oklch(0.929 0.013 255.508); --sidebar-ring: oklch(0.704 0.04 256.788); + --primary-gradient-to: oklch(0.7434 0.115 58.23); /* #E2995F */ + --gradient-primary: linear-gradient( + 93.22deg, + var(--primary) -13.95%, + var(--primary-gradient-to) 99.54% + ); + + /* Centralised logo theming */ + --logo-full-themed: url("/images/logo-light.svg"); } .dark { /* Overrides CSS variables when .dark class is present */ --background: oklch(0 0 0); /* #000000 */ --foreground: oklch(0.984 0.003 247.858); - --card: oklch(0.208 0.042 265.755); + --card: oklch(0.1783 0.0128 270.6); /* #0F1117 */ --card-foreground: oklch(0.984 0.003 247.858); --popover: oklch(0.208 0.042 265.755); --popover-foreground: oklch(0.984 0.003 247.858); @@ -121,6 +131,9 @@ --sidebar-accent-foreground: oklch(0.984 0.003 247.858); --sidebar-border: oklch(1 0 0 / 10%); --sidebar-ring: oklch(0.551 0.027 264.364); + + /* Centralised logo theming (dark) */ + --logo-full-themed: url("/images/logo-dark.svg"); } @layer base { diff --git a/app/layout.tsx b/app/layout.tsx index e624956..104addc 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,20 +1,10 @@ import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; import { Suspense } from "react"; +import { inter, jetbrainsMono, spaceGrotesk } from "@/app/fonts"; import { ClerkProvider } from "@/components/clerk-provider"; import { ThemeProvider } from "@/components/theme-provider"; import "@/app/globals.css"; -const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], -}); - -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", - subsets: ["latin"], -}); - export const metadata: Metadata = { title: "DevFlow", description: @@ -32,10 +22,12 @@ export default function RootLayout({ return ( - - + + + ); +} diff --git a/components/auth/clerk-signup.tsx b/components/auth/clerk-signup.tsx new file mode 100644 index 0000000..49be4fa --- /dev/null +++ b/components/auth/clerk-signup.tsx @@ -0,0 +1,13 @@ +import { SignUp } from "@clerk/nextjs"; + +export function ClerkSignUp() { + return ( + + ); +} diff --git a/components/clerk-provider.tsx b/components/clerk-provider.tsx index c30f7f5..cb37d25 100644 --- a/components/clerk-provider.tsx +++ b/components/clerk-provider.tsx @@ -6,14 +6,40 @@ type ClerkProviderProps = React.ComponentProps; export function ClerkProvider({ children, appearance, + localization, ...props }: ClerkProviderProps) { return ( {children} diff --git a/components/navigation/navbar/index.tsx b/components/navigation/navbar/index.tsx index 5d3f7a4..eeedaf7 100644 --- a/components/navigation/navbar/index.tsx +++ b/components/navigation/navbar/index.tsx @@ -15,17 +15,22 @@ export const Navbar = () => ( aria-label="Primary navigation" className="sticky top-0 z-50 flex w-full items-center justify-between bg-sidebar px-6 py-4 shadow-sm" > - {/* Left: Logo + DevFlow text */} - + {/* Left: Logo (responsive) */} + + {/* Mobile: icon only */} DevFlow logo + {/* Desktop: full themed logo via --logo-full-themed in globals.css */} + -

- DevFlow -

{/* Centre: Global Search placeholder (md+ only) */} diff --git a/components/ui/button.tsx b/components/ui/button.tsx index c6f2d89..72c4ced 100644 --- a/components/ui/button.tsx +++ b/components/ui/button.tsx @@ -19,6 +19,8 @@ const buttonVariants = cva( ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", link: "text-primary underline-offset-4 hover:underline", + gradient: + "bg-[image:var(--gradient-primary)] text-white hover:opacity-90", }, size: { default: "h-9 px-4 py-2 has-[>svg]:px-3", diff --git a/package-lock.json b/package-lock.json index 9512840..aba430e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,11 +15,11 @@ "@vercel/speed-insights": "^1.3.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "lucide-react": "^0.556.0", - "next": "^16.0.8", + "lucide-react": "^0.561.0", + "next": "^16.0.10", "next-themes": "^0.4.6", - "react": "^19.2.1", - "react-dom": "^19.2.1", + "react": "^19.2.3", + "react-dom": "^19.2.3", "tailwind-merge": "^3.4.0" }, "devDependencies": { @@ -30,7 +30,7 @@ "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^14.6.1", - "@types/node": "^24.10.2", + "@types/node": "^25.0.2", "@types/react": "^19", "@types/react-dom": "^19", "@vitejs/plugin-react": "^5.1.2", @@ -42,14 +42,14 @@ "tailwindcss": "^4", "tw-animate-css": "^1.4.0", "typescript": "5.9.3", - "vite-tsconfig-paths": "^5.1.4", + "vite-tsconfig-paths": "^6.0.0", "vitest": "^4.0.15" } }, "node_modules/@acemir/cssom": { - "version": "0.9.28", - "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.28.tgz", - "integrity": "sha512-LuS6IVEivI75vKN8S04qRD+YySP0RmU/cV8UNukhQZvprxF+76Z43TNo/a08eCodaGhT1Us8etqS1ZRY9/Or0A==", + "version": "0.9.29", + "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.29.tgz", + "integrity": "sha512-G90x0VW+9nW4dFajtjCoT+NM0scAfH9Mb08IcjgFHYbfiL/lU04dTF9JuVOi3/OH+DJCQdcIseSXkdCB9Ky6JA==", "dev": true, "license": "MIT" }, @@ -159,7 +159,6 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -185,16 +184,6 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/generator": { "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", @@ -229,16 +218,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/helper-globals": { "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", @@ -605,9 +584,9 @@ } }, "node_modules/@clerk/backend": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/@clerk/backend/-/backend-2.26.0.tgz", - "integrity": "sha512-zj7WgU7sx8rMJyTpUfuPDX+/ZjhfwWM1Cz00PBnKRY+xQBnrTO3KS90Ct2XDVQ7b3lXxjToLLWjdtuSF1QhQSQ==", + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/@clerk/backend/-/backend-2.27.0.tgz", + "integrity": "sha512-e3xdLV/dAp40eFg2eo5tPs/wF942WfJoQA0NLlKHUPYiBD1K+DD8WcX5Fv/kvXUlpoTGiMalexHz42rpx9TJBQ==", "license": "MIT", "dependencies": { "@clerk/shared": "^3.39.0", @@ -638,12 +617,12 @@ } }, "node_modules/@clerk/nextjs": { - "version": "6.36.1", - "resolved": "https://registry.npmjs.org/@clerk/nextjs/-/nextjs-6.36.1.tgz", - "integrity": "sha512-r1Ut99AzPqZsgY+4K+ManP6GzKyygJjZV2o4AlIIb85lvaDfOoZI33z6Nokf1b5+gOOqyX1qQpRSvarRnjNG7w==", + "version": "6.36.2", + "resolved": "https://registry.npmjs.org/@clerk/nextjs/-/nextjs-6.36.2.tgz", + "integrity": "sha512-1ovNi+Xxjq1ZGg8gp++5cp8FYiwkUX5OB5KH7t0bCFkvHTBu48Fdbucmw38AhEqwLnNg9St4GNSKZmyGvVwh6Q==", "license": "MIT", "dependencies": { - "@clerk/backend": "^2.26.0", + "@clerk/backend": "^2.27.0", "@clerk/clerk-react": "^5.58.1", "@clerk/shared": "^3.39.0", "@clerk/types": "^4.101.6", @@ -689,20 +668,14 @@ } } }, - "node_modules/@clerk/shared/node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "license": "MIT" - }, "node_modules/@clerk/testing": { - "version": "1.13.22", - "resolved": "https://registry.npmjs.org/@clerk/testing/-/testing-1.13.22.tgz", - "integrity": "sha512-NkVf5zg4JRZqIHacvgYngUM/KYsqcxspvYRhIdkaFn/zPNUEUbQDqP3ymGyrRngOEUWoMDIq9FSpiJ4SmdXx5w==", + "version": "1.13.23", + "resolved": "https://registry.npmjs.org/@clerk/testing/-/testing-1.13.23.tgz", + "integrity": "sha512-Z/uSgc9aJ++dmi2cX5hcZ/pzAVvXBtKIhNwCMdFI2unsAGE3b4ZJu6cJVAYMIpIFdUiLGe0SKbOuPY50Oau0cw==", "dev": true, "license": "MIT", "dependencies": { - "@clerk/backend": "^2.26.0", + "@clerk/backend": "^2.27.0", "@clerk/shared": "^3.39.0", "@clerk/types": "^4.101.6", "dotenv": "17.2.2" @@ -836,7 +809,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -883,7 +855,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -1838,18 +1809,6 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -1869,15 +1828,15 @@ } }, "node_modules/@next/env": { - "version": "16.0.8", - "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.8.tgz", - "integrity": "sha512-xP4WrQZuj9MdmLJy3eWFHepo+R3vznsMSS8Dy3wdA7FKpjCiesQ6DxZvdGziQisj0tEtCgBKJzjcAc4yZOgLEQ==", + "version": "16.0.10", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.10.tgz", + "integrity": "sha512-8tuaQkyDVgeONQ1MeT9Mkk8pQmZapMKFh5B+OrFUlG3rVmYTXcXlBetBgTurKXGaIZvkoqRT9JL5K3phXcgang==", "license": "MIT" }, "node_modules/@next/swc-darwin-arm64": { - "version": "16.0.8", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.8.tgz", - "integrity": "sha512-yjVMvTQN21ZHOclQnhSFbjBTEizle+1uo4NV6L4rtS9WO3nfjaeJYw+H91G+nEf3Ef43TaEZvY5mPWfB/De7tA==", + "version": "16.0.10", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.10.tgz", + "integrity": "sha512-4XgdKtdVsaflErz+B5XeG0T5PeXKDdruDf3CRpnhN+8UebNa5N2H58+3GDgpn/9GBurrQ1uWW768FfscwYkJRg==", "cpu": [ "arm64" ], @@ -1891,9 +1850,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "16.0.8", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.8.tgz", - "integrity": "sha512-+zu2N3QQ0ZOb6RyqQKfcu/pn0UPGmg+mUDqpAAEviAcEVEYgDckemOpiMRsBP3IsEKpcoKuNzekDcPczEeEIzA==", + "version": "16.0.10", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.10.tgz", + "integrity": "sha512-spbEObMvRKkQ3CkYVOME+ocPDFo5UqHb8EMTS78/0mQ+O1nqE8toHJVioZo4TvebATxgA8XMTHHrScPrn68OGw==", "cpu": [ "x64" ], @@ -1907,9 +1866,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "16.0.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.8.tgz", - "integrity": "sha512-LConttk+BeD0e6RG0jGEP9GfvdaBVMYsLJ5aDDweKiJVVCu6sGvo+Ohz9nQhvj7EQDVVRJMCGhl19DmJwGr6bQ==", + "version": "16.0.10", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.10.tgz", + "integrity": "sha512-uQtWE3X0iGB8apTIskOMi2w/MKONrPOUCi5yLO+v3O8Mb5c7K4Q5KD1jvTpTF5gJKa3VH/ijKjKUq9O9UhwOYw==", "cpu": [ "arm64" ], @@ -1923,9 +1882,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "16.0.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.8.tgz", - "integrity": "sha512-JaXFAlqn8fJV+GhhA9lpg6da/NCN/v9ub98n3HoayoUSPOVdoxEEt86iT58jXqQCs/R3dv5ZnxGkW8aF4obMrQ==", + "version": "16.0.10", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.10.tgz", + "integrity": "sha512-llA+hiDTrYvyWI21Z0L1GiXwjQaanPVQQwru5peOgtooeJ8qx3tlqRV2P7uH2pKQaUfHxI/WVarvI5oYgGxaTw==", "cpu": [ "arm64" ], @@ -1939,9 +1898,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "16.0.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.8.tgz", - "integrity": "sha512-O7M9it6HyNhsJp3HNAsJoHk5BUsfj7hRshfptpGcVsPZ1u0KQ/oVy8oxF7tlwxA5tR43VUP0yRmAGm1us514ng==", + "version": "16.0.10", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.10.tgz", + "integrity": "sha512-AK2q5H0+a9nsXbeZ3FZdMtbtu9jxW4R/NgzZ6+lrTm3d6Zb7jYrWcgjcpM1k8uuqlSy4xIyPR2YiuUr+wXsavA==", "cpu": [ "x64" ], @@ -1955,9 +1914,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "16.0.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.8.tgz", - "integrity": "sha512-8+KClEC/GLI2dLYcrWwHu5JyC5cZYCFnccVIvmxpo6K+XQt4qzqM5L4coofNDZYkct/VCCyJWGbZZDsg6w6LFA==", + "version": "16.0.10", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.10.tgz", + "integrity": "sha512-1TDG9PDKivNw5550S111gsO4RGennLVl9cipPhtkXIFVwo31YZ73nEbLjNC8qG3SgTz/QZyYyaFYMeY4BKZR/g==", "cpu": [ "x64" ], @@ -1971,9 +1930,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "16.0.8", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.8.tgz", - "integrity": "sha512-rpQ/PgTEgH68SiXmhu/cJ2hk9aZ6YgFvspzQWe2I9HufY6g7V02DXRr/xrVqOaKm2lenBFPNQ+KAaeveywqV+A==", + "version": "16.0.10", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.10.tgz", + "integrity": "sha512-aEZIS4Hh32xdJQbHz121pyuVZniSNoqDVx1yIr2hy+ZwJGipeqnMZBJHyMxv2tiuAXGx6/xpTcQJ6btIiBjgmg==", "cpu": [ "arm64" ], @@ -1987,9 +1946,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "16.0.8", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.8.tgz", - "integrity": "sha512-jWpWjWcMQu2iZz4pEK2IktcfR+OA9+cCG8zenyLpcW8rN4rzjfOzH4yj/b1FiEAZHKS+5Vq8+bZyHi+2yqHbFA==", + "version": "16.0.10", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.10.tgz", + "integrity": "sha512-E+njfCoFLb01RAFEnGZn6ERoOqhK1Gl3Lfz1Kjnj0Ulfu7oJbuMyvBKNj/bw8XZnenHDASlygTjZICQW+rYW1Q==", "cpu": [ "x64" ], @@ -2046,7 +2005,6 @@ "integrity": "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "playwright": "1.57.0" }, @@ -2441,9 +2399,9 @@ } }, "node_modules/@tailwindcss/node": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.17.tgz", - "integrity": "sha512-csIkHIgLb3JisEFQ0vxr2Y57GUNYh447C8xzwj89U/8fdW8LhProdxvnVH6U8M2Y73QKiTIH+LWbK3V2BBZsAg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz", + "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2453,37 +2411,37 @@ "lightningcss": "1.30.2", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", - "tailwindcss": "4.1.17" + "tailwindcss": "4.1.18" } }, "node_modules/@tailwindcss/oxide": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.17.tgz", - "integrity": "sha512-F0F7d01fmkQhsTjXezGBLdrl1KresJTcI3DB8EkScCldyKp3Msz4hub4uyYaVnk88BAS1g5DQjjF6F5qczheLA==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz", + "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==", "dev": true, "license": "MIT", "engines": { "node": ">= 10" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.17", - "@tailwindcss/oxide-darwin-arm64": "4.1.17", - "@tailwindcss/oxide-darwin-x64": "4.1.17", - "@tailwindcss/oxide-freebsd-x64": "4.1.17", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.17", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.17", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.17", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.17", - "@tailwindcss/oxide-linux-x64-musl": "4.1.17", - "@tailwindcss/oxide-wasm32-wasi": "4.1.17", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.17", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.17" + "@tailwindcss/oxide-android-arm64": "4.1.18", + "@tailwindcss/oxide-darwin-arm64": "4.1.18", + "@tailwindcss/oxide-darwin-x64": "4.1.18", + "@tailwindcss/oxide-freebsd-x64": "4.1.18", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", + "@tailwindcss/oxide-linux-x64-musl": "4.1.18", + "@tailwindcss/oxide-wasm32-wasi": "4.1.18", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.17.tgz", - "integrity": "sha512-BMqpkJHgOZ5z78qqiGE6ZIRExyaHyuxjgrJ6eBO5+hfrfGkuya0lYfw8fRHG77gdTjWkNWEEm+qeG2cDMxArLQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz", + "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==", "cpu": [ "arm64" ], @@ -2498,9 +2456,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.17.tgz", - "integrity": "sha512-EquyumkQweUBNk1zGEU/wfZo2qkp/nQKRZM8bUYO0J+Lums5+wl2CcG1f9BgAjn/u9pJzdYddHWBiFXJTcxmOg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz", + "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==", "cpu": [ "arm64" ], @@ -2515,9 +2473,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.17.tgz", - "integrity": "sha512-gdhEPLzke2Pog8s12oADwYu0IAw04Y2tlmgVzIN0+046ytcgx8uZmCzEg4VcQh+AHKiS7xaL8kGo/QTiNEGRog==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz", + "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==", "cpu": [ "x64" ], @@ -2532,9 +2490,9 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.17.tgz", - "integrity": "sha512-hxGS81KskMxML9DXsaXT1H0DyA+ZBIbyG/sSAjWNe2EDl7TkPOBI42GBV3u38itzGUOmFfCzk1iAjDXds8Oh0g==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz", + "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==", "cpu": [ "x64" ], @@ -2549,9 +2507,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.17.tgz", - "integrity": "sha512-k7jWk5E3ldAdw0cNglhjSgv501u7yrMf8oeZ0cElhxU6Y2o7f8yqelOp3fhf7evjIS6ujTI3U8pKUXV2I4iXHQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz", + "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==", "cpu": [ "arm" ], @@ -2566,9 +2524,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.17.tgz", - "integrity": "sha512-HVDOm/mxK6+TbARwdW17WrgDYEGzmoYayrCgmLEw7FxTPLcp/glBisuyWkFz/jb7ZfiAXAXUACfyItn+nTgsdQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz", + "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==", "cpu": [ "arm64" ], @@ -2583,9 +2541,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.17.tgz", - "integrity": "sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz", + "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==", "cpu": [ "arm64" ], @@ -2600,9 +2558,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.17.tgz", - "integrity": "sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz", + "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==", "cpu": [ "x64" ], @@ -2617,9 +2575,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.17.tgz", - "integrity": "sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz", + "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==", "cpu": [ "x64" ], @@ -2634,9 +2592,9 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.17.tgz", - "integrity": "sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz", + "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==", "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -2652,10 +2610,10 @@ "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.6.0", - "@emnapi/runtime": "^1.6.0", + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", "@emnapi/wasi-threads": "^1.1.0", - "@napi-rs/wasm-runtime": "^1.0.7", + "@napi-rs/wasm-runtime": "^1.1.0", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, @@ -2663,70 +2621,10 @@ "node": ">=14.0.0" } }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { - "version": "1.6.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.1.0", - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { - "version": "1.6.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { - "version": "1.0.7", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.5.0", - "@emnapi/runtime": "^1.5.0", - "@tybys/wasm-util": "^0.10.1" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { - "version": "2.8.1", - "dev": true, - "inBundle": true, - "license": "0BSD", - "optional": true - }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.17.tgz", - "integrity": "sha512-JU5AHr7gKbZlOGvMdb4722/0aYbU+tN6lv1kONx0JK2cGsh7g148zVWLM0IKR3NeKLv+L90chBVYcJ8uJWbC9A==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz", + "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==", "cpu": [ "arm64" ], @@ -2741,9 +2639,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.17.tgz", - "integrity": "sha512-SKWM4waLuqx0IH+FMDUw6R66Hu4OuTALFgnleKbqhgGU30DY20NORZMZUKgLRjQXNN2TLzKvh48QXTig4h4bGw==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz", + "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==", "cpu": [ "x64" ], @@ -2758,17 +2656,17 @@ } }, "node_modules/@tailwindcss/postcss": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.17.tgz", - "integrity": "sha512-+nKl9N9mN5uJ+M7dBOOCzINw94MPstNR/GtIhz1fpZysxL/4a+No64jCBD6CPN+bIHWFx3KWuu8XJRrj/572Dw==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.18.tgz", + "integrity": "sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==", "dev": true, "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", - "@tailwindcss/node": "4.1.17", - "@tailwindcss/oxide": "4.1.17", + "@tailwindcss/node": "4.1.18", + "@tailwindcss/oxide": "4.1.18", "postcss": "^8.4.41", - "tailwindcss": "4.1.17" + "tailwindcss": "4.1.18" } }, "node_modules/@testing-library/dom": { @@ -2866,7 +2764,8 @@ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -2963,12 +2862,11 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.2.tgz", - "integrity": "sha512-WOhQTZ4G8xZ1tjJTvKOpyEVSGgOTvJAfDK3FNFgELyaTpzhdgHVHeqW8V+UJvzF5BT+/B54T/1S2K6gd9c7bbA==", + "version": "25.0.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.2.tgz", + "integrity": "sha512-gWEkeiyYE4vqjON/+Obqcoeffmk0NF15WSBwSs7zwVA2bAbTaE0SJ7P0WNGoJn8uE7fiaV5a7dKYIJriEqOrmA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -2979,7 +2877,6 @@ "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -2990,11 +2887,17 @@ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "dev": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } }, + "node_modules/@types/react/node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/@types/unist": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", @@ -3206,20 +3109,6 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "license": "MIT", - "optional": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", @@ -3236,6 +3125,7 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=8" } @@ -3246,6 +3136,7 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -3286,15 +3177,14 @@ "integrity": "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/types": "^7.26.0" } }, "node_modules/baseline-browser-mapping": { - "version": "2.9.5", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.5.tgz", - "integrity": "sha512-D5vIoztZOq1XM54LUdttJVc96ggEsIfju2JBvht06pSzpckp3C7HReun67Bghzrtdsq9XdMGbSSB3v3GhMNmAA==", + "version": "2.9.7", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.7.tgz", + "integrity": "sha512-k9xFKplee6KIio3IDbwj+uaCLpqzOwakOgmqzPezM0sFJlFKcg30vk2wOiAJtkTSfx0SSQDSe8q+mWA/fSH5Zg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3325,9 +3215,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", - "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ { @@ -3344,13 +3234,12 @@ } ], "license": "MIT", - "peer": true, "dependencies": { - "baseline-browser-mapping": "^2.8.25", - "caniuse-lite": "^1.0.30001754", - "electron-to-chromium": "^1.5.249", + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", - "update-browserslist-db": "^1.1.4" + "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" @@ -3359,18 +3248,10 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/caniuse-lite": { - "version": "1.0.30001756", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001756.tgz", - "integrity": "sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==", + "version": "1.0.30001760", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz", + "integrity": "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==", "funding": [ { "type": "opencollective", @@ -3520,10 +3401,9 @@ } }, "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "devOptional": true, + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, "node_modules/data-urls": { @@ -3617,7 +3497,8 @@ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/dotenv": { "version": "17.2.2", @@ -3633,16 +3514,16 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.258", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.258.tgz", - "integrity": "sha512-rHUggNV5jKQ0sSdWwlaRDkFc3/rRJIVnOSe9yR4zrR07m3ZxhP4N27Hlg8VeJGGYgFTxK5NqDmWI4DSH72vIJg==", + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", "dev": true, "license": "ISC" }, "node_modules/enhanced-resolve": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", - "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "version": "5.18.4", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", + "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -3654,9 +3535,9 @@ } }, "node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -3736,9 +3617,9 @@ } }, "node_modules/expect-type": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", - "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3778,24 +3659,6 @@ "reusify": "^1.0.4" } }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -3810,10 +3673,9 @@ } }, "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -4108,7 +3970,6 @@ "integrity": "sha512-GtldT42B8+jefDUC4yUKAvsaOrH7PDHmZxZXNgF2xMmymjUbRYJvpAybZAKEmXDGTM0mCsz8duOa4vTm5AY2Kg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@acemir/cssom": "^0.9.28", "@asamuzakjp/dom-selector": "^6.7.6", @@ -4194,9 +4055,9 @@ } }, "node_modules/lefthook": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/lefthook/-/lefthook-2.0.9.tgz", - "integrity": "sha512-SiHbJzS6QCp9UlYh4QZ2Bu+zSNEIFTASXz03hTNL5G6frZeXH56831DDqcPEy+729eA05po3n9ByJ0cAv4yQdw==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/lefthook/-/lefthook-2.0.11.tgz", + "integrity": "sha512-/91k4dt9MRNkzeSr1iMjNi/z8dNuh+XvNfXrWA6PV+M1ZxiNY6uN6bGnr13n+j7N89f4h7YWBhCqhzhK33M5cA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -4204,22 +4065,22 @@ "lefthook": "bin/index.js" }, "optionalDependencies": { - "lefthook-darwin-arm64": "2.0.9", - "lefthook-darwin-x64": "2.0.9", - "lefthook-freebsd-arm64": "2.0.9", - "lefthook-freebsd-x64": "2.0.9", - "lefthook-linux-arm64": "2.0.9", - "lefthook-linux-x64": "2.0.9", - "lefthook-openbsd-arm64": "2.0.9", - "lefthook-openbsd-x64": "2.0.9", - "lefthook-windows-arm64": "2.0.9", - "lefthook-windows-x64": "2.0.9" + "lefthook-darwin-arm64": "2.0.11", + "lefthook-darwin-x64": "2.0.11", + "lefthook-freebsd-arm64": "2.0.11", + "lefthook-freebsd-x64": "2.0.11", + "lefthook-linux-arm64": "2.0.11", + "lefthook-linux-x64": "2.0.11", + "lefthook-openbsd-arm64": "2.0.11", + "lefthook-openbsd-x64": "2.0.11", + "lefthook-windows-arm64": "2.0.11", + "lefthook-windows-x64": "2.0.11" } }, "node_modules/lefthook-darwin-arm64": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/lefthook-darwin-arm64/-/lefthook-darwin-arm64-2.0.9.tgz", - "integrity": "sha512-DRDqDiDWvQ8CAW7c5o90yApxBu5Pe958Ya2OmgTNLKOEw2tSIlz3YPc0AqWlXxp2KkB6RLv0ottLyJFFRmQBtQ==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/lefthook-darwin-arm64/-/lefthook-darwin-arm64-2.0.11.tgz", + "integrity": "sha512-RfpdcJJQXstdgDiIBDRffncayKiXx+0LyMUCunIxDEO2JMXPpYK2hIdpUU0rkitzptAADchG7u1OXJ31rrtIAA==", "cpu": [ "arm64" ], @@ -4231,9 +4092,9 @@ ] }, "node_modules/lefthook-darwin-x64": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/lefthook-darwin-x64/-/lefthook-darwin-x64-2.0.9.tgz", - "integrity": "sha512-Onx2QNWjeVbkDRIbfajcj0U73W51xbhalqRj7yT0JMIIzmyVafnEN2KRrd4i0/UnrquyY2mfrQlVjDM1DoMvCg==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/lefthook-darwin-x64/-/lefthook-darwin-x64-2.0.11.tgz", + "integrity": "sha512-D013UNKQa4FKgpxDMqdaU109U2/Pidtrt9CobQoq8te4eGUglcwxMzuYVTgaYnenz0FgKxSfVaCZsZgwqeMWqA==", "cpu": [ "x64" ], @@ -4245,9 +4106,9 @@ ] }, "node_modules/lefthook-freebsd-arm64": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-2.0.9.tgz", - "integrity": "sha512-0Ew0kabZkl9uid7sz9DxeFjQSI0oBWwMA8eyeQf4z0FWQ1iMay+TSgV8WOSN0OAiS6QECmrl7J+5/S8z4t2XYQ==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-2.0.11.tgz", + "integrity": "sha512-mgfNqG1tiJkCuGNwPG0LEfnAHGJA+Qzl6KidOtX/Zhxmj/sM+6hxiP4LOeEAhCnaZF5kuPtQgbFzShFHc2BK6A==", "cpu": [ "arm64" ], @@ -4259,9 +4120,9 @@ ] }, "node_modules/lefthook-freebsd-x64": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/lefthook-freebsd-x64/-/lefthook-freebsd-x64-2.0.9.tgz", - "integrity": "sha512-bCqj0+bKzMenYkpJty7ZDGR8+RT/PxoYkt5QqIhxCj1b+DjFyOiMAbMiWr7vRm8tLiYK6ieVr5xsvjYPCXAsdA==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/lefthook-freebsd-x64/-/lefthook-freebsd-x64-2.0.11.tgz", + "integrity": "sha512-rnHOlQbJfLGCibr7yHM44kPNgf/tFpEbj/cWVHRhjRdbgYSCAjJk0uKd/EVo3v/vjfId2na0AhWbLvO/aY3wQQ==", "cpu": [ "x64" ], @@ -4273,9 +4134,9 @@ ] }, "node_modules/lefthook-linux-arm64": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/lefthook-linux-arm64/-/lefthook-linux-arm64-2.0.9.tgz", - "integrity": "sha512-jSE+ZIxz++5JkU9vTY0ZCz7VijUvPw9rUXu/ufGq7HYHaxkQlgqGY9p9H9y10Oh1EahWiC3jGlForx5JhHDrCg==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/lefthook-linux-arm64/-/lefthook-linux-arm64-2.0.11.tgz", + "integrity": "sha512-1XjDo2/4fM0TbJBwxZh8w+WMOFueg9oYHkryM8vc3vp8wTajdWBazg1K37JIS3FUco3tcOs+eWHQg0ekVjpWoA==", "cpu": [ "arm64" ], @@ -4287,9 +4148,9 @@ ] }, "node_modules/lefthook-linux-x64": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/lefthook-linux-x64/-/lefthook-linux-x64-2.0.9.tgz", - "integrity": "sha512-Xwqew12w+9HiR0bBetTgaRuR9MdHnoe8gnluUSaH/wuGhC9ChEnxRu4ckahll4/Xl75TntlkOZOMDpnYU5YeEQ==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/lefthook-linux-x64/-/lefthook-linux-x64-2.0.11.tgz", + "integrity": "sha512-OKOcfEvozXhO7+y2xgUzvc2kkqfhluql/sjQSzd8Ka+iK3hM4KCfbfgYx9q61Pjr34a0+i03cuH5DF2dlq/rrg==", "cpu": [ "x64" ], @@ -4301,9 +4162,9 @@ ] }, "node_modules/lefthook-openbsd-arm64": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/lefthook-openbsd-arm64/-/lefthook-openbsd-arm64-2.0.9.tgz", - "integrity": "sha512-5ErPjbzu2623TKPM1lOcsjzswYeEA1u1f8qPp1uvR8QgWDJlx4xdbOQErF5OsYSWhqAegxQITmrJgdPBvjWuFg==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/lefthook-openbsd-arm64/-/lefthook-openbsd-arm64-2.0.11.tgz", + "integrity": "sha512-n1KEx196M3SKaWVNTQXGgxzBsiYAsdAy6Of6I6TAZwPhG7yoRrKGkQrhOlPgMzYl36udG1Lk4D+mfY9T0oOUYQ==", "cpu": [ "arm64" ], @@ -4315,9 +4176,9 @@ ] }, "node_modules/lefthook-openbsd-x64": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/lefthook-openbsd-x64/-/lefthook-openbsd-x64-2.0.9.tgz", - "integrity": "sha512-DhFRJZamG3I+nTPTZV0N3N5VmB4FJSbT/oG4JYDqkvxtqwb3zAL6Q/868uVEgdZl9USxu2yRKI7RnKdllDvdzQ==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/lefthook-openbsd-x64/-/lefthook-openbsd-x64-2.0.11.tgz", + "integrity": "sha512-WAEtKpYUVvuJMVLA38IBoaPnTNSiaEzvUYxjTBlYTLHJwn7HC2GG6P1cnvoua8rfxb9/Bfi7C3D3IPa9VmB33Q==", "cpu": [ "x64" ], @@ -4329,9 +4190,9 @@ ] }, "node_modules/lefthook-windows-arm64": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/lefthook-windows-arm64/-/lefthook-windows-arm64-2.0.9.tgz", - "integrity": "sha512-zp3mLv67+NBPuX9YrYk3CArkREoko1txAsEPyiB/NXGH3QgLHw9HbR+IeY1TslGlXvzQTBrJaiNcmsQWLFFvAQ==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/lefthook-windows-arm64/-/lefthook-windows-arm64-2.0.11.tgz", + "integrity": "sha512-HBqW1qfAnmmbpet7gSWatB6H5YIFdGxCqzolMCLwY/0o8oPFiMwdNE5RGp5JMmhZdz/h3XlbaUlIhnxoW8dk5g==", "cpu": [ "arm64" ], @@ -4343,9 +4204,9 @@ ] }, "node_modules/lefthook-windows-x64": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/lefthook-windows-x64/-/lefthook-windows-x64-2.0.9.tgz", - "integrity": "sha512-1TMNYvsW4D7MD66CRXkvcVTbNCq93wTH5IjTlSSn5CtJer9PFwBMWZfeFeEBU0c0gGAUq4NmkYN2pS8RZfISvA==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/lefthook-windows-x64/-/lefthook-windows-x64-2.0.11.tgz", + "integrity": "sha512-e5TYmV5cBZfRrhPVFCqjauegLI5CjdAd8exyAbMzGHkiwp3ZK145Su/pntgEP3d+ayS9mpgYPJmXYOSL7WHlyg==", "cpu": [ "x64" ], @@ -4638,9 +4499,9 @@ } }, "node_modules/lucide-react": { - "version": "0.556.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.556.0.tgz", - "integrity": "sha512-iOb8dRk7kLaYBZhR2VlV1CeJGxChBgUthpSP8wom9jfj79qovgG6qcSdiy6vkoREKPnbUYzJsCn4o4PtG3Iy+A==", + "version": "0.561.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.561.0.tgz", + "integrity": "sha512-Y59gMY38tl4/i0qewcqohPdEbieBy7SovpBL9IFebhc2mDd8x4PZSOsiFRkpPcOq6bj1r/mjH/Rk73gSlIJP2A==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -4652,6 +4513,7 @@ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, "license": "MIT", + "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -4684,19 +4546,6 @@ "markdown-it": "bin/markdown-it.mjs" } }, - "node_modules/markdown-it/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/markdownlint": { "version": "0.40.0", "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.40.0.tgz", @@ -4727,7 +4576,6 @@ "integrity": "sha512-esPk+8Qvx/f0bzI7YelUeZp+jCtFOk3KjZ7s9iBQZ6HlymSXoTtWGiIRZP05/9Oy2ehIoIjenVwndxGtxOIJYQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "globby": "15.0.0", "js-yaml": "4.1.1", @@ -5334,19 +5182,6 @@ "node": ">=8.6" } }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -5383,13 +5218,12 @@ } }, "node_modules/next": { - "version": "16.0.8", - "resolved": "https://registry.npmjs.org/next/-/next-16.0.8.tgz", - "integrity": "sha512-LmcZzG04JuzNXi48s5P+TnJBsTGPJunViNKV/iE4uM6kstjTQsQhvsAv+xF6MJxU2Pr26tl15eVbp0jQnsv6/g==", + "version": "16.0.10", + "resolved": "https://registry.npmjs.org/next/-/next-16.0.10.tgz", + "integrity": "sha512-RtWh5PUgI+vxlV3HdR+IfWA1UUHu0+Ram/JBO4vWB54cVPentCD0e+lxyAYEsDTqGGMg7qpjhKh6dc6aW7W/sA==", "license": "MIT", - "peer": true, "dependencies": { - "@next/env": "16.0.8", + "@next/env": "16.0.10", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", @@ -5402,14 +5236,14 @@ "node": ">=20.9.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "16.0.8", - "@next/swc-darwin-x64": "16.0.8", - "@next/swc-linux-arm64-gnu": "16.0.8", - "@next/swc-linux-arm64-musl": "16.0.8", - "@next/swc-linux-x64-gnu": "16.0.8", - "@next/swc-linux-x64-musl": "16.0.8", - "@next/swc-win32-arm64-msvc": "16.0.8", - "@next/swc-win32-x64-msvc": "16.0.8", + "@next/swc-darwin-arm64": "16.0.10", + "@next/swc-darwin-x64": "16.0.10", + "@next/swc-linux-arm64-gnu": "16.0.10", + "@next/swc-linux-arm64-musl": "16.0.10", + "@next/swc-linux-x64-gnu": "16.0.10", + "@next/swc-linux-x64-musl": "16.0.10", + "@next/swc-win32-arm64-msvc": "16.0.10", + "@next/swc-win32-x64-msvc": "16.0.10", "sharp": "^0.34.4" }, "peerDependencies": { @@ -5524,6 +5358,19 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/path-type": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", @@ -5551,14 +5398,13 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", - "peer": true, "engines": { - "node": ">=12" + "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" @@ -5596,21 +5442,6 @@ "node": ">=18" } }, - "node_modules/playwright/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -5631,7 +5462,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -5647,6 +5477,7 @@ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -5698,26 +5529,24 @@ "license": "MIT" }, "node_modules/react": { - "version": "19.2.1", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", - "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", + "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "19.2.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.1.tgz", - "integrity": "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==", + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.2.1" + "react": "^19.2.3" } }, "node_modules/react-is": { @@ -5725,7 +5554,8 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/react-refresh": { "version": "0.18.0", @@ -5865,16 +5695,13 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "license": "ISC", - "optional": true, "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/server-only": { @@ -5928,6 +5755,19 @@ "@img/sharp-win32-x64": "0.34.5" } }, + "node_modules/sharp/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/siginfo": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", @@ -5957,29 +5797,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -6116,9 +5933,9 @@ } }, "node_modules/tailwindcss": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.17.tgz", - "integrity": "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", + "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", "dev": true, "license": "MIT" }, @@ -6136,34 +5953,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/terser": { - "version": "5.44.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", - "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -6198,6 +5987,37 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tinyrainbow": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", @@ -6209,22 +6029,22 @@ } }, "node_modules/tldts": { - "version": "7.0.18", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.18.tgz", - "integrity": "sha512-lCcgTAgMxQ1JKOWrVGo6E69Ukbnx4Gc1wiYLRf6J5NN4HRYJtCby1rPF8rkQ4a6qqoFBK5dvjJ1zJ0F7VfDSvw==", + "version": "7.0.19", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.19.tgz", + "integrity": "sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^7.0.18" + "tldts-core": "^7.0.19" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "7.0.18", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.18.tgz", - "integrity": "sha512-jqJC13oP4FFAahv4JT/0WTDrCF9Okv7lpKtOZUGPLiAnNbACcSg8Y8T+Z9xthOmRBqi/Sob4yi0TE0miRCvF7Q==", + "version": "7.0.19", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.19.tgz", + "integrity": "sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==", "dev": true, "license": "MIT" }, @@ -6310,7 +6130,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6347,9 +6166,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", - "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", + "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", "dev": true, "funding": [ { @@ -6387,12 +6206,11 @@ } }, "node_modules/vite": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.4.tgz", - "integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==", + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.7.tgz", + "integrity": "sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -6463,9 +6281,9 @@ } }, "node_modules/vite-tsconfig-paths": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.1.4.tgz", - "integrity": "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-6.0.0.tgz", + "integrity": "sha512-0lGkM62rud1ShKWLbJpbTHPoJuZIL9QW1ecCueDhqxWrStIRsyHapBQ4eV05tBqrW9z6jkp9ybBVgLSWp+Mv1A==", "dev": true, "license": "MIT", "dependencies": { @@ -6482,6 +6300,52 @@ } } }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/vitest": { "version": "4.0.15", "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.15.tgz", @@ -6560,6 +6424,19 @@ } } }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", diff --git a/package.json b/package.json index e839c0f..d300b77 100644 --- a/package.json +++ b/package.json @@ -29,11 +29,11 @@ "@vercel/speed-insights": "^1.3.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "lucide-react": "^0.556.0", - "next": "^16.0.8", + "lucide-react": "^0.561.0", + "next": "^16.0.10", "next-themes": "^0.4.6", - "react": "^19.2.1", - "react-dom": "^19.2.1", + "react": "^19.2.3", + "react-dom": "^19.2.3", "tailwind-merge": "^3.4.0" }, "devDependencies": { @@ -44,7 +44,7 @@ "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^14.6.1", - "@types/node": "^24.10.2", + "@types/node": "^25.0.2", "@types/react": "^19", "@types/react-dom": "^19", "@vitejs/plugin-react": "^5.1.2", @@ -56,7 +56,7 @@ "tailwindcss": "^4", "tw-animate-css": "^1.4.0", "typescript": "5.9.3", - "vite-tsconfig-paths": "^5.1.4", + "vite-tsconfig-paths": "^6.0.0", "vitest": "^4.0.15" } } diff --git a/x_docs/figma/auth/flows.jpg b/x_docs/figma/auth/flows.jpg new file mode 100755 index 0000000..0ee8e7e Binary files /dev/null and b/x_docs/figma/auth/flows.jpg differ diff --git a/x_docs/own/2024-12-14-eval-auth-ui-customise.md b/x_docs/own/2024-12-14-eval-auth-ui-customise.md new file mode 100644 index 0000000..f0245f4 --- /dev/null +++ b/x_docs/own/2024-12-14-eval-auth-ui-customise.md @@ -0,0 +1,333 @@ +# Auth UI Changes Evaluation Report + +**Branch:** `style/auth-ui` +**Evaluated:** 14 December 2025 +**Reviewer:** Claude (Quality Audit) + +--- + +## πŸ“‹ Executive Summary + +This changeset implements custom branding and theming for the authentication UI, introducing responsive logos, theme-aware components, and localised Clerk authentication forms. The implementation demonstrates solid understanding of Tailwind CSS v4 theming patterns and Clerk's appearance API. All identified issues have been addressed. + +--- + +## πŸ“Š Changes Overview + +| File | Change | Purpose | +|------|--------|---------| +| `app/(auth)/sign-in/[[...sign-in]]/page.tsx` | Modified | Replaced direct `` with custom wrapper | +| `app/(auth)/sign-up/[[...sign-up]]/page.tsx` | Modified | Replaced direct `` with custom wrapper | +| `app/globals.css` | Modified | Added `--logo-full-themed` CSS variable for dark/light logos | +| `components/auth/clerk-signin.tsx` | **New** | Client component with JS theme detection for logo | +| `components/auth/clerk-signup.tsx` | **New** | Server component with static logo | +| `components/clerk-provider.tsx` | Modified | Added localization and footer styling | +| `components/navigation/navbar/index.tsx` | Modified | Responsive logo using CSS variable theming | +| `CLAUDE.md` | Modified | Updated documentation | + +--- + +## 🎨 Visual & UX Impact + +### What Changed + +#### Navbar Logo + +The navbar now features a **responsive logo system**: + +- **Desktop (β‰₯640px):** Full branded SVG (containing icon and wordmark), automatically switching between light and dark variants via CSS variable +- **Mobile (<640px):** Compact icon-only logo for space efficiency + +This is an excellent UX improvementβ€”mobile users see a clean, uncluttered header whilst desktop users get full brand visibility. + +#### Sign-in Page + +| Element | Before | After | +|---------|--------|-------| +| Logo | Default Clerk logo | Full branded SVG with theme awareness | +| Title | "Sign in to [app name]" | "Sign in" | +| Subtitle | Default | "to continue to DevFlow" | +| Social buttons | "Continue with GitHub" | "GitHub" (cleaner) | +| Header alignment | Centred | Left-aligned | +| Primary button | Default Clerk | Orange gradient matching brand | + +#### Sign-up Page + +| Element | Before | After | +|---------|--------|-------| +| Logo | Default Clerk logo | Branded icon (no text) | +| Title | Default | Default (unchanged) | +| Subtitle | Default | Default (unchanged) | +| Primary button | Default Clerk | Orange gradient matching brand | + +### Design Improvements βœ… + +1. **Brand consistency** β€” Orange gradient buttons match the DevOverflow brand +2. **Responsive design** β€” Logo adapts appropriately to viewport size +3. **Cleaner OAuth buttons** β€” Simplified "GitHub" / "Google" text +4. **Professional appearance** β€” Left-aligned header on sign-in feels more polished + +--- + +## πŸ”§ Technical Evaluation + +### Tailwind CSS v4.1 Theming + +#### βœ… What Works Well + +**CSS Variable Dark Mode Pattern** + +```css +/* globals.css */ +:root { + --logo-full-themed: url("/images/logo-light.svg"); +} +.dark { + --logo-full-themed: url("/images/logo-dark.svg"); +} +``` + +This follows Tailwind v4's recommended approach for theme-dependent assets. The variable automatically switches based on the `.dark` class. + +**Arbitrary Value Syntax** + +```tsx + +``` + +The `bg-(image:--logo-full-themed)` syntax correctly uses Tailwind v4's arbitrary value notation to reference the CSS variable. + +**Responsive Utilities** + +```tsx + {/* Mobile: icon only */} + {/* Desktop: full logo */} +``` + +Proper mobile-first responsive approach. + +#### ℹ️ Note on Dual Theming Approach + +**CSS Variable for Non-Clerk Components** +The `--logo-full-themed` variable in `globals.css` is the centralised source for themed logos across the app. Currently only the navbar uses it, but this is forward-thinking β€” future components (headers, footers, email templates, etc.) can reference this single variable. + +Clerk components require a parallel JavaScript approach due to API limitations (`logoImageUrl` must be a static URL string). This isn't duplication β€” it's a necessary accommodation. The CSS variable remains the canonical theming source for the broader application. + +### Clerk Integration + +#### βœ… What Works Well + +**Appearance Prop Usage** + +```tsx +// clerk-signin.tsx +appearance={{ + layout: { logoImageUrl: logoUrl }, + elements: { + header: "items-start", + logoBox: "!justify-start", + headerTitle: "text-left", + headerSubtitle: "text-left", + }, +}} +``` + +This correctly uses Clerk's `appearance` prop with both `layout` and `elements` properties. + +**Localization Implementation** + +```tsx +// clerk-provider.tsx +localization={{ + socialButtonsBlockButton: "{{provider|titleize}}", + signIn: { + start: { + title: "Sign in", + subtitle: "to continue to DevFlow", + }, + }, +}} +``` + +Proper use of Clerk's experimental localization API to customise text. The `{{provider|titleize}}` template correctly formats OAuth provider names. + +**Theme Detection for Logo** + +```tsx +const { resolvedTheme } = useTheme(); +const logoUrl = resolvedTheme === "light" + ? "/images/logo-light.svg" + : "/images/logo-dark.svg"; +``` + +Since Clerk's `logoImageUrl` requires a static URL string and cannot use CSS variables, JavaScript theme detection is the correct approach. + +#### βœ… CSS Layer Configuration + +The `@layer` declaration is correctly positioned at the top of `globals.css` (before `@import "tailwindcss"`), ensuring proper cascade order. Combined with `cssLayerName: "clerk"` in ClerkProvider, Tailwind utilities cleanly override Clerk's default styles without requiring `!important` overrides. + +--- + +## ⚠️ Issues Found + +### 🟑 Medium + +#### ~~2. Inconsistent Logo Between Sign-in and Sign-up~~ *(Intentional)* + +| Page | Logo Type | +|------|-----------| +| Sign-in | Full branded SVG (`logo-light.svg`/`logo-dark.svg`), theme-aware | +| Sign-up | Icon only (`site-logo.svg`), static | + +~~Users moving between these pages will experience inconsistent branding.~~ + +**Note:** This is intentional branding β€” different logo variants serve different UX purposes. The full logo on sign-in reinforces brand recognition for returning users, whilst the simplified icon on sign-up provides a cleaner, less cluttered experience for new users during registration. The icon (`site-logo.svg`) displays correctly on both light and dark backgrounds, so theme awareness is not required. + +#### ~~3. Inconsistent Localization~~ *(Fixed)* + +| Page | Title | Subtitle | +|------|-------|----------| +| Sign-in | "Sign in" (custom) | "to continue to DevFlow" (custom) | +| Sign-up | ~~"Create your account" (default)~~ β†’ "Sign up" | ~~"Welcome! Please fill in..." (default)~~ β†’ "to continue to DevFlow" | + +~~The sign-up page uses Clerk's default text whilst sign-in has custom branding.~~ + +**Resolution:** Added `signUp.start` localization to `ClerkProvider`. + +#### 4. ~~CSS Variable Defined But Not Utilised in Clerk Components~~ *(Not an issue)* + +The `--logo-full-themed` CSS variable is intentionally designed for non-Clerk components. Clerk's API requires static URLs, so JavaScript theme detection is necessary there. The CSS variable serves as the canonical theming source for the broader app and will be used by future components beyond the navbar. + +### 🟒 Minor + +#### ~~5. Removed Dynamic Rendering~~ *(Correct)* + +The pages previously used `await connection()` for dynamic rendering: + +```tsx +// Before +export default async function SignInPage() { + await connection(); + // ... +} +``` + +~~This was removed. Whilst likely intentional (the new wrapper components handle their own rendering), it's worth confirming this doesn't affect caching or SSR behaviour.~~ + +**Resolution:** Removing `await connection()` is correct and follows Next.js best practices. The `connection()` function forces dynamic rendering at request time, which was unnecessary for these pages because: + +1. **Clerk components are client-side** β€” `` and `` are client components that don't require server-side dynamic rendering +2. **No runtime data needed** β€” These pages don't access `cookies()`, `headers()`, or other request-time APIs +3. **Performance improvement** β€” Removing it allows Next.js to statically prerender the page shell, improving initial load performance + +The page wrapper is now correctly a simple synchronous function that renders a client component. + +--- + +## πŸ’‘ Recommendations + +### ~~Priority 1: Add Sign-up Localization~~ *(Implemented)* + +Added sign-up localization to ClerkProvider: + +```tsx +localization={{ + // ... existing + signUp: { + start: { + title: "Sign up", + subtitle: "to continue to DevFlow", + }, + }, +}} +``` + +### ~~Priority 2: Centralise Logo Paths~~ *(Not needed)* + +~~The logo URLs (`/images/logo-light.svg`, `/images/logo-dark.svg`) are defined in multiple places. Consider a shared constants file that both the CSS variable comments and JS code reference.~~ + +**Resolution:** After review, centralising logo paths provides minimal benefit: + +1. **CSS cannot import JS constants** β€” `globals.css` would still need hardcoded values +2. **Only 3 logo files** β€” low maintenance burden +3. **Paths rarely change** β€” the risk of drift is minimal +4. **CSS variable is the documented canonical source** β€” already established in Issue #4 + +A constants file would only benefit the JS side whilst adding abstraction overhead. The current pragmatic approach (CSS variable for non-Clerk, JS strings for Clerk) is appropriate. + +--- + +## πŸ“Ž Appendix: Direct Answers + +### Q1: What impact has he had on user experience, how has the design changed? + +**Positive impacts:** + +- βœ… Brand consistency improved with custom logos and orange gradient buttons +- βœ… Responsive navbar logo adapts well to mobile/desktop +- βœ… Cleaner OAuth buttons ("GitHub" instead of "Continue with GitHub") +- βœ… Professional left-aligned header on sign-in page +- βœ… Custom "to continue to DevFlow" messaging adds brand personality +- βœ… Improved page load performance by removing unnecessary `await connection()` + +**Negative impacts:** + +- ~~⚠️ Inconsistent localization between sign-in and sign-up pages~~ *(Fixed)* + +**Overall:** The changes show clear intent to improve branding and UX. A solid improvement to the authentication experience. + +--- + +### Q2: Did he follow good centralised theming practice with Tailwind 4.1? + +**Partially yes:** + +- βœ… CSS variables defined in `:root` and `.dark` selectors (correct pattern) +- βœ… Arbitrary value syntax `bg-(image:--logo-full-themed)` used correctly +- βœ… Responsive utilities follow mobile-first approach + +**Areas for improvement:** + +- βœ… CSS layers properly configured (`cssLayerName: "clerk"` and `@layer` declaration) +- βœ… No `!important` overrides needed β€” correct layer ordering ensures clean cascade + +**Note:** The dual approach (CSS variable for non-Clerk, JS for Clerk) is a reasonable accommodation for Clerk's API limitation, not a flaw. The CSS variable is the canonical source for future components. + +**Verdict:** Good foundational understanding of Tailwind v4 theming. The dual approach for logos is a pragmatic solution to Clerk's constraints. + +--- + +### Q3: Has he used Clerk best practices as advised in the official documentation? + +**What's done well:** + +- βœ… `appearance.layout.logoImageUrl` used correctly for custom logos +- βœ… `appearance.elements` used for fine-grained styling +- βœ… `localization` prop used for custom text +- βœ… JavaScript theme detection for logos (since CSS variables don't work with `logoImageUrl`) +- βœ… ClerkProvider wraps the app and applies global appearance settings +- βœ… Correctly removed `await connection()` β€” Clerk components are client-side, so forcing dynamic rendering was unnecessary + +**What's missing or incorrect:** + +- βœ… `cssLayerName` property correctly configured for Tailwind v4 +- βœ… Localization applied to both sign-in and sign-up +- βœ… CSS layer ordering correct β€” no `!important` overrides needed + +**Verdict:** Demonstrates good familiarity with Clerk's customisation APIs and proper Tailwind v4 configuration. + +--- + +### Q4: Any recommendations that are important improvements? + +**Should fix:** + +1. ~~🟑 **Add Clerk localization for sign-up**~~ *(Fixed)* β€” Added "Sign up" / "to continue to DevFlow" + +**Nice to have:** + +2. ~~🟒 **Centralise logo paths**~~ *(Not needed)* β€” CSS cannot import JS constants, so a shared file would only partially help. Current approach is pragmatic. + +--- + +*Report generated by Claude Code evaluation* diff --git a/x_docs/own/secrets-reference.md b/x_docs/own/secrets-reference.md new file mode 100644 index 0000000..cdad998 --- /dev/null +++ b/x_docs/own/secrets-reference.md @@ -0,0 +1,141 @@ +# Environment Variables + +Quick reference for all environment variables and secrets across Local, Vercel, and GitHub. + +## Quick Reference Commands + +| Platform | Command | +|----------|---------| +| Local | `cat .env.local` | +| Vercel | `vercel env ls` | +| GitHub | `gh secret list` | + +## Variables by Platform + +### Local (`.env.local`) + +| Variable | Value | Purpose | +|----------|-------|---------| +| `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` | `pk_test_YXdha2Utb3dsLTYzLmNsZXJrLmFjY291bnRzLmRldiQ` | Clerk client-side key | +| `CLERK_PUBLISHABLE_KEY` | `pk_test_YXdha2Utb3dsLTYzLmNsZXJrLmFjY291bnRzLmRldiQ` | Same key for @clerk/testing | +| `CLERK_SECRET_KEY` | `sk_test_...` | Clerk server-side key | +| `E2E_TEST_EMAIL` | `test+clerk_test@example.com` | Test user email | +| `E2E_TEST_PASSWORD` | `********` | Test user password | +| `E2E_TEST_OTP` | `424242` | Test OTP code | +| `NEXT_PUBLIC_CLERK_SIGN_IN_URL` | `/sign-in` | Custom sign-in page route | +| `NEXT_PUBLIC_CLERK_SIGN_UP_URL` | `/sign-up` | Custom sign-up page route | +| `NEXT_PUBLIC_CLERK_SIGN_IN_FALLBACK_REDIRECT_URL` | `/` | Redirect after sign-in (fallback) | +| `NEXT_PUBLIC_CLERK_SIGN_UP_FALLBACK_REDIRECT_URL` | `/` | Redirect after sign-up (fallback) | + +### Vercel + +| Variable | Value | Production | Preview | Development | Sensitive? | +|----------|-------|:----------:|:-------:|:-----------:|:----------:| +| `CLERK_SECRET_KEY` | `sk_test_...` | Yes | Yes | - | **Yes** | +| `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` | `pk_test_YXdha2Utb3dsLTYzLmNsZXJrLmFjY291bnRzLmRldiQ` | Yes | Yes | Yes | No | +| `CLERK_PUBLISHABLE_KEY` | `pk_test_YXdha2Utb3dsLTYzLmNsZXJrLmFjY291bnRzLmRldiQ` | Yes | Yes | Yes | No | +| `NEXT_PUBLIC_CLERK_SIGN_IN_URL` | `/sign-in` | Yes | Yes | Yes | No | +| `NEXT_PUBLIC_CLERK_SIGN_UP_URL` | `/sign-up` | Yes | Yes | Yes | No | +| `NEXT_PUBLIC_CLERK_SIGN_IN_FALLBACK_REDIRECT_URL` | `/` | Yes | Yes | Yes | No | +| `NEXT_PUBLIC_CLERK_SIGN_UP_FALLBACK_REDIRECT_URL` | `/` | Yes | Yes | Yes | No | + +> **Note:** Only `CLERK_SECRET_KEY` needs to be Sensitive. All `NEXT_PUBLIC_*` variables are exposed to the browser anyway, and publishable keys are designed to be public. Using "Plain text" for non-secrets makes configuration easier to audit in the Vercel dashboard. + +### GitHub Secrets + +| Secret | Purpose | +|--------|---------| +| `CLERK_PUBLISHABLE_KEY` | E2E tests (@clerk/testing) | +| `CLERK_SECRET_KEY` | E2E tests (@clerk/testing) | +| `E2E_TEST_EMAIL` | Test user credentials | +| `E2E_TEST_PASSWORD` | Test user credentials | +| `E2E_TEST_OTP` | Test user OTP code | +| `VERCEL_AUTOMATION_BYPASS_SECRET` | Vercel preview deployment automation | + +## Variable Reference + +### Clerk API Keys + +| Variable | Description | +|----------|-------------| +| `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` | Client-side key for Next.js (browser-exposed, starts with `pk_test_` or `pk_live_`) | +| `CLERK_PUBLISHABLE_KEY` | Same value as above, required by `@clerk/testing` package | +| `CLERK_SECRET_KEY` | Server-side key (starts with `sk_test_` or `sk_live_`). Never expose publicly. | + +### Clerk Routes + +| Variable | Description | +|----------|-------------| +| `NEXT_PUBLIC_CLERK_SIGN_IN_URL` | Path to your custom sign-in page. Without this, Clerk redirects to the Account Portal. | +| `NEXT_PUBLIC_CLERK_SIGN_UP_URL` | Path to your custom sign-up page. Without this, Clerk redirects to the Account Portal. | +| `NEXT_PUBLIC_CLERK_SIGN_IN_FALLBACK_REDIRECT_URL` | Where to redirect after sign-in when no `redirect_url` query param exists | +| `NEXT_PUBLIC_CLERK_SIGN_UP_FALLBACK_REDIRECT_URL` | Where to redirect after sign-up when no `redirect_url` query param exists | + +### E2E Test Credentials + +| Variable | Description | +|----------|-------------| +| `E2E_TEST_EMAIL` | Test user email. Use `+clerk_test` pattern (e.g., `test+clerk_test@example.com`) to enable test mode. | +| `E2E_TEST_PASSWORD` | Test user password | +| `E2E_TEST_OTP` | OTP code for verification. The `+clerk_test` email pattern accepts `424242` as valid OTP. | + +### Automation + +| Variable | Description | +|----------|-------------| +| `VERCEL_AUTOMATION_BYPASS_SECRET` | Used by GitHub Actions to trigger Vercel preview deployment tests | + +--- + +## E2E Testing Setup + +### How @clerk/testing Works + +The `@clerk/testing` package enables E2E tests to authenticate without triggering bot detection: + +1. `clerkSetup()` runs in global setup and obtains a Testing Token +2. `setupClerkTestingToken()` injects the token in each test +3. Clerk's bot detection is automatically bypassed + +### Creating a Clerk Test User + +1. Go to **Clerk Dashboard** > **Users** > **Create user** +2. Set email using the `+clerk_test` pattern (e.g., `test+clerk_test@example.com`) +3. Set a password +4. The `+clerk_test` pattern enables test mode, which accepts `424242` as the OTP code + +### Running E2E Tests + +```bash +npm run test:e2e # Run all E2E tests +npm run test:e2e:headed # Run with visible browser +npx playwright test auth # Run only auth tests +``` + +### Vercel Preview Deployment Flow + +When Vercel finishes deploying a preview, it triggers a GitHub Action that runs Playwright tests against your live preview URL: + +1. You push code > Vercel deploys to a preview URL +2. Vercel notifies GitHub via `repository_dispatch` event +3. GitHub Actions runs Playwright, which connects to your preview URL and tests it +4. Results are reported back to your PR + +**Note:** Test credentials (`E2E_TEST_*`) are stored in GitHub Secrets, not Vercel. Playwright runs on GitHub Actions and uses those secrets when it connects to your preview URL. + +### Troubleshooting + +#### "Bot traffic detected" error + +- Ensure `clerkSetup()` runs in global setup before tests +- Verify `CLERK_PUBLISHABLE_KEY` and `CLERK_SECRET_KEY` are set + +#### Tests fail in CI but pass locally + +- Check all required secrets are configured in GitHub Actions +- Verify secrets match your local `.env.local` values + +#### Tests timeout waiting for elements + +- Clerk components load asynchronously; use Playwright's auto-waiting +- If issues persist, add explicit waits for Clerk elements diff --git a/x_docs/own/setup-clerk-secrets.md b/x_docs/own/setup-clerk-secrets.md deleted file mode 100644 index 5e2101e..0000000 --- a/x_docs/own/setup-clerk-secrets.md +++ /dev/null @@ -1,114 +0,0 @@ -# E2E Authentication Tests Setup - -This guide explains how to configure environment variables for running Clerk authentication tests locally, in GitHub Actions, and on Vercel preview deployments. - -## How It Works - -The auth smoke test uses `@clerk/testing` which: - -1. Obtains a Testing Token via `clerkSetup()` in global setup -2. Injects the token via `setupClerkTestingToken()` in each test -3. Bypasses Clerk's bot detection automatically - -## Environment Variables - -| Variable | Description | -|----------|-------------| -| `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` | Clerk publishable key for Next.js (starts with `pk_test_`) | -| `CLERK_PUBLISHABLE_KEY` | Same key, used by `@clerk/testing` for E2E tests | -| `CLERK_SECRET_KEY` | Clerk secret key (starts with `sk_test_`) | -| `E2E_TEST_EMAIL` | Test user email address | -| `E2E_TEST_PASSWORD` | Test user password | -| `E2E_TEST_OTP` | OTP code for new device verification (default: `424242`) | - -## Local Development - -Ensure `.env.local` contains: - -```bash -# Clerk - Next.js requires NEXT_PUBLIC_ prefix for client-side -NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_... -CLERK_PUBLISHABLE_KEY=pk_test_... # Same value, needed by @clerk/testing -CLERK_SECRET_KEY=sk_test_... - -# E2E Test User -E2E_TEST_EMAIL=test+clerk_test@example.com -E2E_TEST_PASSWORD=Horse1234! -E2E_TEST_OTP=424242 -``` - -Run tests: - -```bash -npm run test:e2e # Run all E2E tests -npm run test:e2e:headed # Run with visible browser -npx playwright test auth # Run only auth tests -``` - -## GitHub Actions - -Add these secrets to your repository: - -1. Go to **Settings** β†’ **Secrets and variables** β†’ **Actions** -2. Click **New repository secret** for each: - -| Secret | Value | -|--------|-------| -| `CLERK_PUBLISHABLE_KEY` | `pk_test_...` | -| `CLERK_SECRET_KEY` | `sk_test_...` | -| `E2E_TEST_EMAIL` | `test+clerk_test@example.com` | -| `E2E_TEST_PASSWORD` | `Horse1234!` | -| `E2E_TEST_OTP` | `424242` | - -The workflows (`.github/workflows/test-e2e.yml` and `test-e2e-vercel.yml`) are already configured to use these secrets. - -## Vercel Preview Deployments - -When Vercel finishes deploying a preview, it triggers a GitHub Action that runs Playwright tests **against your live preview URL**. This verifies your deployed app works before you merge. - -**How it works:** - -1. You push code β†’ Vercel deploys to a preview URL -2. Vercel notifies GitHub via `repository_dispatch` event -3. GitHub Actions runs Playwright, which connects to your preview URL and tests it -4. Results are reported back to your PR - -**Note:** Test credentials (`E2E_TEST_*`) are stored in GitHub Secrets, not Vercel. Playwright runs on GitHub Actions and uses those secrets when it connects to your preview URL over the network. - -**Required setup:** - -1. **GitHub Secrets** (same as above) - Test credentials used by Playwright -2. **Vercel Environment Variables** - Clerk keys needed for your deployed app to function: - -| Variable | Environment | -|----------|-------------| -| `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` | Preview (and Production) | -| `CLERK_SECRET_KEY` | Preview (and Production) | - -You likely already have these configured. The `E2E_TEST_*` variables are NOT needed on Vercel β€” Playwright uses GitHub Secrets when it connects to your preview URL. - -## Creating a Clerk Test User - -If you need to create a new test user: - -1. Go to **Clerk Dashboard** β†’ **Users** β†’ **Create user** -2. Set email using the `+clerk_test` pattern (e.g., `test+clerk_test@example.com`) -3. Set a password -4. The `+clerk_test` email pattern enables test mode, which accepts `424242` as the OTP code if needed - -## Troubleshooting - -### "Bot traffic detected" error - -- Ensure `clerkSetup()` runs in global setup before tests -- Verify `CLERK_PUBLISHABLE_KEY` and `CLERK_SECRET_KEY` are set - -### Tests fail in CI but pass locally - -- Check all required secrets are configured in GitHub Actions -- Verify secrets match your local `.env.local` values - -### Tests timeout waiting for elements - -- Clerk components load asynchronously; use Playwright's auto-waiting -- If issues persist, add explicit waits for Clerk elements