Finish the CrawlerX rebrand: theme tokens, sign-in page, stray logo refs
The Oct-era rebrand commit swapped the sidebar/app-shell logo and most daisyUI component colors, but missed several spots: - app.css's "crawlerx" / "crawlerx-dark" theme tokens were still the old MetatronCube blue (#3779b9) instead of the brand guide's teal (#0E6E6A). Every daisyUI-token-based component (most of the app) now gets the correct color with this one change. - AuthPage.tsx (sign-in/sign-up) was untouched by the token system: a mountain-climber stock photo background, "Metatroncube / Solutions" wordmark, blue/cyan gradients, generic value props, and a stray alt="Metatroncube" on the logo. Replaced with the brand gradient, the CrawlerX mark, on-brand copy and value props, and the real color tokens instead of hardcoded Tailwind blue/cyan classes. - Four more components (onboarding chat, post-signup onboarding, the OAuth consent screen, the subscribe page) still pointed their logo <img> at /transparent-logo.png instead of /crawlerx-mark.png. - PricingGraphics.tsx (the decorative cube/chart illustration on the subscribe page) had ~17 hardcoded MetatronCube-blue hex values; remapped the whole palette to the CrawlerX teal family. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
336db032a4
commit
0e8bfa1fa1
@ -136,9 +136,13 @@ export function AuthInputField({
|
|||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
type={
|
type={
|
||||||
showPasswordToggle ? (isPasswordVisible ? "text" : "password") : type
|
showPasswordToggle
|
||||||
|
? isPasswordVisible
|
||||||
|
? "text"
|
||||||
|
: "password"
|
||||||
|
: type
|
||||||
}
|
}
|
||||||
className="w-full h-11 sm:h-12 bg-slate-50/90 hover:bg-slate-50 focus:bg-white border border-slate-200 rounded-xl pl-10 pr-10 text-sm text-slate-900 placeholder:text-slate-400 focus:border-blue-600 focus:ring-4 focus:ring-blue-500/10 transition-all outline-none disabled:opacity-60"
|
className="w-full h-11 sm:h-12 bg-slate-50/90 hover:bg-slate-50 focus:bg-white border border-slate-200 rounded-xl pl-10 pr-10 text-sm text-slate-900 placeholder:text-slate-400 focus:border-primary focus:ring-4 focus:ring-primary/10 transition-all outline-none disabled:opacity-60"
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
@ -184,7 +188,7 @@ export function AuthSubmitButton({
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={disabled || isSubmitting}
|
disabled={disabled || isSubmitting}
|
||||||
className="w-full h-11 sm:h-12 rounded-xl bg-gradient-to-r from-blue-600 to-blue-700 hover:from-blue-700 hover:to-blue-800 active:scale-[0.99] text-white font-medium shadow-lg shadow-blue-600/25 transition-all flex items-center justify-center gap-2 text-sm disabled:opacity-60 disabled:cursor-not-allowed cursor-pointer"
|
className="w-full h-11 sm:h-12 rounded-xl bg-gradient-to-r from-primary to-teal-700 hover:brightness-110 active:scale-[0.99] text-primary-content font-medium shadow-lg shadow-primary/25 transition-all flex items-center justify-center gap-2 text-sm disabled:opacity-60 disabled:cursor-not-allowed cursor-pointer"
|
||||||
>
|
>
|
||||||
{isSubmitting ? (
|
{isSubmitting ? (
|
||||||
<span className="loading loading-spinner loading-sm" />
|
<span className="loading loading-spinner loading-sm" />
|
||||||
@ -223,11 +227,11 @@ export function AuthPageCard({
|
|||||||
footer?: React.ReactNode;
|
footer?: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="w-full max-w-[440px] bg-white/95 backdrop-blur-xl rounded-[28px] p-7 sm:p-9 shadow-[0_20px_60px_-15px_rgba(8,112,184,0.15),0_2px_20px_rgba(0,0,0,0.06)] border border-white/80 transition-all">
|
<div className="w-full max-w-[440px] bg-white/95 backdrop-blur-xl rounded-[28px] p-7 sm:p-9 shadow-[0_20px_60px_-15px_rgba(14,110,106,0.18),0_2px_20px_rgba(0,0,0,0.06)] border border-white/80 transition-all">
|
||||||
<div className="text-center space-y-1.5 mb-6">
|
<div className="text-center space-y-1.5 mb-6">
|
||||||
<img
|
<img
|
||||||
src="/transparent-logo.png"
|
src="/crawlerx-mark.png"
|
||||||
alt="Metatroncube"
|
alt="CrawlerX"
|
||||||
className="mx-auto size-11 object-contain drop-shadow-sm"
|
className="mx-auto size-11 object-contain drop-shadow-sm"
|
||||||
/>
|
/>
|
||||||
<h2 className="text-2xl font-bold tracking-tight text-slate-900">
|
<h2 className="text-2xl font-bold tracking-tight text-slate-900">
|
||||||
@ -242,7 +246,9 @@ export function AuthPageCard({
|
|||||||
|
|
||||||
<div className="space-y-3.5">{children}</div>
|
<div className="space-y-3.5">{children}</div>
|
||||||
|
|
||||||
{footer ? <div className="mt-5 space-y-3 text-center">{footer}</div> : null}
|
{footer ? (
|
||||||
|
<div className="mt-5 space-y-3 text-center">{footer}</div>
|
||||||
|
) : null}
|
||||||
|
|
||||||
<div className="flex items-center justify-center gap-1.5 text-xs text-slate-400 pt-4 mt-2">
|
<div className="flex items-center justify-center gap-1.5 text-xs text-slate-400 pt-4 mt-2">
|
||||||
<Lock className="size-3.5 text-slate-400 shrink-0" />
|
<Lock className="size-3.5 text-slate-400 shrink-0" />
|
||||||
@ -261,7 +267,7 @@ export function InviteOnlyCard({ redirectTo }: { redirectTo: string }) {
|
|||||||
<Link
|
<Link
|
||||||
to="/sign-in"
|
to="/sign-in"
|
||||||
search={getSignInSearch(redirectTo)}
|
search={getSignInSearch(redirectTo)}
|
||||||
className="w-full h-11 sm:h-12 rounded-xl bg-gradient-to-r from-blue-600 to-blue-700 hover:from-blue-700 hover:to-blue-800 text-white font-medium shadow-md shadow-blue-600/25 transition-all flex items-center justify-center gap-2 text-sm"
|
className="w-full h-11 sm:h-12 rounded-xl bg-gradient-to-r from-primary to-teal-700 hover:brightness-110 text-primary-content font-medium shadow-md shadow-primary/25 transition-all flex items-center justify-center gap-2 text-sm"
|
||||||
>
|
>
|
||||||
<span>Back to sign in</span>
|
<span>Back to sign in</span>
|
||||||
<ArrowRight className="size-4" />
|
<ArrowRight className="size-4" />
|
||||||
@ -273,18 +279,18 @@ export function InviteOnlyCard({ redirectTo }: { redirectTo: string }) {
|
|||||||
const VALUE_PROPS = [
|
const VALUE_PROPS = [
|
||||||
{
|
{
|
||||||
icon: Zap,
|
icon: Zap,
|
||||||
title: "Get Started Quickly",
|
title: "Live Site Audits",
|
||||||
desc: "Set up your account in just a few simple steps.",
|
desc: "120+ technical checks, prioritized by what actually moves rankings.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: ShieldCheck,
|
icon: ShieldCheck,
|
||||||
title: "Your Data is Safe",
|
title: "Review Before It Ships",
|
||||||
desc: "Enterprise-grade security to keep your information protected.",
|
desc: "AI-drafted fixes wait for your approval — nothing publishes itself.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: TrendingUp,
|
icon: TrendingUp,
|
||||||
title: "Build for What's Next",
|
title: "Client-Ready Reporting",
|
||||||
desc: "Powerful tools and flexible features to help you grow.",
|
desc: "Rank movement and traffic, in language your clients understand.",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -301,10 +307,10 @@ export function AuthPageShell({
|
|||||||
};
|
};
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen w-full relative flex flex-col lg:flex-row bg-[#020617] text-slate-900 selection:bg-blue-500 selection:text-white overflow-x-hidden">
|
<div className="min-h-screen w-full relative flex flex-col lg:flex-row bg-[#0F161C] text-slate-900 selection:bg-primary selection:text-white overflow-x-hidden">
|
||||||
<div
|
<div
|
||||||
className="absolute inset-0 bg-cover bg-center pointer-events-none z-0 opacity-90 transition-opacity"
|
className="absolute inset-0 pointer-events-none z-0 opacity-95 transition-opacity"
|
||||||
style={{ backgroundImage: `url('/auth-bg.jpg')` }}
|
style={{ backgroundImage: "var(--brand-gradient)" }}
|
||||||
/>
|
/>
|
||||||
<div className="absolute inset-y-0 left-0 w-full lg:w-[50%] bg-gradient-to-r from-slate-950/95 via-slate-950/80 to-transparent pointer-events-none z-0" />
|
<div className="absolute inset-y-0 left-0 w-full lg:w-[50%] bg-gradient-to-r from-slate-950/95 via-slate-950/80 to-transparent pointer-events-none z-0" />
|
||||||
|
|
||||||
@ -312,47 +318,44 @@ export function AuthPageShell({
|
|||||||
<div className="lg:w-[46%] xl:w-[44%] p-6 sm:p-10 lg:p-14 xl:p-16 flex flex-col justify-between z-10 text-white min-h-[auto] lg:min-h-screen">
|
<div className="lg:w-[46%] xl:w-[44%] p-6 sm:p-10 lg:p-14 xl:p-16 flex flex-col justify-between z-10 text-white min-h-[auto] lg:min-h-screen">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<img
|
<img
|
||||||
src="/transparent-logo.png"
|
src="/crawlerx-mark.png"
|
||||||
alt="Metatroncube"
|
alt="CrawlerX"
|
||||||
className="size-10 object-contain drop-shadow-md"
|
className="size-10 object-contain drop-shadow-md"
|
||||||
/>
|
/>
|
||||||
<div>
|
<div className="font-bold text-lg tracking-tight text-white leading-none">
|
||||||
<div className="font-bold text-lg tracking-tight text-white leading-none">
|
Crawler<span className="text-accent">X</span>
|
||||||
Metatroncube
|
|
||||||
</div>
|
|
||||||
<div className="text-[11px] font-medium text-blue-200/70 tracking-wider uppercase mt-1">
|
|
||||||
Solutions
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="my-auto py-8 lg:py-0">
|
<div className="my-auto py-8 lg:py-0">
|
||||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-blue-500/15 border border-blue-400/30 text-blue-300 text-[11px] font-semibold tracking-wider uppercase mb-5 backdrop-blur-sm shadow-sm">
|
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-primary/15 border border-accent/30 text-accent text-[11px] font-semibold tracking-wider uppercase mb-5 backdrop-blur-sm shadow-sm">
|
||||||
<span className="size-1.5 rounded-full bg-cyan-400 animate-pulse" />
|
<span className="size-1.5 rounded-full bg-accent animate-pulse" />
|
||||||
JOIN OUR PLATFORM
|
WEBSITE INTELLIGENCE THAT ACTS
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 className="text-3xl sm:text-4xl xl:text-5xl font-extrabold tracking-tight text-white leading-[1.15]">
|
<h1 className="text-3xl sm:text-4xl xl:text-5xl font-extrabold tracking-tight text-white leading-[1.15]">
|
||||||
Build something
|
Find it. Fix it.
|
||||||
<br />
|
<br />
|
||||||
<span className="bg-gradient-to-r from-cyan-400 via-sky-300 to-blue-400 bg-clip-text text-transparent">
|
<span className="bg-gradient-to-r from-accent via-teal-300 to-primary bg-clip-text text-transparent">
|
||||||
exceptional.
|
Prove it.
|
||||||
</span>
|
</span>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p className="mt-4 text-slate-300/85 text-sm xl:text-base leading-relaxed max-w-md font-normal">
|
<p className="mt-4 text-slate-300/85 text-sm xl:text-base leading-relaxed max-w-md font-normal">
|
||||||
Create your account and get started in minutes. Join a growing
|
Sign in to audit your sites, review AI-drafted fixes and report
|
||||||
community of creators, builders and innovators.
|
progress your clients actually understand.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="mt-8 space-y-4 max-w-md">
|
<div className="mt-8 space-y-4 max-w-md">
|
||||||
{VALUE_PROPS.map(({ icon: Icon, title, desc }) => (
|
{VALUE_PROPS.map(({ icon: Icon, title, desc }) => (
|
||||||
<div key={title} className="flex items-start gap-3.5">
|
<div key={title} className="flex items-start gap-3.5">
|
||||||
<div className="size-10 rounded-xl bg-blue-500/15 border border-blue-400/25 flex items-center justify-center shrink-0 shadow-inner">
|
<div className="size-10 rounded-xl bg-primary/15 border border-accent/25 flex items-center justify-center shrink-0 shadow-inner">
|
||||||
<Icon className="size-5 text-blue-400" />
|
<Icon className="size-5 text-accent" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-sm font-semibold text-white">{title}</div>
|
<div className="text-sm font-semibold text-white">
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
<div className="text-xs text-slate-400 mt-0.5 leading-relaxed">
|
<div className="text-xs text-slate-400 mt-0.5 leading-relaxed">
|
||||||
{desc}
|
{desc}
|
||||||
</div>
|
</div>
|
||||||
@ -361,10 +364,10 @@ export function AuthPageShell({
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-10 font-['Caveat',cursive] text-2xl text-blue-200/90 leading-snug tracking-wide italic select-none">
|
<div className="mt-10 font-['Caveat',cursive] text-2xl text-accent/90 leading-snug tracking-wide italic select-none">
|
||||||
"More than software,
|
"Built for agencies who bill
|
||||||
<br />
|
<br />
|
||||||
it's a better tomorrow."
|
by results, not by hours."
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -380,7 +383,7 @@ export function AuthPageShell({
|
|||||||
<Link
|
<Link
|
||||||
to={topLink.to}
|
to={topLink.to}
|
||||||
search={topLink.search}
|
search={topLink.search}
|
||||||
className="text-blue-600 hover:text-blue-700 font-semibold hover:underline flex items-center gap-1 transition-colors"
|
className="text-primary hover:brightness-90 font-semibold hover:underline flex items-center gap-1 transition-colors"
|
||||||
>
|
>
|
||||||
<span>{topLink.linkText}</span>
|
<span>{topLink.linkText}</span>
|
||||||
<ArrowRight className="size-3.5" />
|
<ArrowRight className="size-3.5" />
|
||||||
@ -389,7 +392,9 @@ export function AuthPageShell({
|
|||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-full my-auto flex justify-center py-4">{children}</div>
|
<div className="w-full my-auto flex justify-center py-4">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="w-full flex justify-end pb-2 sm:pb-4 pt-4">
|
<div className="w-full flex justify-end pb-2 sm:pb-4 pt-4">
|
||||||
<div className="flex items-center gap-2 text-[10px] sm:text-[11px] font-semibold tracking-widest text-slate-400/80 uppercase select-none">
|
<div className="flex items-center gap-2 text-[10px] sm:text-[11px] font-semibold tracking-widest text-slate-400/80 uppercase select-none">
|
||||||
|
|||||||
@ -15,28 +15,59 @@ import {
|
|||||||
export function CrawlerXLogo() {
|
export function CrawlerXLogo() {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-3 select-none">
|
<div className="flex items-center gap-3 select-none">
|
||||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" className="shrink-0 drop-shadow-sm">
|
<svg
|
||||||
{/* Top facet - Cyan / Ice Blue (#4faede) */}
|
width="40"
|
||||||
|
height="40"
|
||||||
|
viewBox="0 0 40 40"
|
||||||
|
fill="none"
|
||||||
|
className="shrink-0 drop-shadow-sm"
|
||||||
|
>
|
||||||
|
{/* Top facet - CrawlerX accent teal (#3fb6ae) */}
|
||||||
<path d="M20 4L34 12L20 20L6 12L20 4Z" fill="url(#cube-top-theme)" />
|
<path d="M20 4L34 12L20 20L6 12L20 4Z" fill="url(#cube-top-theme)" />
|
||||||
{/* Left facet - MetatronCube Blue (#3779b9) */}
|
{/* Left facet - CrawlerX primary teal (#0e6e6a) */}
|
||||||
<path d="M6 12L20 20V36L6 28V12Z" fill="url(#cube-left-theme)" />
|
<path d="M6 12L20 20V36L6 28V12Z" fill="url(#cube-left-theme)" />
|
||||||
{/* Right facet - Deep Navy (#0f1d34) */}
|
{/* Right facet - CrawlerX ink navy (#0f161c) */}
|
||||||
<path d="M20 20L34 12V28L20 36V20Z" fill="url(#cube-right-theme)" />
|
<path d="M20 20L34 12V28L20 36V20Z" fill="url(#cube-right-theme)" />
|
||||||
{/* Subtle highlights */}
|
{/* Subtle highlights */}
|
||||||
<path d="M20 20V36" stroke="rgba(255,255,255,0.25)" strokeWidth="1" />
|
<path d="M20 20V36" stroke="rgba(255,255,255,0.25)" strokeWidth="1" />
|
||||||
<path d="M6 12L20 20L34 12" stroke="rgba(255,255,255,0.35)" strokeWidth="0.8" />
|
<path
|
||||||
|
d="M6 12L20 20L34 12"
|
||||||
|
stroke="rgba(255,255,255,0.35)"
|
||||||
|
strokeWidth="0.8"
|
||||||
|
/>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="cube-top-theme" x1="6" y1="4" x2="34" y2="20" gradientUnits="userSpaceOnUse">
|
<linearGradient
|
||||||
<stop stopColor="#4faede" />
|
id="cube-top-theme"
|
||||||
<stop offset="1" stopColor="#3779b9" />
|
x1="6"
|
||||||
|
y1="4"
|
||||||
|
x2="34"
|
||||||
|
y2="20"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
>
|
||||||
|
<stop stopColor="#3fb6ae" />
|
||||||
|
<stop offset="1" stopColor="#0e6e6a" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
<linearGradient id="cube-left-theme" x1="6" y1="12" x2="20" y2="36" gradientUnits="userSpaceOnUse">
|
<linearGradient
|
||||||
<stop stopColor="#3779b9" />
|
id="cube-left-theme"
|
||||||
<stop offset="1" stopColor="#2563eb" />
|
x1="6"
|
||||||
|
y1="12"
|
||||||
|
x2="20"
|
||||||
|
y2="36"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
>
|
||||||
|
<stop stopColor="#0e6e6a" />
|
||||||
|
<stop offset="1" stopColor="#127b76" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
<linearGradient id="cube-right-theme" x1="20" y1="20" x2="34" y2="36" gradientUnits="userSpaceOnUse">
|
<linearGradient
|
||||||
<stop stopColor="#0f1d34" />
|
id="cube-right-theme"
|
||||||
<stop offset="1" stopColor="#091424" />
|
x1="20"
|
||||||
|
y1="20"
|
||||||
|
x2="34"
|
||||||
|
y2="36"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
>
|
||||||
|
<stop stopColor="#0f161c" />
|
||||||
|
<stop offset="1" stopColor="#0a1210" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
@ -72,7 +103,7 @@ export function DotGridMatrix({ className }: { className?: string }) {
|
|||||||
height="16"
|
height="16"
|
||||||
patternUnits="userSpaceOnUse"
|
patternUnits="userSpaceOnUse"
|
||||||
>
|
>
|
||||||
<circle cx="2" cy="2" r="1.5" fill="#3779b9" opacity="0.25" />
|
<circle cx="2" cy="2" r="1.5" fill="#0e6e6a" opacity="0.25" />
|
||||||
</pattern>
|
</pattern>
|
||||||
</defs>
|
</defs>
|
||||||
<rect width="140" height="90" fill="url(#dot-grid-theme)" />
|
<rect width="140" height="90" fill="url(#dot-grid-theme)" />
|
||||||
@ -91,7 +122,7 @@ export function Floating3DChartCard({ className }: { className?: string }) {
|
|||||||
<div className="relative rounded-3xl bg-white/95 p-5 shadow-[0_25px_60px_rgba(55,121,185,0.18),0_10px_25px_rgba(15,29,52,0.05)] border border-slate-100/90 backdrop-blur-xl -rotate-6 w-44 h-44 flex flex-col justify-between">
|
<div className="relative rounded-3xl bg-white/95 p-5 shadow-[0_25px_60px_rgba(55,121,185,0.18),0_10px_25px_rgba(15,29,52,0.05)] border border-slate-100/90 backdrop-blur-xl -rotate-6 w-44 h-44 flex flex-col justify-between">
|
||||||
{/* Top Row: "Grow Faster" Pill & Growth Arrow */}
|
{/* Top Row: "Grow Faster" Pill & Growth Arrow */}
|
||||||
<div className="flex items-center justify-between w-full">
|
<div className="flex items-center justify-between w-full">
|
||||||
<span className="px-2.5 py-0.5 rounded-full bg-[#3779b9] text-white text-[10px] font-bold shadow-xs tracking-wide">
|
<span className="px-2.5 py-0.5 rounded-full bg-[#0e6e6a] text-white text-[10px] font-bold shadow-xs tracking-wide">
|
||||||
Grow Faster
|
Grow Faster
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
@ -111,9 +142,16 @@ export function Floating3DChartCard({ className }: { className?: string }) {
|
|||||||
strokeLinejoin="round"
|
strokeLinejoin="round"
|
||||||
/>
|
/>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="theme-growth-arrow" x1="6" y1="24" x2="27" y2="9" gradientUnits="userSpaceOnUse">
|
<linearGradient
|
||||||
<stop stopColor="#4faede" />
|
id="theme-growth-arrow"
|
||||||
<stop offset="1" stopColor="#3779b9" />
|
x1="6"
|
||||||
|
y1="24"
|
||||||
|
x2="27"
|
||||||
|
y2="9"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
>
|
||||||
|
<stop stopColor="#3fb6ae" />
|
||||||
|
<stop offset="1" stopColor="#0e6e6a" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
@ -121,20 +159,36 @@ export function Floating3DChartCard({ className }: { className?: string }) {
|
|||||||
|
|
||||||
{/* 4 Rising Theme Blue Bars */}
|
{/* 4 Rising Theme Blue Bars */}
|
||||||
<div className="flex items-end gap-2.5 w-full justify-center pb-1">
|
<div className="flex items-end gap-2.5 w-full justify-center pb-1">
|
||||||
<div className="w-4 h-9 rounded-md bg-gradient-to-t from-[#0f1d34] to-[#1e3a66] shadow-xs" />
|
<div className="w-4 h-9 rounded-md bg-gradient-to-t from-[#0f161c] to-[#163b39] shadow-xs" />
|
||||||
<div className="w-4 h-14 rounded-md bg-gradient-to-t from-[#1e3a66] to-[#2563eb] shadow-xs" />
|
<div className="w-4 h-14 rounded-md bg-gradient-to-t from-[#163b39] to-[#127b76] shadow-xs" />
|
||||||
<div className="w-4 h-19 rounded-md bg-gradient-to-t from-[#2563eb] to-[#3779b9] shadow-xs" />
|
<div className="w-4 h-19 rounded-md bg-gradient-to-t from-[#127b76] to-[#0e6e6a] shadow-xs" />
|
||||||
<div className="w-4 h-24 rounded-md bg-gradient-to-t from-[#3779b9] to-[#4faede] shadow-md shadow-[#4faede]/30" />
|
<div className="w-4 h-24 rounded-md bg-gradient-to-t from-[#0e6e6a] to-[#3fb6ae] shadow-md shadow-[#3fb6ae]/30" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Small Plant in White Pot */}
|
{/* Small Plant in White Pot */}
|
||||||
<div className="absolute -bottom-3 -left-3 size-11 z-20">
|
<div className="absolute -bottom-3 -left-3 size-11 z-20">
|
||||||
<svg viewBox="0 0 44 44" fill="none">
|
<svg viewBox="0 0 44 44" fill="none">
|
||||||
<path d="M12 28L15 40H29L32 28H12Z" fill="#ffffff" stroke="#e2e8f0" strokeWidth="1.5" />
|
<path
|
||||||
<path d="M22 28C22 18 10 14 6 20C10 26 18 26 22 28Z" fill="#10b981" />
|
d="M12 28L15 40H29L32 28H12Z"
|
||||||
<path d="M22 28C22 16 34 12 38 18C34 24 26 24 22 28Z" fill="#059669" />
|
fill="#ffffff"
|
||||||
<path d="M22 28V12" stroke="#047857" strokeWidth="2" strokeLinecap="round" />
|
stroke="#e2e8f0"
|
||||||
|
strokeWidth="1.5"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M22 28C22 18 10 14 6 20C10 26 18 26 22 28Z"
|
||||||
|
fill="#10b981"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M22 28C22 16 34 12 38 18C34 24 26 24 22 28Z"
|
||||||
|
fill="#059669"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M22 28V12"
|
||||||
|
stroke="#047857"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -153,35 +207,41 @@ export function Floating3DSearchCard({ className }: { className?: string }) {
|
|||||||
<div className="relative rounded-3xl bg-white/95 p-4 shadow-[0_25px_60px_rgba(55,121,185,0.18),0_10px_25px_rgba(15,29,52,0.05)] border border-slate-100/90 backdrop-blur-xl rotate-6 w-48 space-y-2.5">
|
<div className="relative rounded-3xl bg-white/95 p-4 shadow-[0_25px_60px_rgba(55,121,185,0.18),0_10px_25px_rgba(15,29,52,0.05)] border border-slate-100/90 backdrop-blur-xl rotate-6 w-48 space-y-2.5">
|
||||||
{/* Search Input Simulation */}
|
{/* Search Input Simulation */}
|
||||||
<div className="h-7 w-full rounded-xl bg-slate-50 border border-slate-200/80 px-2.5 flex items-center justify-between">
|
<div className="h-7 w-full rounded-xl bg-slate-50 border border-slate-200/80 px-2.5 flex items-center justify-between">
|
||||||
<Search className="size-3 text-[#3779b9]" />
|
<Search className="size-3 text-[#0e6e6a]" />
|
||||||
<div className="size-2 rounded-full bg-[#3779b9]" />
|
<div className="size-2 rounded-full bg-[#0e6e6a]" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 3 Theme Pills */}
|
{/* 3 Theme Pills */}
|
||||||
<div className="space-y-2 pt-0.5">
|
<div className="space-y-2 pt-0.5">
|
||||||
<div className="p-2 rounded-xl bg-emerald-50/80 border border-emerald-100 flex items-center gap-2">
|
<div className="p-2 rounded-xl bg-emerald-50/80 border border-emerald-100 flex items-center gap-2">
|
||||||
<span className="size-2 rounded-full bg-emerald-500 shrink-0" />
|
<span className="size-2 rounded-full bg-emerald-500 shrink-0" />
|
||||||
<span className="text-[11px] font-bold text-emerald-800">Better Rankings</span>
|
<span className="text-[11px] font-bold text-emerald-800">
|
||||||
|
Better Rankings
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-2 rounded-xl bg-[#f0f6fc] border border-[#d6e4f3] flex items-center gap-2">
|
<div className="p-2 rounded-xl bg-[#f0f8f7] border border-[#d9e8e7] flex items-center gap-2">
|
||||||
<span className="size-2 rounded-full bg-[#3779b9] shrink-0" />
|
<span className="size-2 rounded-full bg-[#0e6e6a] shrink-0" />
|
||||||
<span className="text-[11px] font-bold text-[#0f1d34]">More Traffic</span>
|
<span className="text-[11px] font-bold text-[#0f161c]">
|
||||||
|
More Traffic
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-2 rounded-xl bg-[#e0f2fe] border border-sky-100 flex items-center gap-2">
|
<div className="p-2 rounded-xl bg-[#e3f3f2] border border-sky-100 flex items-center gap-2">
|
||||||
<span className="size-2 rounded-full bg-[#4faede] shrink-0" />
|
<span className="size-2 rounded-full bg-[#3fb6ae] shrink-0" />
|
||||||
<span className="text-[11px] font-bold text-[#0284c7]">Real Results</span>
|
<span className="text-[11px] font-bold text-[#1a8a84]">
|
||||||
|
Real Results
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Hand-drawn Loop Arrow */}
|
{/* Hand-drawn Loop Arrow */}
|
||||||
<div className="absolute -bottom-8 -left-8 size-16 text-[#4faede]">
|
<div className="absolute -bottom-8 -left-8 size-16 text-[#3fb6ae]">
|
||||||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none">
|
<svg width="48" height="48" viewBox="0 0 48 48" fill="none">
|
||||||
<path
|
<path
|
||||||
d="M38 8C34 22 14 18 12 32C11 38 18 42 24 38L22 42"
|
d="M38 8C34 22 14 18 12 32C11 38 18 42 24 38L22 42"
|
||||||
stroke="#4faede"
|
stroke="#3fb6ae"
|
||||||
strokeWidth="2.5"
|
strokeWidth="2.5"
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
strokeLinejoin="round"
|
strokeLinejoin="round"
|
||||||
@ -207,10 +267,17 @@ export function CornerWaveDecoration() {
|
|||||||
fill="url(#theme-top-right-wave)"
|
fill="url(#theme-top-right-wave)"
|
||||||
/>
|
/>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="theme-top-right-wave" x1="740" y1="0" x2="420" y2="520" gradientUnits="userSpaceOnUse">
|
<linearGradient
|
||||||
<stop stopColor="#4faede" stopOpacity="0.22" />
|
id="theme-top-right-wave"
|
||||||
<stop offset="0.6" stopColor="#3779b9" stopOpacity="0.12" />
|
x1="740"
|
||||||
<stop offset="1" stopColor="#0f1d34" stopOpacity="0" />
|
y1="0"
|
||||||
|
x2="420"
|
||||||
|
y2="520"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
>
|
||||||
|
<stop stopColor="#3fb6ae" stopOpacity="0.22" />
|
||||||
|
<stop offset="0.6" stopColor="#0e6e6a" stopOpacity="0.12" />
|
||||||
|
<stop offset="1" stopColor="#0f161c" stopOpacity="0" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
@ -223,7 +290,7 @@ export function CornerWaveDecoration() {
|
|||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
d="M-60 560C120 440 180 300 120 180C60 60 140 -20 220 -40"
|
d="M-60 560C120 440 180 300 120 180C60 60 140 -20 220 -40"
|
||||||
stroke="#4faede"
|
stroke="#3fb6ae"
|
||||||
strokeWidth="32"
|
strokeWidth="32"
|
||||||
strokeOpacity="0.12"
|
strokeOpacity="0.12"
|
||||||
/>
|
/>
|
||||||
@ -244,13 +311,13 @@ export function renderPlanIcon(type: keyof typeof PLAN_ICONS) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const TRUST_ICONS: Record<string, React.ReactNode> = {
|
const TRUST_ICONS: Record<string, React.ReactNode> = {
|
||||||
guarantee: <ShieldCheck className="size-4.5 text-[#3779b9]" />,
|
guarantee: <ShieldCheck className="size-4.5 text-[#0e6e6a]" />,
|
||||||
upi: <Zap className="size-4.5 text-[#3779b9]" />,
|
upi: <Zap className="size-4.5 text-[#0e6e6a]" />,
|
||||||
gst: <FileText className="size-4.5 text-[#3779b9]" />,
|
gst: <FileText className="size-4.5 text-[#0e6e6a]" />,
|
||||||
cards: <CreditCard className="size-4.5 text-[#3779b9]" />,
|
cards: <CreditCard className="size-4.5 text-[#0e6e6a]" />,
|
||||||
support: <span className="text-sm">🇮🇳</span>,
|
support: <span className="text-sm">🇮🇳</span>,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function renderTrustIcon(id: string) {
|
export function renderTrustIcon(id: string) {
|
||||||
return TRUST_ICONS[id] ?? <ShieldCheck className="size-4.5 text-[#3779b9]" />;
|
return TRUST_ICONS[id] ?? <ShieldCheck className="size-4.5 text-[#0e6e6a]" />;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,7 +85,7 @@ function SiteForm({ projectId }: { projectId: string }) {
|
|||||||
>
|
>
|
||||||
<div className="space-y-3 text-center">
|
<div className="space-y-3 text-center">
|
||||||
<img
|
<img
|
||||||
src="/transparent-logo.png"
|
src="/crawlerx-mark.png"
|
||||||
alt="CrawlerX"
|
alt="CrawlerX"
|
||||||
className="mx-auto size-10 rounded-lg"
|
className="mx-auto size-10 rounded-lg"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -60,7 +60,7 @@ export function PostSignupOnboarding({
|
|||||||
|
|
||||||
<div className="text-center space-y-3">
|
<div className="text-center space-y-3">
|
||||||
<img
|
<img
|
||||||
src="/transparent-logo.png"
|
src="/crawlerx-mark.png"
|
||||||
alt="CrawlerX"
|
alt="CrawlerX"
|
||||||
className="mx-auto size-10 rounded-lg"
|
className="mx-auto size-10 rounded-lg"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -8,14 +8,14 @@
|
|||||||
"Helvetica Neue", Arial, sans-serif;
|
"Helvetica Neue", Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CrawlerX brand gradient (MetatronCube blue → deep black), used on the
|
/* CrawlerX brand gradient (teal → ink navy), used on the sign-in surface and
|
||||||
sign-in surface and the sidebar header. */
|
the sidebar header. Matches the brand guide's product-UI palette. */
|
||||||
:root {
|
:root {
|
||||||
--brand-gradient: linear-gradient(
|
--brand-gradient: linear-gradient(
|
||||||
135deg,
|
135deg,
|
||||||
#3779b9 0%,
|
#0e6e6a 0%,
|
||||||
#0f1d34 70%,
|
#0f161c 70%,
|
||||||
#00060c 100%
|
#060a0d 100%
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +38,7 @@
|
|||||||
exclude: properties;
|
exclude: properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Light theme — CrawlerX / MetatronCube brand (primary #3779b9) */
|
/* Light theme — CrawlerX brand (primary #0E6E6A, from the brand guide) */
|
||||||
@plugin "daisyui/theme" {
|
@plugin "daisyui/theme" {
|
||||||
name: "crawlerx";
|
name: "crawlerx";
|
||||||
default: true;
|
default: true;
|
||||||
@ -48,15 +48,15 @@
|
|||||||
--color-base-200: #f6f8fa;
|
--color-base-200: #f6f8fa;
|
||||||
--color-base-300: #e6eaef;
|
--color-base-300: #e6eaef;
|
||||||
--color-base-content: #151515;
|
--color-base-content: #151515;
|
||||||
--color-primary: #3779b9;
|
--color-primary: #0e6e6a;
|
||||||
--color-primary-content: #ffffff;
|
--color-primary-content: #ffffff;
|
||||||
--color-secondary: #0f1d34;
|
--color-secondary: #0f161c;
|
||||||
--color-secondary-content: #ffffff;
|
--color-secondary-content: #ffffff;
|
||||||
--color-accent: #4faede;
|
--color-accent: #3fb6ae;
|
||||||
--color-accent-content: #06263a;
|
--color-accent-content: #06263a;
|
||||||
--color-neutral: #151515;
|
--color-neutral: #151515;
|
||||||
--color-neutral-content: #ffffff;
|
--color-neutral-content: #ffffff;
|
||||||
--color-info: #3779b9;
|
--color-info: #0e6e6a;
|
||||||
--color-info-content: #ffffff;
|
--color-info-content: #ffffff;
|
||||||
--color-success: oklch(65% 0.18 145);
|
--color-success: oklch(65% 0.18 145);
|
||||||
--color-success-content: oklch(100% 0 0);
|
--color-success-content: oklch(100% 0 0);
|
||||||
@ -83,16 +83,16 @@
|
|||||||
--color-base-200: #0e121b;
|
--color-base-200: #0e121b;
|
||||||
--color-base-300: #232a37;
|
--color-base-300: #232a37;
|
||||||
--color-base-content: #e8ebf0;
|
--color-base-content: #e8ebf0;
|
||||||
--color-primary: #3f8ad4;
|
--color-primary: #3fb6ae;
|
||||||
--color-primary-content: #ffffff;
|
--color-primary-content: #06263a;
|
||||||
--color-secondary: #9fb3c8;
|
--color-secondary: #9fb3c8;
|
||||||
--color-secondary-content: #0e121b;
|
--color-secondary-content: #0e121b;
|
||||||
--color-accent: #4faede;
|
--color-accent: #3fb6ae;
|
||||||
--color-accent-content: #06263a;
|
--color-accent-content: #06263a;
|
||||||
--color-neutral: #e8ebf0;
|
--color-neutral: #e8ebf0;
|
||||||
--color-neutral-content: #141821;
|
--color-neutral-content: #141821;
|
||||||
--color-info: #3f8ad4;
|
--color-info: #3fb6ae;
|
||||||
--color-info-content: #ffffff;
|
--color-info-content: #06263a;
|
||||||
--color-success: oklch(65% 0.18 145);
|
--color-success: oklch(65% 0.18 145);
|
||||||
--color-success-content: oklch(100% 0 0);
|
--color-success-content: oklch(100% 0 0);
|
||||||
--color-warning: oklch(80% 0.15 80);
|
--color-warning: oklch(80% 0.15 80);
|
||||||
|
|||||||
@ -73,7 +73,7 @@ function OAuthConsentPage() {
|
|||||||
<div className="w-full max-w-md rounded-2xl border border-base-300 bg-base-100 p-8 shadow-sm">
|
<div className="w-full max-w-md rounded-2xl border border-base-300 bg-base-100 p-8 shadow-sm">
|
||||||
<div className="flex flex-col items-center text-center">
|
<div className="flex flex-col items-center text-center">
|
||||||
<img
|
<img
|
||||||
src="/transparent-logo.png"
|
src="/crawlerx-mark.png"
|
||||||
alt="CrawlerX"
|
alt="CrawlerX"
|
||||||
className="size-10 rounded-lg"
|
className="size-10 rounded-lg"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -125,8 +125,7 @@ function SubscribePage() {
|
|||||||
});
|
});
|
||||||
const siteCount = Math.max(1, projectsQuery.data?.length ?? 1);
|
const siteCount = Math.max(1, projectsQuery.data?.length ?? 1);
|
||||||
const activePlanId: "free" | "starter" | "pro" | "agency" =
|
const activePlanId: "free" | "starter" | "pro" | "agency" =
|
||||||
billingQuery.data?.planId ??
|
billingQuery.data?.planId ?? (planStatus === "paid" ? "pro" : "free");
|
||||||
(planStatus === "paid" ? "pro" : "free");
|
|
||||||
const subscribeRouteState = getSubscribeRouteState({
|
const subscribeRouteState = getSubscribeRouteState({
|
||||||
hasSession,
|
hasSession,
|
||||||
isCustomerLoading: customerQuery.isLoading,
|
isCustomerLoading: customerQuery.isLoading,
|
||||||
@ -184,14 +183,14 @@ function SubscribePage() {
|
|||||||
<div className="min-h-screen flex items-center justify-center p-4">
|
<div className="min-h-screen flex items-center justify-center p-4">
|
||||||
<div className="w-full max-w-sm space-y-4 text-center p-8 rounded-3xl bg-white border border-slate-200 shadow-xl">
|
<div className="w-full max-w-sm space-y-4 text-center p-8 rounded-3xl bg-white border border-slate-200 shadow-xl">
|
||||||
<img
|
<img
|
||||||
src="/transparent-logo.png"
|
src="/crawlerx-mark.png"
|
||||||
alt="CrawlerX"
|
alt="CrawlerX"
|
||||||
className="mx-auto size-12 object-contain"
|
className="mx-auto size-12 object-contain"
|
||||||
/>
|
/>
|
||||||
<h1 className="text-xl font-bold text-slate-900">
|
<h1 className="text-xl font-bold text-slate-900">
|
||||||
Finalizing your subscription…
|
Finalizing your subscription…
|
||||||
</h1>
|
</h1>
|
||||||
<span className="loading loading-spinner loading-md text-blue-600" />
|
<span className="loading loading-spinner loading-md text-primary" />
|
||||||
<p className="text-sm text-slate-500">
|
<p className="text-sm text-slate-500">
|
||||||
Setting up your workspace limits and credits.
|
Setting up your workspace limits and credits.
|
||||||
</p>
|
</p>
|
||||||
@ -239,7 +238,9 @@ function SubscribePage() {
|
|||||||
|
|
||||||
throw new Error("Stripe checkout session did not return a valid URL.");
|
throw new Error("Stripe checkout session did not return a valid URL.");
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
const errObj = err as { message?: string; data?: { message?: string } } | undefined;
|
const errObj = err as
|
||||||
|
| { message?: string; data?: { message?: string } }
|
||||||
|
| undefined;
|
||||||
const rawMsg = errObj?.data?.message || errObj?.message;
|
const rawMsg = errObj?.data?.message || errObj?.message;
|
||||||
const msg = rawMsg
|
const msg = rawMsg
|
||||||
? getStandardErrorMessage(new Error(rawMsg), rawMsg)
|
? getStandardErrorMessage(new Error(rawMsg), rawMsg)
|
||||||
@ -278,8 +279,13 @@ function SubscribePage() {
|
|||||||
}
|
}
|
||||||
throw new Error("Unable to retrieve Stripe billing portal URL.");
|
throw new Error("Unable to retrieve Stripe billing portal URL.");
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
const errObj = err as { message?: string; data?: { message?: string } } | undefined;
|
const errObj = err as
|
||||||
const msg = errObj?.data?.message || errObj?.message || "Failed to open billing portal.";
|
| { message?: string; data?: { message?: string } }
|
||||||
|
| undefined;
|
||||||
|
const msg =
|
||||||
|
errObj?.data?.message ||
|
||||||
|
errObj?.message ||
|
||||||
|
"Failed to open billing portal.";
|
||||||
toast.error(msg);
|
toast.error(msg);
|
||||||
} finally {
|
} finally {
|
||||||
setIsOpeningPortal(false);
|
setIsOpeningPortal(false);
|
||||||
@ -379,7 +385,8 @@ function SubscribePage() {
|
|||||||
|
|
||||||
{/* Footer */}
|
{/* Footer */}
|
||||||
<footer className="pt-8 pb-12 text-center text-xs text-slate-400 border-t border-slate-100">
|
<footer className="pt-8 pb-12 text-center text-xs text-slate-400 border-t border-slate-100">
|
||||||
CrawlerX by Metatroncube Solutions • Enterprise & Custom Agency Plans: {SUPPORT_EMAIL}
|
CrawlerX by Metatroncube Solutions • Enterprise & Custom Agency Plans:{" "}
|
||||||
|
{SUPPORT_EMAIL}
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user