Finished Landing Page
This commit is contained in:
@@ -4,8 +4,9 @@
|
|||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
|
color-scheme: light;
|
||||||
/* Light Mode - Smart-Admin Copilot Palette */
|
/* Light Mode - Smart-Admin Copilot Palette */
|
||||||
--background: 0 0% 100%;
|
--background: 210 40% 98%;
|
||||||
--foreground: 222 47% 11%;
|
--foreground: 222 47% 11%;
|
||||||
--card: 210 40% 98%;
|
--card: 210 40% 98%;
|
||||||
--card-foreground: 222 47% 11%;
|
--card-foreground: 222 47% 11%;
|
||||||
@@ -41,6 +42,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
|
color-scheme: dark;
|
||||||
/* Dark Mode - Smart-Admin Copilot Palette */
|
/* Dark Mode - Smart-Admin Copilot Palette */
|
||||||
--background: 222 47% 5%;
|
--background: 222 47% 5%;
|
||||||
--foreground: 210 40% 98%;
|
--foreground: 210 40% 98%;
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { Geist, Geist_Mono } from "next/font/google";
|
import { Poppins, Geist_Mono } from "next/font/google";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
import { Providers } from "./provider";
|
import { Providers } from "./provider";
|
||||||
|
|
||||||
const geistSans = Geist({
|
const poppins = Poppins({
|
||||||
variable: "--font-geist-sans",
|
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
|
weight: ["400", "500", "600", "700", "800", "900"],
|
||||||
|
variable: "--font-poppins",
|
||||||
|
display: "swap",
|
||||||
});
|
});
|
||||||
|
|
||||||
const geistMono = Geist_Mono({
|
const geistMono = Geist_Mono({
|
||||||
variable: "--font-geist-mono",
|
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
|
variable: "--font-geist-mono",
|
||||||
|
display: "swap",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
@@ -26,7 +29,7 @@ export default function RootLayout({
|
|||||||
return (
|
return (
|
||||||
<html lang="en" suppressHydrationWarning>
|
<html lang="en" suppressHydrationWarning>
|
||||||
<body
|
<body
|
||||||
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
className={`${poppins.variable} ${geistMono.variable} min-h-screen bg-background text-foreground antialiased`}
|
||||||
>
|
>
|
||||||
<Providers>{children}</Providers>
|
<Providers>{children}</Providers>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -4,7 +4,12 @@ import { ReactNode } from "react";
|
|||||||
|
|
||||||
export function Providers({ children }: { children: ReactNode }) {
|
export function Providers({ children }: { children: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
<ThemeProvider
|
||||||
|
attribute="class"
|
||||||
|
defaultTheme="system"
|
||||||
|
enableSystem
|
||||||
|
disableTransitionOnChange
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,5 +19,7 @@
|
|||||||
"lib": "@/lib",
|
"lib": "@/lib",
|
||||||
"hooks": "@/hooks"
|
"hooks": "@/hooks"
|
||||||
},
|
},
|
||||||
"registries": {}
|
"registries": {
|
||||||
|
"@aceternity": "https://ui.aceternity.com/registry/{name}.json"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
141
components/ui/background-beams.tsx
Normal file
141
components/ui/background-beams.tsx
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
"use client";
|
||||||
|
import React from "react";
|
||||||
|
import { motion } from "motion/react";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
export const BackgroundBeams = React.memo(
|
||||||
|
({ className }: { className?: string }) => {
|
||||||
|
const paths = [
|
||||||
|
"M-380 -189C-380 -189 -312 216 152 343C616 470 684 875 684 875",
|
||||||
|
"M-373 -197C-373 -197 -305 208 159 335C623 462 691 867 691 867",
|
||||||
|
"M-366 -205C-366 -205 -298 200 166 327C630 454 698 859 698 859",
|
||||||
|
"M-359 -213C-359 -213 -291 192 173 319C637 446 705 851 705 851",
|
||||||
|
"M-352 -221C-352 -221 -284 184 180 311C644 438 712 843 712 843",
|
||||||
|
"M-345 -229C-345 -229 -277 176 187 303C651 430 719 835 719 835",
|
||||||
|
"M-338 -237C-338 -237 -270 168 194 295C658 422 726 827 726 827",
|
||||||
|
"M-331 -245C-331 -245 -263 160 201 287C665 414 733 819 733 819",
|
||||||
|
"M-324 -253C-324 -253 -256 152 208 279C672 406 740 811 740 811",
|
||||||
|
"M-317 -261C-317 -261 -249 144 215 271C679 398 747 803 747 803",
|
||||||
|
"M-310 -269C-310 -269 -242 136 222 263C686 390 754 795 754 795",
|
||||||
|
"M-303 -277C-303 -277 -235 128 229 255C693 382 761 787 761 787",
|
||||||
|
"M-296 -285C-296 -285 -228 120 236 247C700 374 768 779 768 779",
|
||||||
|
"M-289 -293C-289 -293 -221 112 243 239C707 366 775 771 775 771",
|
||||||
|
"M-282 -301C-282 -301 -214 104 250 231C714 358 782 763 782 763",
|
||||||
|
"M-275 -309C-275 -309 -207 96 257 223C721 350 789 755 789 755",
|
||||||
|
"M-268 -317C-268 -317 -200 88 264 215C728 342 796 747 796 747",
|
||||||
|
"M-261 -325C-261 -325 -193 80 271 207C735 334 803 739 803 739",
|
||||||
|
"M-254 -333C-254 -333 -186 72 278 199C742 326 810 731 810 731",
|
||||||
|
"M-247 -341C-247 -341 -179 64 285 191C749 318 817 723 817 723",
|
||||||
|
"M-240 -349C-240 -349 -172 56 292 183C756 310 824 715 824 715",
|
||||||
|
"M-233 -357C-233 -357 -165 48 299 175C763 302 831 707 831 707",
|
||||||
|
"M-226 -365C-226 -365 -158 40 306 167C770 294 838 699 838 699",
|
||||||
|
"M-219 -373C-219 -373 -151 32 313 159C777 286 845 691 845 691",
|
||||||
|
"M-212 -381C-212 -381 -144 24 320 151C784 278 852 683 852 683",
|
||||||
|
"M-205 -389C-205 -389 -137 16 327 143C791 270 859 675 859 675",
|
||||||
|
"M-198 -397C-198 -397 -130 8 334 135C798 262 866 667 866 667",
|
||||||
|
"M-191 -405C-191 -405 -123 0 341 127C805 254 873 659 873 659",
|
||||||
|
"M-184 -413C-184 -413 -116 -8 348 119C812 246 880 651 880 651",
|
||||||
|
"M-177 -421C-177 -421 -109 -16 355 111C819 238 887 643 887 643",
|
||||||
|
"M-170 -429C-170 -429 -102 -24 362 103C826 230 894 635 894 635",
|
||||||
|
"M-163 -437C-163 -437 -95 -32 369 95C833 222 901 627 901 627",
|
||||||
|
"M-156 -445C-156 -445 -88 -40 376 87C840 214 908 619 908 619",
|
||||||
|
"M-149 -453C-149 -453 -81 -48 383 79C847 206 915 611 915 611",
|
||||||
|
"M-142 -461C-142 -461 -74 -56 390 71C854 198 922 603 922 603",
|
||||||
|
"M-135 -469C-135 -469 -67 -64 397 63C861 190 929 595 929 595",
|
||||||
|
"M-128 -477C-128 -477 -60 -72 404 55C868 182 936 587 936 587",
|
||||||
|
"M-121 -485C-121 -485 -53 -80 411 47C875 174 943 579 943 579",
|
||||||
|
"M-114 -493C-114 -493 -46 -88 418 39C882 166 950 571 950 571",
|
||||||
|
"M-107 -501C-107 -501 -39 -96 425 31C889 158 957 563 957 563",
|
||||||
|
"M-100 -509C-100 -509 -32 -104 432 23C896 150 964 555 964 555",
|
||||||
|
"M-93 -517C-93 -517 -25 -112 439 15C903 142 971 547 971 547",
|
||||||
|
"M-86 -525C-86 -525 -18 -120 446 7C910 134 978 539 978 539",
|
||||||
|
"M-79 -533C-79 -533 -11 -128 453 -1C917 126 985 531 985 531",
|
||||||
|
"M-72 -541C-72 -541 -4 -136 460 -9C924 118 992 523 992 523",
|
||||||
|
"M-65 -549C-65 -549 3 -144 467 -17C931 110 999 515 999 515",
|
||||||
|
"M-58 -557C-58 -557 10 -152 474 -25C938 102 1006 507 1006 507",
|
||||||
|
"M-51 -565C-51 -565 17 -160 481 -33C945 94 1013 499 1013 499",
|
||||||
|
"M-44 -573C-44 -573 24 -168 488 -41C952 86 1020 491 1020 491",
|
||||||
|
"M-37 -581C-37 -581 31 -176 495 -49C959 78 1027 483 1027 483",
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"absolute inset-0 flex h-full w-full items-center justify-center [mask-repeat:no-repeat] [mask-size:40px]",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="pointer-events-none absolute z-0 h-full w-full"
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
viewBox="0 0 696 316"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M-380 -189C-380 -189 -312 216 152 343C616 470 684 875 684 875M-373 -197C-373 -197 -305 208 159 335C623 462 691 867 691 867M-366 -205C-366 -205 -298 200 166 327C630 454 698 859 698 859M-359 -213C-359 -213 -291 192 173 319C637 446 705 851 705 851M-352 -221C-352 -221 -284 184 180 311C644 438 712 843 712 843M-345 -229C-345 -229 -277 176 187 303C651 430 719 835 719 835M-338 -237C-338 -237 -270 168 194 295C658 422 726 827 726 827M-331 -245C-331 -245 -263 160 201 287C665 414 733 819 733 819M-324 -253C-324 -253 -256 152 208 279C672 406 740 811 740 811M-317 -261C-317 -261 -249 144 215 271C679 398 747 803 747 803M-310 -269C-310 -269 -242 136 222 263C686 390 754 795 754 795M-303 -277C-303 -277 -235 128 229 255C693 382 761 787 761 787M-296 -285C-296 -285 -228 120 236 247C700 374 768 779 768 779M-289 -293C-289 -293 -221 112 243 239C707 366 775 771 775 771M-282 -301C-282 -301 -214 104 250 231C714 358 782 763 782 763M-275 -309C-275 -309 -207 96 257 223C721 350 789 755 789 755M-268 -317C-268 -317 -200 88 264 215C728 342 796 747 796 747M-261 -325C-261 -325 -193 80 271 207C735 334 803 739 803 739M-254 -333C-254 -333 -186 72 278 199C742 326 810 731 810 731M-247 -341C-247 -341 -179 64 285 191C749 318 817 723 817 723M-240 -349C-240 -349 -172 56 292 183C756 310 824 715 824 715M-233 -357C-233 -357 -165 48 299 175C763 302 831 707 831 707M-226 -365C-226 -365 -158 40 306 167C770 294 838 699 838 699M-219 -373C-219 -373 -151 32 313 159C777 286 845 691 845 691M-212 -381C-212 -381 -144 24 320 151C784 278 852 683 852 683M-205 -389C-205 -389 -137 16 327 143C791 270 859 675 859 675M-198 -397C-198 -397 -130 8 334 135C798 262 866 667 866 667M-191 -405C-191 -405 -123 0 341 127C805 254 873 659 873 659M-184 -413C-184 -413 -116 -8 348 119C812 246 880 651 880 651M-177 -421C-177 -421 -109 -16 355 111C819 238 887 643 887 643M-170 -429C-170 -429 -102 -24 362 103C826 230 894 635 894 635M-163 -437C-163 -437 -95 -32 369 95C833 222 901 627 901 627M-156 -445C-156 -445 -88 -40 376 87C840 214 908 619 908 619M-149 -453C-149 -453 -81 -48 383 79C847 206 915 611 915 611M-142 -461C-142 -461 -74 -56 390 71C854 198 922 603 922 603M-135 -469C-135 -469 -67 -64 397 63C861 190 929 595 929 595M-128 -477C-128 -477 -60 -72 404 55C868 182 936 587 936 587M-121 -485C-121 -485 -53 -80 411 47C875 174 943 579 943 579M-114 -493C-114 -493 -46 -88 418 39C882 166 950 571 950 571M-107 -501C-107 -501 -39 -96 425 31C889 158 957 563 957 563M-100 -509C-100 -509 -32 -104 432 23C896 150 964 555 964 555M-93 -517C-93 -517 -25 -112 439 15C903 142 971 547 971 547M-86 -525C-86 -525 -18 -120 446 7C910 134 978 539 978 539M-79 -533C-79 -533 -11 -128 453 -1C917 126 985 531 985 531M-72 -541C-72 -541 -4 -136 460 -9C924 118 992 523 992 523M-65 -549C-65 -549 3 -144 467 -17C931 110 999 515 999 515M-58 -557C-58 -557 10 -152 474 -25C938 102 1006 507 1006 507M-51 -565C-51 -565 17 -160 481 -33C945 94 1013 499 1013 499M-44 -573C-44 -573 24 -168 488 -41C952 86 1020 491 1020 491M-37 -581C-37 -581 31 -176 495 -49C959 78 1027 483 1027 483M-30 -589C-30 -589 38 -184 502 -57C966 70 1034 475 1034 475M-23 -597C-23 -597 45 -192 509 -65C973 62 1041 467 1041 467M-16 -605C-16 -605 52 -200 516 -73C980 54 1048 459 1048 459M-9 -613C-9 -613 59 -208 523 -81C987 46 1055 451 1055 451M-2 -621C-2 -621 66 -216 530 -89C994 38 1062 443 1062 443M5 -629C5 -629 73 -224 537 -97C1001 30 1069 435 1069 435M12 -637C12 -637 80 -232 544 -105C1008 22 1076 427 1076 427M19 -645C19 -645 87 -240 551 -113C1015 14 1083 419 1083 419"
|
||||||
|
stroke="url(#paint0_radial_242_278)"
|
||||||
|
strokeOpacity="0.05"
|
||||||
|
strokeWidth="0.5"
|
||||||
|
></path>
|
||||||
|
|
||||||
|
{paths.map((path, index) => (
|
||||||
|
<motion.path
|
||||||
|
key={`path-` + index}
|
||||||
|
d={path}
|
||||||
|
stroke={`url(#linearGradient-${index})`}
|
||||||
|
strokeOpacity="0.4"
|
||||||
|
strokeWidth="0.5"
|
||||||
|
></motion.path>
|
||||||
|
))}
|
||||||
|
<defs>
|
||||||
|
{paths.map((path, index) => (
|
||||||
|
<motion.linearGradient
|
||||||
|
id={`linearGradient-${index}`}
|
||||||
|
key={`gradient-${index}`}
|
||||||
|
initial={{
|
||||||
|
x1: "0%",
|
||||||
|
x2: "0%",
|
||||||
|
y1: "0%",
|
||||||
|
y2: "0%",
|
||||||
|
}}
|
||||||
|
animate={{
|
||||||
|
x1: ["0%", "100%"],
|
||||||
|
x2: ["0%", "95%"],
|
||||||
|
y1: ["0%", "100%"],
|
||||||
|
y2: ["0%", `${93 + Math.random() * 8}%`],
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
duration: Math.random() * 10 + 10,
|
||||||
|
ease: "easeInOut",
|
||||||
|
repeat: Infinity,
|
||||||
|
delay: Math.random() * 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<stop stopColor="#3b82f6" stopOpacity="0"></stop>
|
||||||
|
<stop stopColor="#3b82f6"></stop>
|
||||||
|
<stop offset="32.5%" stopColor="#8b5cf6"></stop>
|
||||||
|
<stop offset="100%" stopColor="#14b8a6" stopOpacity="0"></stop>
|
||||||
|
</motion.linearGradient>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<radialGradient
|
||||||
|
id="paint0_radial_242_278"
|
||||||
|
cx="0"
|
||||||
|
cy="0"
|
||||||
|
r="1"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="translate(352 34) rotate(90) scale(555 1560.62)"
|
||||||
|
>
|
||||||
|
<stop offset="0.0666667" stopColor="#d4d4d4"></stop>
|
||||||
|
<stop offset="0.243243" stopColor="#d4d4d4"></stop>
|
||||||
|
<stop offset="0.43594" stopColor="white" stopOpacity="0"></stop>
|
||||||
|
</radialGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
BackgroundBeams.displayName = "BackgroundBeams";
|
||||||
54
components/ui/bento-grid.tsx
Normal file
54
components/ui/bento-grid.tsx
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
export const BentoGrid = ({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
className?: string;
|
||||||
|
children?: React.ReactNode;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"mx-auto grid max-w-7xl grid-cols-1 gap-4 md:auto-rows-[18rem] md:grid-cols-3",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BentoGridItem = ({
|
||||||
|
className,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
header,
|
||||||
|
icon,
|
||||||
|
}: {
|
||||||
|
className?: string;
|
||||||
|
title?: string | React.ReactNode;
|
||||||
|
description?: string | React.ReactNode;
|
||||||
|
header?: React.ReactNode;
|
||||||
|
icon?: React.ReactNode;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"group/bento shadow-input row-span-1 flex flex-col justify-between space-y-4 rounded-xl border border-neutral-200 bg-white p-4 transition duration-200 hover:shadow-xl dark:border-white/[0.2] dark:bg-black dark:shadow-none",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{header}
|
||||||
|
<div className="transition duration-200 group-hover/bento:translate-x-2">
|
||||||
|
{icon}
|
||||||
|
<div className="mt-2 mb-2 font-sans font-bold text-neutral-600 dark:text-neutral-200">
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
|
<div className="font-sans text-xs font-normal text-neutral-600 dark:text-neutral-300">
|
||||||
|
{description}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
190
components/ui/glowing-effect.tsx
Normal file
190
components/ui/glowing-effect.tsx
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { memo, useCallback, useEffect, useRef } from "react";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { animate } from "motion/react";
|
||||||
|
|
||||||
|
interface GlowingEffectProps {
|
||||||
|
blur?: number;
|
||||||
|
inactiveZone?: number;
|
||||||
|
proximity?: number;
|
||||||
|
spread?: number;
|
||||||
|
variant?: "default" | "white";
|
||||||
|
glow?: boolean;
|
||||||
|
className?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
movementDuration?: number;
|
||||||
|
borderWidth?: number;
|
||||||
|
}
|
||||||
|
const GlowingEffect = memo(
|
||||||
|
({
|
||||||
|
blur = 0,
|
||||||
|
inactiveZone = 0.7,
|
||||||
|
proximity = 0,
|
||||||
|
spread = 20,
|
||||||
|
variant = "default",
|
||||||
|
glow = false,
|
||||||
|
className,
|
||||||
|
movementDuration = 2,
|
||||||
|
borderWidth = 1,
|
||||||
|
disabled = true,
|
||||||
|
}: GlowingEffectProps) => {
|
||||||
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
const lastPosition = useRef({ x: 0, y: 0 });
|
||||||
|
const animationFrameRef = useRef<number>(0);
|
||||||
|
|
||||||
|
const handleMove = useCallback(
|
||||||
|
(e?: MouseEvent | { x: number; y: number }) => {
|
||||||
|
if (!containerRef.current) return;
|
||||||
|
|
||||||
|
if (animationFrameRef.current) {
|
||||||
|
cancelAnimationFrame(animationFrameRef.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
animationFrameRef.current = requestAnimationFrame(() => {
|
||||||
|
const element = containerRef.current;
|
||||||
|
if (!element) return;
|
||||||
|
|
||||||
|
const { left, top, width, height } = element.getBoundingClientRect();
|
||||||
|
const mouseX = e?.x ?? lastPosition.current.x;
|
||||||
|
const mouseY = e?.y ?? lastPosition.current.y;
|
||||||
|
|
||||||
|
if (e) {
|
||||||
|
lastPosition.current = { x: mouseX, y: mouseY };
|
||||||
|
}
|
||||||
|
|
||||||
|
const center = [left + width * 0.5, top + height * 0.5];
|
||||||
|
const distanceFromCenter = Math.hypot(
|
||||||
|
mouseX - center[0],
|
||||||
|
mouseY - center[1]
|
||||||
|
);
|
||||||
|
const inactiveRadius = 0.5 * Math.min(width, height) * inactiveZone;
|
||||||
|
|
||||||
|
if (distanceFromCenter < inactiveRadius) {
|
||||||
|
element.style.setProperty("--active", "0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isActive =
|
||||||
|
mouseX > left - proximity &&
|
||||||
|
mouseX < left + width + proximity &&
|
||||||
|
mouseY > top - proximity &&
|
||||||
|
mouseY < top + height + proximity;
|
||||||
|
|
||||||
|
element.style.setProperty("--active", isActive ? "1" : "0");
|
||||||
|
|
||||||
|
if (!isActive) return;
|
||||||
|
|
||||||
|
const currentAngle =
|
||||||
|
parseFloat(element.style.getPropertyValue("--start")) || 0;
|
||||||
|
let targetAngle =
|
||||||
|
(180 * Math.atan2(mouseY - center[1], mouseX - center[0])) /
|
||||||
|
Math.PI +
|
||||||
|
90;
|
||||||
|
|
||||||
|
const angleDiff = ((targetAngle - currentAngle + 180) % 360) - 180;
|
||||||
|
const newAngle = currentAngle + angleDiff;
|
||||||
|
|
||||||
|
animate(currentAngle, newAngle, {
|
||||||
|
duration: movementDuration,
|
||||||
|
ease: [0.16, 1, 0.3, 1],
|
||||||
|
onUpdate: (value) => {
|
||||||
|
element.style.setProperty("--start", String(value));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[inactiveZone, proximity, movementDuration]
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (disabled) return;
|
||||||
|
|
||||||
|
const handleScroll = () => handleMove();
|
||||||
|
const handlePointerMove = (e: PointerEvent) => handleMove(e);
|
||||||
|
|
||||||
|
window.addEventListener("scroll", handleScroll, { passive: true });
|
||||||
|
document.body.addEventListener("pointermove", handlePointerMove, {
|
||||||
|
passive: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (animationFrameRef.current) {
|
||||||
|
cancelAnimationFrame(animationFrameRef.current);
|
||||||
|
}
|
||||||
|
window.removeEventListener("scroll", handleScroll);
|
||||||
|
document.body.removeEventListener("pointermove", handlePointerMove);
|
||||||
|
};
|
||||||
|
}, [handleMove, disabled]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"pointer-events-none absolute -inset-px hidden rounded-[inherit] border opacity-0 transition-opacity",
|
||||||
|
glow && "opacity-100",
|
||||||
|
variant === "white" && "border-white",
|
||||||
|
disabled && "!block"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
ref={containerRef}
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"--blur": `${blur}px`,
|
||||||
|
"--spread": spread,
|
||||||
|
"--start": "0",
|
||||||
|
"--active": "0",
|
||||||
|
"--glowingeffect-border-width": `${borderWidth}px`,
|
||||||
|
"--repeating-conic-gradient-times": "5",
|
||||||
|
"--gradient":
|
||||||
|
variant === "white"
|
||||||
|
? `repeating-conic-gradient(
|
||||||
|
from 236.84deg at 50% 50%,
|
||||||
|
var(--black),
|
||||||
|
var(--black) calc(25% / var(--repeating-conic-gradient-times))
|
||||||
|
)`
|
||||||
|
: `radial-gradient(circle, #3b82f6 10%, #3b82f600 20%),
|
||||||
|
radial-gradient(circle at 40% 40%, #60a5fa 5%, #60a5fa00 15%),
|
||||||
|
radial-gradient(circle at 60% 60%, #2563eb 10%, #2563eb00 20%),
|
||||||
|
radial-gradient(circle at 40% 60%, #1d4ed8 10%, #1d4ed800 20%),
|
||||||
|
repeating-conic-gradient(
|
||||||
|
from 236.84deg at 50% 50%,
|
||||||
|
#3b82f6 0%,
|
||||||
|
#60a5fa calc(25% / var(--repeating-conic-gradient-times)),
|
||||||
|
#2563eb calc(50% / var(--repeating-conic-gradient-times)),
|
||||||
|
#1d4ed8 calc(75% / var(--repeating-conic-gradient-times)),
|
||||||
|
#3b82f6 calc(100% / var(--repeating-conic-gradient-times))
|
||||||
|
)`,
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
className={cn(
|
||||||
|
"pointer-events-none absolute inset-0 rounded-[inherit] opacity-100 transition-opacity",
|
||||||
|
glow && "opacity-100",
|
||||||
|
blur > 0 && "blur-[var(--blur)] ",
|
||||||
|
className,
|
||||||
|
disabled && "!hidden"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"glow",
|
||||||
|
"rounded-[inherit]",
|
||||||
|
'after:content-[""] after:rounded-[inherit] after:absolute after:inset-[calc(-1*var(--glowingeffect-border-width))]',
|
||||||
|
"after:[border:var(--glowingeffect-border-width)_solid_transparent]",
|
||||||
|
"after:[background:var(--gradient)] after:[background-attachment:fixed]",
|
||||||
|
"after:opacity-[var(--active)] after:transition-opacity after:duration-300",
|
||||||
|
"after:[mask-clip:padding-box,border-box]",
|
||||||
|
"after:[mask-composite:intersect]",
|
||||||
|
"after:[mask-image:linear-gradient(#0000,#0000),conic-gradient(from_calc((var(--start)-var(--spread))*1deg),#00000000_0deg,#fff,#00000000_calc(var(--spread)*2deg))]"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
GlowingEffect.displayName = "GlowingEffect";
|
||||||
|
|
||||||
|
export { GlowingEffect };
|
||||||
50
components/ui/mode-toggle.tsx
Normal file
50
components/ui/mode-toggle.tsx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
import { Moon, Sun } from "lucide-react";
|
||||||
|
import { useTheme } from "next-themes";
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from "@/components/ui/dropdown-menu";
|
||||||
|
|
||||||
|
type ModeToggleProps = {
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function ModeToggle({ className }: ModeToggleProps) {
|
||||||
|
const { setTheme } = useTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className={cn("h-9 w-9", className)}
|
||||||
|
aria-label="Toggle theme"
|
||||||
|
>
|
||||||
|
<Sun className="h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||||
|
<Moon className="absolute h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||||
|
<span className="sr-only">Toggle theme</span>
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end">
|
||||||
|
<DropdownMenuItem onClick={() => setTheme("light")}>
|
||||||
|
Light
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem onClick={() => setTheme("dark")}>
|
||||||
|
Dark
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem onClick={() => setTheme("system")}>
|
||||||
|
System
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
);
|
||||||
|
}
|
||||||
128
components/ui/spotlight-new.tsx
Normal file
128
components/ui/spotlight-new.tsx
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
"use client";
|
||||||
|
import React from "react";
|
||||||
|
import { motion } from "motion/react";
|
||||||
|
|
||||||
|
type SpotlightProps = {
|
||||||
|
gradientFirst?: string;
|
||||||
|
gradientSecond?: string;
|
||||||
|
gradientThird?: string;
|
||||||
|
translateY?: number;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
smallWidth?: number;
|
||||||
|
duration?: number;
|
||||||
|
xOffset?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Spotlight = ({
|
||||||
|
gradientFirst = "radial-gradient(68.54% 68.72% at 55.02% 31.46%, hsla(210, 100%, 85%, .08) 0, hsla(210, 100%, 55%, .02) 50%, hsla(210, 100%, 45%, 0) 80%)",
|
||||||
|
gradientSecond = "radial-gradient(50% 50% at 50% 50%, hsla(210, 100%, 85%, .06) 0, hsla(210, 100%, 55%, .02) 80%, transparent 100%)",
|
||||||
|
gradientThird = "radial-gradient(50% 50% at 50% 50%, hsla(210, 100%, 85%, .04) 0, hsla(210, 100%, 45%, .02) 80%, transparent 100%)",
|
||||||
|
translateY = -350,
|
||||||
|
width = 560,
|
||||||
|
height = 1380,
|
||||||
|
smallWidth = 240,
|
||||||
|
duration = 7,
|
||||||
|
xOffset = 100,
|
||||||
|
}: SpotlightProps = {}) => {
|
||||||
|
return (
|
||||||
|
<motion.div
|
||||||
|
initial={{
|
||||||
|
opacity: 0,
|
||||||
|
}}
|
||||||
|
animate={{
|
||||||
|
opacity: 1,
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
duration: 1.5,
|
||||||
|
}}
|
||||||
|
className="pointer-events-none absolute inset-0 h-full w-full"
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
animate={{
|
||||||
|
x: [0, xOffset, 0],
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
duration,
|
||||||
|
repeat: Infinity,
|
||||||
|
repeatType: "reverse",
|
||||||
|
ease: "easeInOut",
|
||||||
|
}}
|
||||||
|
className="absolute top-0 left-0 w-screen h-screen z-40 pointer-events-none"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
transform: `translateY(${translateY}px) rotate(-45deg)`,
|
||||||
|
background: gradientFirst,
|
||||||
|
width: `${width}px`,
|
||||||
|
height: `${height}px`,
|
||||||
|
}}
|
||||||
|
className={`absolute top-0 left-0`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
transform: "rotate(-45deg) translate(5%, -50%)",
|
||||||
|
background: gradientSecond,
|
||||||
|
width: `${smallWidth}px`,
|
||||||
|
height: `${height}px`,
|
||||||
|
}}
|
||||||
|
className={`absolute top-0 left-0 origin-top-left`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
transform: "rotate(-45deg) translate(-180%, -70%)",
|
||||||
|
background: gradientThird,
|
||||||
|
width: `${smallWidth}px`,
|
||||||
|
height: `${height}px`,
|
||||||
|
}}
|
||||||
|
className={`absolute top-0 left-0 origin-top-left`}
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
animate={{
|
||||||
|
x: [0, -xOffset, 0],
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
duration,
|
||||||
|
repeat: Infinity,
|
||||||
|
repeatType: "reverse",
|
||||||
|
ease: "easeInOut",
|
||||||
|
}}
|
||||||
|
className="absolute top-0 right-0 w-screen h-screen z-40 pointer-events-none"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
transform: `translateY(${translateY}px) rotate(45deg)`,
|
||||||
|
background: gradientFirst,
|
||||||
|
width: `${width}px`,
|
||||||
|
height: `${height}px`,
|
||||||
|
}}
|
||||||
|
className={`absolute top-0 right-0`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
transform: "rotate(45deg) translate(-5%, -50%)",
|
||||||
|
background: gradientSecond,
|
||||||
|
width: `${smallWidth}px`,
|
||||||
|
height: `${height}px`,
|
||||||
|
}}
|
||||||
|
className={`absolute top-0 right-0 origin-top-right`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
transform: "rotate(45deg) translate(180%, -70%)",
|
||||||
|
background: gradientThird,
|
||||||
|
width: `${smallWidth}px`,
|
||||||
|
height: `${height}px`,
|
||||||
|
}}
|
||||||
|
className={`absolute top-0 right-0 origin-top-right`}
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1,176 +1,159 @@
|
|||||||
'use client';
|
"use client";
|
||||||
import { useScrollAnimation } from '@/hooks/useScrollAnimation';
|
import { useScrollAnimation } from "@/hooks/useScrollAnimation";
|
||||||
import {
|
import {
|
||||||
MessageSquare,
|
MessageSquare,
|
||||||
Brain,
|
Brain,
|
||||||
Shield,
|
Shield,
|
||||||
BarChart3,
|
BarChart3,
|
||||||
Bell,
|
Bell,
|
||||||
Lock,
|
Lock,
|
||||||
Sparkles,
|
Sparkles,
|
||||||
Link,
|
Link,
|
||||||
Zap,
|
Zap,
|
||||||
Check,
|
Check,
|
||||||
TrendingUp
|
TrendingUp,
|
||||||
} from 'lucide-react';
|
} from "lucide-react";
|
||||||
|
import { GlowingEffect } from "@/components/ui/glowing-effect";
|
||||||
// Feature Card Component
|
// Feature Card Component with Glowing Effect and Dotted Background
|
||||||
interface FeatureCardProps {
|
interface FeatureCardProps {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
icon: React.ElementType;
|
icon: React.ElementType;
|
||||||
gradient: string;
|
gradient: string;
|
||||||
size?: 'normal' | 'large' | 'wide';
|
gridArea: string;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
delay?: number;
|
delay?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function FeatureCard({
|
function FeatureCard({
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
icon: Icon,
|
icon: Icon,
|
||||||
gradient,
|
gradient,
|
||||||
size = 'normal',
|
gridArea,
|
||||||
children,
|
children,
|
||||||
delay = 0
|
delay = 0,
|
||||||
}: FeatureCardProps) {
|
}: FeatureCardProps) {
|
||||||
const { ref, isVisible } = useScrollAnimation<HTMLDivElement>({ threshold: 0.2 });
|
const { ref, isVisible } = useScrollAnimation<HTMLLIElement>({
|
||||||
|
threshold: 0.2,
|
||||||
const sizeClasses = {
|
});
|
||||||
normal: 'md:col-span-1 aspect-square',
|
|
||||||
large: 'md:col-span-2 md:row-span-2',
|
|
||||||
wide: 'md:col-span-2',
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<li
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={`relative group ${sizeClasses[size]} rounded-3xl overflow-hidden cursor-pointer hover-lift`}
|
className={`min-h-[16rem] list-none ${gridArea}`}
|
||||||
style={{
|
style={{
|
||||||
opacity: isVisible ? 1 : 0,
|
opacity: isVisible ? 1 : 0,
|
||||||
transform: isVisible ? 'translateY(0)' : 'translateY(30px)',
|
transform: isVisible ? "translateY(0)" : "translateY(30px)",
|
||||||
transition: `all 0.6s ease-out ${delay}s`,
|
transition: `all 0.6s cubic-bezier(0.16, 1, 0.3, 1) ${delay}s`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className={`absolute inset-0 ${gradient} backdrop-blur-xl`} />
|
<div className="relative h-full rounded-xl border border-slate-200/80 dark:border-slate-700/80 p-1.5 md:rounded-2xl md:p-2 hover:border-blue-500/40 dark:hover:border-blue-400/40 transition-colors duration-500 overflow-hidden">
|
||||||
<div className="absolute inset-0 bg-white/40 dark:bg-slate-900/40 backdrop-blur-xl" />
|
{/* Glowing Effect */}
|
||||||
<div className="absolute inset-0 border border-slate-200/50 dark:border-slate-700/50 rounded-3xl group-hover:border-blue-500/30 dark:group-hover:border-blue-400/30 transition-colors duration-300" />
|
<GlowingEffect
|
||||||
|
spread={40}
|
||||||
<div className="relative h-full p-6 md:p-8 flex flex-col">
|
glow={true}
|
||||||
{/* Icon */}
|
disabled={false}
|
||||||
<div className="mb-4">
|
proximity={60}
|
||||||
<div className="relative inline-flex p-3 rounded-2xl bg-gradient-to-br from-white/50 to-white/20 dark:from-slate-800/50 dark:to-slate-800/20 shadow-lg group-hover:shadow-xl transition-shadow duration-300">
|
inactiveZone={0.01}
|
||||||
<Icon className="w-8 h-8 text-blue-600 dark:text-blue-400" />
|
borderWidth={1.5}
|
||||||
<div className="absolute inset-0 bg-blue-500/20 blur-xl rounded-full opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
|
/>
|
||||||
|
<div className="relative flex h-full flex-col justify-between gap-3 overflow-hidden rounded-lg md:rounded-xl p-4 md:p-5 bg-white/60 dark:bg-slate-900/60 backdrop-blur-xl shadow-lg dark:shadow-[0px_0px_30px_0px_rgba(59,130,246,0.08)]">
|
||||||
|
<div className="relative flex flex-1 flex-col justify-between gap-3">
|
||||||
|
{/* Icon Container */}
|
||||||
|
<div className="relative inline-flex w-fit">
|
||||||
|
<div
|
||||||
|
className={`p-2.5 rounded-xl ${gradient} shadow-md group-hover:shadow-lg transition-all duration-500`}
|
||||||
|
>
|
||||||
|
<Icon className="w-5 h-5 text-white" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<h3 className="font-bold text-base md:text-lg text-slate-900 dark:text-white leading-tight">
|
||||||
|
{title}
|
||||||
|
</h3>
|
||||||
|
<p className="text-xs md:text-sm text-slate-600 dark:text-slate-400 leading-relaxed line-clamp-2">
|
||||||
|
{description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Animated Content */}
|
||||||
|
{children && <div className="mt-auto">{children}</div>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Content */}
|
|
||||||
<h3 className="text-xl md:text-2xl font-bold text-slate-800 dark:text-slate-200 mb-3">
|
|
||||||
{title}
|
|
||||||
</h3>
|
|
||||||
<p className="text-slate-600 dark:text-slate-400 text-sm md:text-base leading-relaxed">
|
|
||||||
{description}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{/* Custom Content */}
|
|
||||||
{children && (
|
|
||||||
<div className="mt-auto pt-4">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Hover Glow */}
|
|
||||||
<div className="absolute -inset-px bg-gradient-to-r from-blue-500/0 via-violet-500/0 to-teal-500/0 group-hover:from-blue-500/20 group-hover:via-violet-500/20 group-hover:to-teal-500/20 rounded-3xl opacity-0 group-hover:opacity-100 transition-opacity duration-500 blur-xl" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</li>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Animated Chat Messages
|
// Animated Chat Messages (Compact)
|
||||||
function ChatAnimation() {
|
function ChatAnimation() {
|
||||||
const messages = [
|
const messages = [
|
||||||
{ text: "What's the liability cap?", isUser: true },
|
{ text: "What's the liability cap?", isUser: true },
|
||||||
{ text: "The liability cap is $5M per Section 8.3", isUser: false },
|
{ text: "$5M per Section 8.3", isUser: false },
|
||||||
{ text: "When does this contract expire?", isUser: true },
|
|
||||||
{ text: "December 31, 2024 - 45 days remaining", isUser: false },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-6 space-y-3">
|
<div className="mt-2 space-y-2">
|
||||||
{messages.map((msg, i) => (
|
{messages.map((msg, i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className={`flex ${msg.isUser ? 'justify-end' : 'justify-start'}`}
|
className={`flex ${msg.isUser ? "justify-end" : "justify-start"}`}
|
||||||
style={{
|
style={{
|
||||||
animation: `slide-up 0.4s ease-out forwards`,
|
animation: `slide-up 0.3s ease-out forwards`,
|
||||||
animationDelay: `${i * 0.8 + 1}s`,
|
animationDelay: `${i * 0.6 + 1}s`,
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`max-w-[85%] px-4 py-2.5 rounded-2xl text-sm ${
|
className={`max-w-[90%] px-3 py-1.5 rounded-xl text-xs shadow-sm ${
|
||||||
msg.isUser
|
msg.isUser
|
||||||
? 'bg-blue-600 text-white rounded-tr-sm'
|
? "bg-blue-600 text-white rounded-tr-sm"
|
||||||
: 'bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-300 rounded-tl-sm'
|
: "bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-300 rounded-tl-sm"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{msg.text}
|
{msg.text}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{/* Typing Indicator */}
|
|
||||||
<div
|
|
||||||
className="flex justify-start"
|
|
||||||
style={{
|
|
||||||
animation: `fade-in 0.3s ease-out forwards`,
|
|
||||||
animationDelay: '4.5s',
|
|
||||||
opacity: 0,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="bg-slate-100 dark:bg-slate-800 rounded-2xl rounded-tl-sm px-4 py-3">
|
|
||||||
<div className="flex gap-1">
|
|
||||||
<span className="w-2 h-2 bg-slate-400 rounded-full animate-bounce" style={{ animationDelay: '0s' }} />
|
|
||||||
<span className="w-2 h-2 bg-slate-400 rounded-full animate-bounce" style={{ animationDelay: '0.2s' }} />
|
|
||||||
<span className="w-2 h-2 bg-slate-400 rounded-full animate-bounce" style={{ animationDelay: '0.4s' }} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Document Extraction Animation
|
// Document Extraction Animation (Compact)
|
||||||
function ExtractionAnimation() {
|
function ExtractionAnimation() {
|
||||||
const fields = [
|
const fields = [
|
||||||
{ label: 'Contract Type', value: 'Service Agreement', status: 'done' },
|
{ label: "Contract Type", value: "Service", status: "done" },
|
||||||
{ label: 'Parties', value: '3 identified', status: 'done' },
|
{ label: "Parties", value: "3 found", status: "done" },
|
||||||
{ label: 'Effective Date', value: 'Jan 1, 2024', status: 'done' },
|
{ label: "Term", value: "24 mo", status: "processing" },
|
||||||
{ label: 'Term', value: '24 months', status: 'processing' },
|
|
||||||
{ label: 'Value', value: 'Analyzing...', status: 'pending' },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-6 space-y-2">
|
<div className="mt-2 space-y-1.5">
|
||||||
{fields.map((field, i) => (
|
{fields.map((field, i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className="flex items-center justify-between p-3 rounded-xl bg-white/50 dark:bg-slate-800/50"
|
className="flex items-center justify-between p-2 rounded-lg bg-white/50 dark:bg-slate-800/50 backdrop-blur-sm"
|
||||||
style={{
|
style={{
|
||||||
animation: `slide-up 0.4s ease-out forwards`,
|
animation: `slide-up 0.3s ease-out forwards`,
|
||||||
animationDelay: `${i * 0.3 + 0.5}s`,
|
animationDelay: `${i * 0.2 + 0.5}s`,
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="text-xs text-slate-500 dark:text-slate-400">{field.label}</span>
|
<span className="text-[10px] text-slate-500 dark:text-slate-400 font-medium">
|
||||||
<div className="flex items-center gap-2">
|
{field.label}
|
||||||
<span className="text-sm font-medium text-slate-700 dark:text-slate-300">{field.value}</span>
|
</span>
|
||||||
{field.status === 'done' && <Check className="w-4 h-4 text-emerald-500" />}
|
<div className="flex items-center gap-1.5">
|
||||||
{field.status === 'processing' && (
|
<span className="text-xs font-semibold text-slate-700 dark:text-slate-300">
|
||||||
<div className="w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" />
|
{field.value}
|
||||||
|
</span>
|
||||||
|
{field.status === "done" && (
|
||||||
|
<Check className="w-3 h-3 text-emerald-500" />
|
||||||
)}
|
)}
|
||||||
{field.status === 'pending' && (
|
{field.status === "processing" && (
|
||||||
<div className="w-4 h-4 rounded-full bg-slate-300 dark:bg-slate-600" />
|
<div className="w-3 h-3 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -179,26 +162,26 @@ function ExtractionAnimation() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blockchain Animation
|
// Blockchain Animation (Compact)
|
||||||
function BlockchainAnimation() {
|
function BlockchainAnimation() {
|
||||||
return (
|
return (
|
||||||
<div className="mt-6 relative h-32">
|
<div className="mt-2 relative h-24">
|
||||||
{/* Nodes */}
|
{/* Nodes */}
|
||||||
{[0, 1, 2, 3].map((i) => (
|
{[0, 1, 2].map((i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className="absolute w-10 h-10 rounded-full bg-gradient-to-br from-violet-500 to-purple-600 flex items-center justify-center shadow-lg"
|
className="absolute w-8 h-8 rounded-full bg-gradient-to-br from-violet-500 to-purple-600 flex items-center justify-center shadow-lg"
|
||||||
style={{
|
style={{
|
||||||
left: `${i * 25}%`,
|
left: `${i * 33}%`,
|
||||||
top: i % 2 === 0 ? '20%' : '50%',
|
top: i % 2 === 0 ? "20%" : "50%",
|
||||||
animation: `float 3s ease-in-out infinite`,
|
animation: `float 3s ease-in-out infinite`,
|
||||||
animationDelay: `${i * 0.3}s`,
|
animationDelay: `${i * 0.3}s`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Link className="w-5 h-5 text-white" />
|
<Link className="w-4 h-4 text-white" />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{/* Connection Lines */}
|
{/* Connection Lines */}
|
||||||
<svg className="absolute inset-0 w-full h-full" style={{ zIndex: -1 }}>
|
<svg className="absolute inset-0 w-full h-full" style={{ zIndex: -1 }}>
|
||||||
<defs>
|
<defs>
|
||||||
@@ -207,32 +190,31 @@ function BlockchainAnimation() {
|
|||||||
<stop offset="100%" stopColor="#a855f7" stopOpacity="0.5" />
|
<stop offset="100%" stopColor="#a855f7" stopOpacity="0.5" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
{[0, 1, 2].map((i) => (
|
{[0, 1].map((i) => (
|
||||||
<line
|
<line
|
||||||
key={i}
|
key={i}
|
||||||
x1={`${i * 25 + 12}%`}
|
x1={`${i * 33 + 12}%`}
|
||||||
y1={i % 2 === 0 ? '35%' : '65%'}
|
y1={i % 2 === 0 ? "35%" : "65%"}
|
||||||
x2={`${(i + 1) * 25 + 12}%`}
|
x2={`${(i + 1) * 33 + 12}%`}
|
||||||
y2={i % 2 === 0 ? '65%' : '35%'}
|
y2={i % 2 === 0 ? "65%" : "35%"}
|
||||||
stroke="url(#lineGradient)"
|
stroke="url(#lineGradient)"
|
||||||
strokeWidth="2"
|
strokeWidth="2"
|
||||||
strokeDasharray="5,5"
|
strokeDasharray="4,4"
|
||||||
className="animate-pulse"
|
className="animate-pulse"
|
||||||
style={{ animationDelay: `${i * 0.2}s` }}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
{/* Transaction Hash */}
|
{/* Transaction Hash */}
|
||||||
<div
|
<div
|
||||||
className="absolute bottom-0 left-1/2 -translate-x-1/2 px-3 py-1.5 rounded-full bg-violet-500/10 dark:bg-violet-500/20"
|
className="absolute bottom-0 left-1/2 -translate-x-1/2 px-2.5 py-1 rounded-full bg-violet-500/15 dark:bg-violet-500/25 backdrop-blur-sm"
|
||||||
style={{
|
style={{
|
||||||
animation: `slide-up 0.5s ease-out forwards`,
|
animation: `slide-up 0.4s ease-out forwards`,
|
||||||
animationDelay: '1.5s',
|
animationDelay: "1.2s",
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="text-xs font-mono text-violet-600 dark:text-violet-400">
|
<span className="text-[10px] font-mono font-semibold text-violet-600 dark:text-violet-400">
|
||||||
0x7f8a...9b2c ✓
|
0x7f8a...9b2c ✓
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -240,83 +222,98 @@ function BlockchainAnimation() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dashboard Mini Preview
|
// Dashboard Mini Preview (Compact)
|
||||||
function DashboardPreview() {
|
function DashboardPreview() {
|
||||||
return (
|
return (
|
||||||
<div className="mt-6 grid grid-cols-3 gap-3">
|
<div className="mt-2 grid grid-cols-3 gap-2">
|
||||||
{/* Mini Chart */}
|
{/* Mini Chart */}
|
||||||
<div className="col-span-2 glass rounded-xl p-3">
|
<div className="col-span-2 bg-white/50 dark:bg-slate-800/50 backdrop-blur-sm rounded-lg p-2 shadow-sm">
|
||||||
<div className="flex items-end gap-1 h-16">
|
<div className="flex items-end gap-0.5 h-14">
|
||||||
{[30, 50, 40, 70, 55, 80, 65, 90, 75, 85].map((h, i) => (
|
{[30, 50, 40, 70, 55, 80, 65].map((h, i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className="flex-1 bg-gradient-to-t from-blue-500 to-violet-500 rounded-t-sm"
|
className="flex-1 bg-gradient-to-t from-blue-500 to-blue-400 rounded-t-sm transition-all duration-300 hover:opacity-80"
|
||||||
style={{ height: `${h}%` }}
|
style={{
|
||||||
|
height: `${h}%`,
|
||||||
|
animation: `slide-up 0.3s ease-out forwards`,
|
||||||
|
animationDelay: `${i * 0.08 + 0.4}s`,
|
||||||
|
opacity: 0,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Stats */}
|
{/* Stats */}
|
||||||
<div className="space-y-2">
|
<div className="space-y-1.5">
|
||||||
<div className="glass rounded-lg p-2 text-center">
|
<div className="bg-white/50 dark:bg-slate-800/50 backdrop-blur-sm rounded-lg p-2 text-center shadow-sm">
|
||||||
<TrendingUp className="w-4 h-4 mx-auto text-emerald-500 mb-1" />
|
<TrendingUp className="w-4 h-4 mx-auto text-emerald-500 mb-0.5" />
|
||||||
<span className="text-xs font-bold text-slate-700 dark:text-slate-300">+24%</span>
|
<span className="text-xs font-bold text-slate-700 dark:text-slate-300">
|
||||||
|
+24%
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="glass rounded-lg p-2 text-center">
|
<div className="bg-white/50 dark:bg-slate-800/50 backdrop-blur-sm rounded-lg p-2 text-center shadow-sm">
|
||||||
<Zap className="w-4 h-4 mx-auto text-amber-500 mb-1" />
|
<Zap className="w-4 h-4 mx-auto text-amber-500 mb-0.5" />
|
||||||
<span className="text-xs font-bold text-slate-700 dark:text-slate-300">98.9%</span>
|
<span className="text-xs font-bold text-slate-700 dark:text-slate-300">
|
||||||
|
98.9%
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notification Animation
|
// Notification Animation (Compact)
|
||||||
function NotificationAnimation() {
|
function NotificationAnimation() {
|
||||||
const notifications = [
|
const notifications = [
|
||||||
{ icon: Bell, text: 'Contract renewal in 7 days', color: 'text-amber-500' },
|
{ icon: Bell, text: "Renewal in 7 days", color: "text-amber-500" },
|
||||||
{ icon: Check, text: 'Document verified', color: 'text-emerald-500' },
|
{ icon: Check, text: "Doc verified", color: "text-emerald-500" },
|
||||||
{ icon: Sparkles, text: 'AI analysis complete', color: 'text-blue-500' },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-6 space-y-2">
|
<div className="mt-2 space-y-1.5">
|
||||||
{notifications.map((notif, i) => (
|
{notifications.map((notif, i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className="flex items-center gap-3 p-3 rounded-xl bg-white/50 dark:bg-slate-800/50"
|
className="flex items-center gap-2 p-2 rounded-lg bg-white/50 dark:bg-slate-800/50 backdrop-blur-sm"
|
||||||
style={{
|
style={{
|
||||||
animation: `slide-up 0.4s ease-out forwards`,
|
animation: `slide-up 0.3s ease-out forwards`,
|
||||||
animationDelay: `${i * 0.5 + 0.8}s`,
|
animationDelay: `${i * 0.4 + 0.6}s`,
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<notif.icon className={`w-5 h-5 ${notif.color}`} />
|
<notif.icon className={`w-4 h-4 flex-shrink-0 ${notif.color}`} />
|
||||||
<span className="text-sm text-slate-700 dark:text-slate-300">{notif.text}</span>
|
<span className="text-xs text-slate-700 dark:text-slate-300 font-medium truncate">
|
||||||
|
{notif.text}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Security Animation
|
// Security Animation (Compact)
|
||||||
function SecurityAnimation() {
|
function SecurityAnimation() {
|
||||||
return (
|
return (
|
||||||
<div className="mt-6 flex flex-col items-center">
|
<div className="mt-2 flex flex-col items-center">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className="w-20 h-20 rounded-full bg-gradient-to-br from-emerald-500 to-green-600 flex items-center justify-center shadow-lg animate-pulse-glow">
|
<div className="w-16 h-16 rounded-full bg-gradient-to-br from-emerald-500 to-green-600 flex items-center justify-center shadow-xl animate-pulse-glow">
|
||||||
<Lock className="w-10 h-10 text-white" />
|
<Lock className="w-8 h-8 text-white" />
|
||||||
</div>
|
</div>
|
||||||
<div className="absolute -top-1 -right-1 w-6 h-6 rounded-full bg-emerald-500 flex items-center justify-center">
|
<div className="absolute -top-0.5 -right-0.5 w-5 h-5 rounded-full bg-emerald-500 flex items-center justify-center shadow-md">
|
||||||
<Check className="w-4 h-4 text-white" />
|
<Check className="w-3 h-3 text-white" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 flex gap-2 flex-wrap justify-center">
|
<div className="mt-3 flex gap-1.5 flex-wrap justify-center">
|
||||||
{['AES-256', 'GDPR', 'ISO 27001'].map((badge, i) => (
|
{["AES-256", "GDPR", "ISO"].map((badge, i) => (
|
||||||
<span
|
<span
|
||||||
key={i}
|
key={i}
|
||||||
className="px-3 py-1 rounded-full text-xs font-medium bg-emerald-500/10 text-emerald-600 dark:text-emerald-400"
|
className="px-2.5 py-1 rounded-full text-[10px] font-bold bg-emerald-500/15 dark:bg-emerald-500/25 text-emerald-600 dark:text-emerald-400"
|
||||||
|
style={{
|
||||||
|
animation: `slide-up 0.3s ease-out forwards`,
|
||||||
|
animationDelay: `${i * 0.15 + 0.4}s`,
|
||||||
|
opacity: 0,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{badge}
|
{badge}
|
||||||
</span>
|
</span>
|
||||||
@@ -327,88 +324,104 @@ function SecurityAnimation() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function Features() {
|
export function Features() {
|
||||||
const { ref: headerRef, isVisible: headerVisible } = useScrollAnimation<HTMLDivElement>();
|
const { ref: headerRef, isVisible: headerVisible } =
|
||||||
|
useScrollAnimation<HTMLDivElement>();
|
||||||
|
|
||||||
const features = [
|
const features = [
|
||||||
{
|
{
|
||||||
title: 'AI-Powered Conversational Assistant',
|
title: "AI-Powered Assistant",
|
||||||
description: 'Ask any question about your contracts. Our AI understands legal context and responds in seconds with precise answers.',
|
description:
|
||||||
|
"Ask questions about your contracts and get instant, precise answers with legal context.",
|
||||||
icon: MessageSquare,
|
icon: MessageSquare,
|
||||||
gradient: 'card-gradient-blue',
|
gradient: "bg-gradient-to-br from-blue-500 to-blue-600",
|
||||||
size: 'large' as const,
|
gridArea: "md:[grid-area:1/1/2/3]",
|
||||||
content: <ChatAnimation />,
|
content: <ChatAnimation />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Intelligent Document Extraction',
|
title: "Document Extraction",
|
||||||
description: 'Advanced OCR + AI automatically extracts and structures all information from your PDF documents.',
|
description:
|
||||||
|
"Advanced OCR + AI extracts and structures information from PDFs automatically.",
|
||||||
icon: Brain,
|
icon: Brain,
|
||||||
gradient: 'card-gradient-teal',
|
gradient: "bg-gradient-to-br from-teal-500 to-teal-600",
|
||||||
|
gridArea: "md:[grid-area:1/3/2/4]",
|
||||||
content: <ExtractionAnimation />,
|
content: <ExtractionAnimation />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Blockchain Proof of Submission',
|
title: "Blockchain Proof",
|
||||||
description: 'Immutable timestamping on Polygon. Cryptographic proof that\'s legally valid and instantly verifiable.',
|
description:
|
||||||
|
"Immutable timestamping on Polygon with cryptographic verification.",
|
||||||
icon: Shield,
|
icon: Shield,
|
||||||
gradient: 'card-gradient-violet',
|
gradient: "bg-gradient-to-br from-violet-500 to-purple-600",
|
||||||
|
gridArea: "md:[grid-area:2/3/3/4]",
|
||||||
content: <BlockchainAnimation />,
|
content: <BlockchainAnimation />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Comprehensive Dashboard & Analytics',
|
title: "Analytics Dashboard",
|
||||||
description: 'Visualize all contracts, renewal alerts, and detailed analytics in one beautiful interface.',
|
description:
|
||||||
|
"Visualize contracts, renewals, and analytics in one interface.",
|
||||||
icon: BarChart3,
|
icon: BarChart3,
|
||||||
gradient: 'from-blue-500/10 via-violet-500/10 to-teal-500/10',
|
gradient: "bg-gradient-to-br from-indigo-500 to-indigo-600",
|
||||||
size: 'wide' as const,
|
gridArea: "md:[grid-area:2/1/3/3]",
|
||||||
content: <DashboardPreview />,
|
content: <DashboardPreview />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Smart Notifications',
|
title: "Smart Alerts",
|
||||||
description: 'Automated alerts for renewals, deadlines, and important contract events. Never miss a date.',
|
description:
|
||||||
|
"Automated notifications for renewals, deadlines, and key events.",
|
||||||
icon: Bell,
|
icon: Bell,
|
||||||
gradient: 'card-gradient-amber',
|
gradient: "bg-gradient-to-br from-amber-500 to-orange-600",
|
||||||
|
gridArea: "md:[grid-area:3/3/4/4]",
|
||||||
content: <NotificationAnimation />,
|
content: <NotificationAnimation />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Enterprise Security',
|
title: "Enterprise Security",
|
||||||
description: 'AES-256 encryption, GDPR compliant, secure hosting. Your data is protected at every level.',
|
description: "AES-256 encryption, GDPR compliant with secure hosting.",
|
||||||
icon: Lock,
|
icon: Lock,
|
||||||
gradient: 'card-gradient-emerald',
|
gradient: "bg-gradient-to-br from-emerald-500 to-green-600",
|
||||||
|
gridArea: "md:[grid-area:3/1/4/3]",
|
||||||
content: <SecurityAnimation />,
|
content: <SecurityAnimation />,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="features" className="relative py-24 px-4 sm:px-6 lg:px-8 overflow-hidden">
|
<section
|
||||||
|
id="features"
|
||||||
|
className="relative pt-16 pb-0 px-4 sm:px-6 lg:px-8 overflow-hidden"
|
||||||
|
>
|
||||||
{/* Background */}
|
{/* Background */}
|
||||||
<div className="absolute inset-0 gradient-bg-mesh opacity-50" />
|
<div className="absolute inset-0 gradient-bg-mesh opacity-30" />
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-blue-50/50 to-transparent dark:via-slate-900/50" />
|
||||||
|
|
||||||
<div className="relative max-w-7xl mx-auto">
|
<div className="relative max-w-6xl mx-auto pb-6">
|
||||||
{/* Section Header */}
|
{/* Section Header */}
|
||||||
<div
|
<div
|
||||||
ref={headerRef}
|
ref={headerRef}
|
||||||
className="text-center mb-16"
|
className="text-center mb-12"
|
||||||
style={{
|
style={{
|
||||||
opacity: headerVisible ? 1 : 0,
|
opacity: headerVisible ? 1 : 0,
|
||||||
transform: headerVisible ? 'translateY(0)' : 'translateY(30px)',
|
transform: headerVisible ? "translateY(0)" : "translateY(20px)",
|
||||||
transition: 'all 0.6s ease-out',
|
transition: "all 0.6s cubic-bezier(0.16, 1, 0.3, 1)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full glass mb-6">
|
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full glass mb-6 shadow-md">
|
||||||
<Sparkles className="w-4 h-4 text-blue-600 dark:text-blue-400" />
|
<Sparkles className="w-4 h-4 text-blue-600 dark:text-blue-400" />
|
||||||
<span className="text-sm font-medium text-slate-700 dark:text-slate-300">Features</span>
|
<span className="text-xs font-bold text-slate-700 dark:text-slate-300">
|
||||||
|
Features
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 className="text-4xl md:text-5xl font-bold text-slate-900 dark:text-white mb-4">
|
<h2 className="text-3xl md:text-5xl font-black text-slate-900 dark:text-white mb-4 leading-tight">
|
||||||
Everything You Need to{' '}
|
Everything You Need to{" "}
|
||||||
<span className="gradient-text">Manage Contracts</span>
|
<span className="gradient-text">Manage Contracts</span>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p className="text-xl text-slate-600 dark:text-slate-400 max-w-2xl mx-auto">
|
<p className="text-lg md:text-xl text-slate-600 dark:text-slate-400 max-w-2xl mx-auto leading-relaxed">
|
||||||
Powerful AI combined with blockchain security. Built for professionals.
|
Powerful AI combined with blockchain security.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Bento Grid */}
|
{/* Bento Grid - Compact */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
<ul className="grid grid-cols-1 grid-rows-none gap-3 md:grid-cols-3 md:grid-rows-3 lg:gap-4">
|
||||||
{features.map((feature, index) => (
|
{features.map((feature, index) => (
|
||||||
<FeatureCard
|
<FeatureCard
|
||||||
key={feature.title}
|
key={feature.title}
|
||||||
@@ -416,13 +429,13 @@ export function Features() {
|
|||||||
description={feature.description}
|
description={feature.description}
|
||||||
icon={feature.icon}
|
icon={feature.icon}
|
||||||
gradient={feature.gradient}
|
gradient={feature.gradient}
|
||||||
size={feature.size}
|
gridArea={feature.gridArea}
|
||||||
delay={index * 0.1}
|
delay={index * 0.08}
|
||||||
>
|
>
|
||||||
{feature.content}
|
{feature.content}
|
||||||
</FeatureCard>
|
</FeatureCard>
|
||||||
))}
|
))}
|
||||||
</div>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,36 +1,8 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useScrollAnimation } from "@/hooks/useScrollAnimation";
|
import { useScrollAnimation } from "@/hooks/useScrollAnimation";
|
||||||
import { useTheme } from "@/hooks/useTheme";
|
import { Sparkles, Github, Twitter, Linkedin, Mail } from "lucide-react";
|
||||||
import {
|
import Image from "next/image";
|
||||||
Sparkles,
|
|
||||||
Github,
|
|
||||||
Twitter,
|
|
||||||
Linkedin,
|
|
||||||
Mail,
|
|
||||||
ArrowRight,
|
|
||||||
Sun,
|
|
||||||
Moon,
|
|
||||||
} from "lucide-react";
|
|
||||||
|
|
||||||
// Footer Link Component
|
|
||||||
function FooterLink({
|
|
||||||
href,
|
|
||||||
children,
|
|
||||||
}: {
|
|
||||||
href: string;
|
|
||||||
children: React.ReactNode;
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
href={href}
|
|
||||||
className="group flex items-center gap-1 text-sm text-slate-400 hover:text-white transition-colors duration-200"
|
|
||||||
>
|
|
||||||
<span>{children}</span>
|
|
||||||
<ArrowRight className="w-3 h-3 opacity-0 -translate-x-2 group-hover:opacity-100 group-hover:translate-x-0 transition-all duration-200" />
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Social Icon Component
|
// Social Icon Component
|
||||||
function SocialIcon({
|
function SocialIcon({
|
||||||
@@ -48,7 +20,7 @@ function SocialIcon({
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
aria-label={label}
|
aria-label={label}
|
||||||
className="w-10 h-10 rounded-full bg-white/5 backdrop-blur-sm border border-white/10 flex items-center justify-center text-white/70 hover:bg-white/10 hover:text-white hover:scale-110 transition-all duration-200"
|
className="text-slate-500 hover:text-slate-900 dark:hover:text-white transition-colors duration-200"
|
||||||
>
|
>
|
||||||
<Icon className="w-5 h-5" />
|
<Icon className="w-5 h-5" />
|
||||||
</a>
|
</a>
|
||||||
@@ -59,80 +31,72 @@ export function Footer() {
|
|||||||
const { ref, isVisible } = useScrollAnimation<HTMLElement>({
|
const { ref, isVisible } = useScrollAnimation<HTMLElement>({
|
||||||
threshold: 0.1,
|
threshold: 0.1,
|
||||||
});
|
});
|
||||||
const { theme, toggleTheme, mounted } = useTheme();
|
|
||||||
|
|
||||||
const productLinks = [
|
const navLinks = [
|
||||||
{ label: "Features", href: "#features" },
|
{ label: "Features", href: "#features" },
|
||||||
{ label: "How It Works", href: "#how-it-works" },
|
{ label: "How It Works", href: "#how-it-works" },
|
||||||
{ label: "Documentation", href: "#" },
|
{ label: "About", href: "#about" },
|
||||||
{ label: "API Access", href: "#" },
|
|
||||||
{ label: "Updates", href: "#" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const resourceLinks = [
|
|
||||||
{ label: "Blog", href: "#" },
|
|
||||||
{ label: "Guides", href: "#" },
|
|
||||||
{ label: "FAQ", href: "#" },
|
|
||||||
{ label: "Support", href: "#" },
|
|
||||||
{ label: "Contact", href: "#" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const legalLinks = [
|
|
||||||
{ label: "Privacy Policy", href: "#" },
|
|
||||||
{ label: "Terms of Service", href: "#" },
|
|
||||||
{ label: "Cookie Policy", href: "#" },
|
|
||||||
{ label: "Security", href: "#" },
|
|
||||||
{ label: "GDPR", href: "#" },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer
|
<footer
|
||||||
id="footer"
|
id="footer"
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className="relative bg-slate-900 dark:bg-slate-950 pt-16 pb-8 px-4 sm:px-6 lg:px-8"
|
className="relative bg-white dark:bg-slate-950 border-t border-slate-200 dark:border-slate-800 py-12 px-4 sm:px-6 lg:px-8"
|
||||||
>
|
>
|
||||||
{/* Top Gradient Line */}
|
|
||||||
<div className="absolute top-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-blue-500/50 to-transparent" />
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="max-w-7xl mx-auto"
|
className="max-w-7xl mx-auto"
|
||||||
style={{
|
style={{
|
||||||
opacity: isVisible ? 1 : 0,
|
opacity: isVisible ? 1 : 0,
|
||||||
transform: isVisible ? "translateY(0)" : "translateY(30px)",
|
transform: isVisible ? "translateY(0)" : "translateY(20px)",
|
||||||
transition: "all 0.6s ease-out",
|
transition: "all 0.6s ease-out",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Main Footer Content */}
|
{/* Main Content */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-12 gap-12 lg:gap-8 mb-12">
|
<div className="flex flex-col items-center space-y-8">
|
||||||
{/* Brand Column */}
|
{/* Logo */}
|
||||||
<div className="lg:col-span-4">
|
<a href="#" className="inline-flex items-center gap-2 group">
|
||||||
{/* Logo */}
|
<div className="relative">
|
||||||
<a href="#" className="inline-flex items-center gap-2 group mb-4">
|
<Image
|
||||||
<div className="relative">
|
src="/LexiChain.png"
|
||||||
<Sparkles className="w-8 h-8 text-blue-500 transition-transform duration-300 group-hover:rotate-12" />
|
alt="LexiChain Logo"
|
||||||
<div className="absolute inset-0 bg-blue-500/30 blur-lg rounded-full opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
|
width={48}
|
||||||
</div>
|
height={48}
|
||||||
<span className="text-2xl font-bold gradient-text">
|
className="
|
||||||
Smart-Admin Copilot
|
relative z-10
|
||||||
</span>
|
w-12 h-12 object-contain
|
||||||
</a>
|
transition-all duration-300 ease-out
|
||||||
|
group-hover:scale-110
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
<p className="text-sm text-slate-400 mb-2">
|
{/* Navigation Links */}
|
||||||
AI-powered contract intelligence
|
<nav className="flex items-center gap-8">
|
||||||
</p>
|
{navLinks.map((link) => (
|
||||||
<p className="text-sm text-slate-500 leading-relaxed max-w-xs mb-6">
|
<a
|
||||||
Transform your contract management with cutting-edge AI and
|
key={link.label}
|
||||||
blockchain technology. Built for banking, financial services, and
|
href={link.href}
|
||||||
insurance.
|
className="text-sm text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white transition-colors duration-200"
|
||||||
|
>
|
||||||
|
{link.label}
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{/* Divider */}
|
||||||
|
<div className="w-full max-w-4xl h-px bg-slate-200 dark:bg-slate-800" />
|
||||||
|
|
||||||
|
{/* Bottom Row */}
|
||||||
|
<div className="flex items-center gap-8">
|
||||||
|
{/* Copyright */}
|
||||||
|
<p className="text-sm text-slate-500 dark:text-slate-500">
|
||||||
|
© LexiChain
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{/* Social Icons */}
|
{/* Social Icons */}
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-4">
|
||||||
<SocialIcon
|
|
||||||
icon={Github}
|
|
||||||
href="https://github.com"
|
|
||||||
label="GitHub"
|
|
||||||
/>
|
|
||||||
<SocialIcon
|
<SocialIcon
|
||||||
icon={Twitter}
|
icon={Twitter}
|
||||||
href="https://twitter.com"
|
href="https://twitter.com"
|
||||||
@@ -143,103 +107,18 @@ export function Footer() {
|
|||||||
href="https://linkedin.com"
|
href="https://linkedin.com"
|
||||||
label="LinkedIn"
|
label="LinkedIn"
|
||||||
/>
|
/>
|
||||||
|
<SocialIcon
|
||||||
|
icon={Github}
|
||||||
|
href="https://github.com"
|
||||||
|
label="GitHub"
|
||||||
|
/>
|
||||||
<SocialIcon
|
<SocialIcon
|
||||||
icon={Mail}
|
icon={Mail}
|
||||||
href="mailto:contact@smartadmin.com"
|
href="mailto:contact@lexichain.com"
|
||||||
label="Email"
|
label="Email"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Product Links */}
|
|
||||||
<div className="lg:col-span-2 lg:col-start-6">
|
|
||||||
<h3 className="text-white font-semibold mb-4">Product</h3>
|
|
||||||
<ul className="space-y-3">
|
|
||||||
{productLinks.map((link) => (
|
|
||||||
<li key={link.label}>
|
|
||||||
<FooterLink href={link.href}>{link.label}</FooterLink>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Resources Links */}
|
|
||||||
<div className="lg:col-span-2">
|
|
||||||
<h3 className="text-white font-semibold mb-4">Resources</h3>
|
|
||||||
<ul className="space-y-3">
|
|
||||||
{resourceLinks.map((link) => (
|
|
||||||
<li key={link.label}>
|
|
||||||
<FooterLink href={link.href}>{link.label}</FooterLink>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Legal Links */}
|
|
||||||
<div className="lg:col-span-2">
|
|
||||||
<h3 className="text-white font-semibold mb-4">Legal</h3>
|
|
||||||
<ul className="space-y-3">
|
|
||||||
{legalLinks.map((link) => (
|
|
||||||
<li key={link.label}>
|
|
||||||
<FooterLink href={link.href}>{link.label}</FooterLink>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Divider */}
|
|
||||||
<div className="h-px bg-slate-800 mb-8" />
|
|
||||||
|
|
||||||
{/* Bottom Bar */}
|
|
||||||
<div className="flex flex-col md:flex-row items-center justify-between gap-4">
|
|
||||||
{/* Copyright */}
|
|
||||||
<p className="text-sm text-slate-500">
|
|
||||||
© 2024 Smart-Admin Copilot. All rights reserved.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{/* Right Side */}
|
|
||||||
<div className="flex items-center gap-4">
|
|
||||||
{/* Language Selector */}
|
|
||||||
<button className="flex items-center gap-2 px-3 py-1.5 rounded-full bg-white/5 border border-white/10 text-sm text-slate-400 hover:text-white hover:bg-white/10 transition-all duration-200">
|
|
||||||
<span className="text-lg">🇬🇧</span>
|
|
||||||
<span>English</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{/* Theme Toggle */}
|
|
||||||
<button
|
|
||||||
onClick={toggleTheme}
|
|
||||||
className="flex items-center gap-2 px-3 py-1.5 rounded-full bg-white/5 border border-white/10 text-sm text-slate-400 hover:text-white hover:bg-white/10 transition-all duration-200"
|
|
||||||
aria-label="Toggle theme"
|
|
||||||
>
|
|
||||||
{mounted ? (
|
|
||||||
theme === "light" ? (
|
|
||||||
<>
|
|
||||||
<Sun className="w-4 h-4" />
|
|
||||||
<span>Light</span>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<Moon className="w-4 h-4" />
|
|
||||||
<span>Dark</span>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<Sun className="w-4 h-4" />
|
|
||||||
<span>Theme</span>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Made With Love */}
|
|
||||||
<div className="mt-8 text-center">
|
|
||||||
<p className="text-xs text-slate-600">
|
|
||||||
Made with <span className="text-red-500">♥</span> for your PFE
|
|
||||||
project
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState, useRef, useMemo } from "react";
|
import { useEffect, useState, useRef, useMemo } from "react";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Sparkles,
|
Sparkles,
|
||||||
Rocket,
|
Rocket,
|
||||||
Play,
|
|
||||||
Lock,
|
Lock,
|
||||||
Check,
|
Check,
|
||||||
Zap,
|
Zap,
|
||||||
@@ -16,6 +16,213 @@ import {
|
|||||||
Bell,
|
Bell,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
|
||||||
|
// Ripple Effect Component
|
||||||
|
function BackgroundRipple() {
|
||||||
|
return (
|
||||||
|
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||||
|
<svg
|
||||||
|
className="absolute inset-0 w-full h-full"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<defs>
|
||||||
|
<linearGradient
|
||||||
|
id="ripple-gradient-1"
|
||||||
|
x1="0%"
|
||||||
|
y1="0%"
|
||||||
|
x2="100%"
|
||||||
|
y2="100%"
|
||||||
|
>
|
||||||
|
<stop offset="0%" stopColor="rgb(59, 130, 246)" stopOpacity="0.3" />
|
||||||
|
<stop
|
||||||
|
offset="50%"
|
||||||
|
stopColor="rgb(139, 92, 246)"
|
||||||
|
stopOpacity="0.2"
|
||||||
|
/>
|
||||||
|
<stop
|
||||||
|
offset="100%"
|
||||||
|
stopColor="rgb(20, 184, 166)"
|
||||||
|
stopOpacity="0.1"
|
||||||
|
/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="ripple-gradient-2"
|
||||||
|
x1="100%"
|
||||||
|
y1="0%"
|
||||||
|
x2="0%"
|
||||||
|
y2="100%"
|
||||||
|
>
|
||||||
|
<stop offset="0%" stopColor="rgb(139, 92, 246)" stopOpacity="0.3" />
|
||||||
|
<stop
|
||||||
|
offset="50%"
|
||||||
|
stopColor="rgb(59, 130, 246)"
|
||||||
|
stopOpacity="0.2"
|
||||||
|
/>
|
||||||
|
<stop
|
||||||
|
offset="100%"
|
||||||
|
stopColor="rgb(20, 184, 166)"
|
||||||
|
stopOpacity="0.1"
|
||||||
|
/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
{/* First set of ripples */}
|
||||||
|
<circle
|
||||||
|
cx="50%"
|
||||||
|
cy="50%"
|
||||||
|
r="0"
|
||||||
|
fill="none"
|
||||||
|
stroke="url(#ripple-gradient-1)"
|
||||||
|
strokeWidth="2"
|
||||||
|
opacity="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="r"
|
||||||
|
from="0"
|
||||||
|
to="800"
|
||||||
|
dur="8s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
values="0;0.5;0.3;0"
|
||||||
|
dur="8s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</circle>
|
||||||
|
|
||||||
|
<circle
|
||||||
|
cx="50%"
|
||||||
|
cy="50%"
|
||||||
|
r="0"
|
||||||
|
fill="none"
|
||||||
|
stroke="url(#ripple-gradient-2)"
|
||||||
|
strokeWidth="2"
|
||||||
|
opacity="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="r"
|
||||||
|
from="0"
|
||||||
|
to="800"
|
||||||
|
dur="8s"
|
||||||
|
begin="2s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
values="0;0.4;0.2;0"
|
||||||
|
dur="8s"
|
||||||
|
begin="2s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</circle>
|
||||||
|
|
||||||
|
<circle
|
||||||
|
cx="50%"
|
||||||
|
cy="50%"
|
||||||
|
r="0"
|
||||||
|
fill="none"
|
||||||
|
stroke="url(#ripple-gradient-1)"
|
||||||
|
strokeWidth="3"
|
||||||
|
opacity="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="r"
|
||||||
|
from="0"
|
||||||
|
to="800"
|
||||||
|
dur="8s"
|
||||||
|
begin="4s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
values="0;0.6;0.4;0"
|
||||||
|
dur="8s"
|
||||||
|
begin="4s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</circle>
|
||||||
|
|
||||||
|
<circle
|
||||||
|
cx="50%"
|
||||||
|
cy="50%"
|
||||||
|
r="0"
|
||||||
|
fill="none"
|
||||||
|
stroke="url(#ripple-gradient-2)"
|
||||||
|
strokeWidth="2"
|
||||||
|
opacity="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="r"
|
||||||
|
from="0"
|
||||||
|
to="800"
|
||||||
|
dur="8s"
|
||||||
|
begin="6s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
values="0;0.5;0.3;0"
|
||||||
|
dur="8s"
|
||||||
|
begin="6s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</circle>
|
||||||
|
|
||||||
|
{/* Additional slower ripples for depth */}
|
||||||
|
<circle
|
||||||
|
cx="50%"
|
||||||
|
cy="50%"
|
||||||
|
r="0"
|
||||||
|
fill="none"
|
||||||
|
stroke="url(#ripple-gradient-1)"
|
||||||
|
strokeWidth="4"
|
||||||
|
opacity="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="r"
|
||||||
|
from="0"
|
||||||
|
to="1000"
|
||||||
|
dur="12s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
values="0;0.3;0.15;0"
|
||||||
|
dur="12s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</circle>
|
||||||
|
|
||||||
|
<circle
|
||||||
|
cx="50%"
|
||||||
|
cy="50%"
|
||||||
|
r="0"
|
||||||
|
fill="none"
|
||||||
|
stroke="url(#ripple-gradient-2)"
|
||||||
|
strokeWidth="3"
|
||||||
|
opacity="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="r"
|
||||||
|
from="0"
|
||||||
|
to="1000"
|
||||||
|
dur="12s"
|
||||||
|
begin="4s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
values="0;0.25;0.12;0"
|
||||||
|
dur="12s"
|
||||||
|
begin="4s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</circle>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Floating Orb Component
|
// Floating Orb Component
|
||||||
function FloatingOrb({
|
function FloatingOrb({
|
||||||
size,
|
size,
|
||||||
@@ -211,7 +418,10 @@ export function Hero() {
|
|||||||
{/* Background Layer 1 - Animated Gradient Mesh */}
|
{/* Background Layer 1 - Animated Gradient Mesh */}
|
||||||
<div className="absolute inset-0 gradient-bg-mesh animate-gradient-shift" />
|
<div className="absolute inset-0 gradient-bg-mesh animate-gradient-shift" />
|
||||||
|
|
||||||
{/* Background Layer 2 - Grid Pattern */}
|
{/* Background Layer 2 - Ripple Effect */}
|
||||||
|
<BackgroundRipple />
|
||||||
|
|
||||||
|
{/* Background Layer 3 - Grid Pattern */}
|
||||||
<div
|
<div
|
||||||
className="absolute inset-0 grid-pattern"
|
className="absolute inset-0 grid-pattern"
|
||||||
style={{
|
style={{
|
||||||
@@ -222,7 +432,7 @@ export function Hero() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Background Layer 3 - Floating Orbs */}
|
{/* Background Layer 4 - Floating Orbs */}
|
||||||
<FloatingOrb
|
<FloatingOrb
|
||||||
size={200}
|
size={200}
|
||||||
color="rgba(59, 130, 246, 0.3)"
|
color="rgba(59, 130, 246, 0.3)"
|
||||||
@@ -264,7 +474,7 @@ export function Hero() {
|
|||||||
top="80%"
|
top="80%"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Background Layer 4 - Spotlight Effect */}
|
{/* Background Layer 5 - Spotlight Effect */}
|
||||||
<div
|
<div
|
||||||
className="absolute inset-0 pointer-events-none opacity-30 dark:opacity-20"
|
className="absolute inset-0 pointer-events-none opacity-30 dark:opacity-20"
|
||||||
style={{
|
style={{
|
||||||
@@ -289,13 +499,13 @@ export function Hero() {
|
|||||||
<div className="relative z-10 max-w-7xl mx-auto text-center">
|
<div className="relative z-10 max-w-7xl mx-auto text-center">
|
||||||
{/* Announcement Badge */}
|
{/* Announcement Badge */}
|
||||||
<div
|
<div
|
||||||
className={`inline-flex items-center gap-2 px-4 py-2 rounded-full glass mb-8 transition-all duration-700 ${
|
className={`inline-flex items-center gap-2 px-4 py-2 mt-4 rounded-full glass mb-8 transition-all duration-700 ${
|
||||||
isLoaded ? "opacity-100 translate-y-0" : "opacity-0 -translate-y-4"
|
isLoaded ? "opacity-100 translate-y-0" : "opacity-0 -translate-y-4"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<Sparkles className="w-4 h-4 text-blue-600 dark:text-blue-400 animate-spin-slow" />
|
<Sparkles className="w-4 h-4 text-blue-600 dark:text-blue-400 animate-spin-slow" />
|
||||||
<span className="text-sm font-medium text-slate-700 dark:text-slate-300">
|
<span className="text-sm font-medium text-slate-700 dark:text-slate-300">
|
||||||
New: GPT-4 Turbo + Blockchain Integration
|
Powered by Ai + Blockchain Integration
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -322,6 +532,7 @@ export function Hero() {
|
|||||||
AI-Powered contract analysis meets blockchain verification. The only
|
AI-Powered contract analysis meets blockchain verification. The only
|
||||||
platform that truly understands your banking and insurance documents.
|
platform that truly understands your banking and insurance documents.
|
||||||
<span className="text-blue-600 dark:text-blue-400 font-medium">
|
<span className="text-blue-600 dark:text-blue-400 font-medium">
|
||||||
|
{" "}
|
||||||
Secure, transparent, instant.
|
Secure, transparent, instant.
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
@@ -333,22 +544,60 @@ export function Hero() {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{/* Primary CTA */}
|
{/* Primary CTA */}
|
||||||
<button className="group relative px-8 py-4 text-base md:text-lg font-bold text-white btn-gradient rounded-2xl overflow-hidden">
|
<Button
|
||||||
<span className="relative z-10 flex items-center gap-2">
|
className="
|
||||||
Start Free Trial
|
group relative px-12 py-5
|
||||||
<Rocket className="w-5 h-5 transition-transform duration-300 group-hover:translate-x-1" />
|
text-lg md:text-xl font-semibold
|
||||||
</span>
|
text-white rounded-2xl
|
||||||
<div className="absolute inset-0 bg-gradient-to-r from-blue-500 via-violet-500 to-teal-500 opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
|
overflow-hidden
|
||||||
<div className="absolute inset-0 animate-shimmer opacity-30" />
|
bg-gradient-to-r
|
||||||
</button>
|
from-[hsl(var(--primary))]
|
||||||
|
via-[hsl(var(--accent))]
|
||||||
|
to-[hsl(var(--secondary))]
|
||||||
|
shadow-lg shadow-blue-500/20
|
||||||
|
transition-all duration-300 ease-out
|
||||||
|
hover:scale-[1.04]
|
||||||
|
hover:shadow-xl hover:shadow-blue-500/40
|
||||||
|
active:scale-[0.98]
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{/* Glow background layer */}
|
||||||
|
<div
|
||||||
|
className="
|
||||||
|
absolute inset-0
|
||||||
|
opacity-0 group-hover:opacity-100
|
||||||
|
transition-opacity duration-500
|
||||||
|
bg-gradient-to-r
|
||||||
|
from-blue-400/20
|
||||||
|
via-purple-400/20
|
||||||
|
to-teal-400/20
|
||||||
|
blur-xl
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Secondary CTA */}
|
{/* Animated gradient shift layer */}
|
||||||
<button className="group flex items-center gap-2 px-8 py-4 text-base md:text-lg font-semibold text-slate-900 dark:text-white bg-white/10 dark:bg-white/5 backdrop-blur-sm border border-white/20 rounded-2xl hover:bg-white/20 transition-all duration-300 hover:scale-105">
|
<div
|
||||||
<div className="p-2 rounded-full bg-blue-500/10 dark:bg-blue-500/20 group-hover:bg-blue-500/20 transition-colors">
|
className="
|
||||||
<Play className="w-4 h-4 text-blue-600 dark:text-blue-400" />
|
absolute inset-0
|
||||||
</div>
|
bg-[length:200%_200%]
|
||||||
Watch Demo
|
animate-gradient-shift
|
||||||
</button>
|
opacity-70
|
||||||
|
mix-blend-overlay
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<span className="relative z-10 flex items-center gap-3">
|
||||||
|
Get Started
|
||||||
|
<Rocket
|
||||||
|
className="
|
||||||
|
w-6 h-6
|
||||||
|
transition-transform duration-300
|
||||||
|
group-hover:translate-x-1
|
||||||
|
group-hover:-translate-y-1
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Trust Indicators */}
|
{/* Trust Indicators */}
|
||||||
@@ -468,10 +717,11 @@ export function Hero() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Right Column - Notifications */}
|
{/* Right Column - Notifications & Chart (Equal Heights) */}
|
||||||
<div className="space-y-4">
|
<div className="flex flex-col gap-6">
|
||||||
|
{/* Notifications - 50% height */}
|
||||||
<div
|
<div
|
||||||
className="glass rounded-xl p-4"
|
className="glass rounded-xl p-4 flex-1"
|
||||||
style={{
|
style={{
|
||||||
animation: `slide-up 0.6s ease-out forwards`,
|
animation: `slide-up 0.6s ease-out forwards`,
|
||||||
animationDelay: `1s`,
|
animationDelay: `1s`,
|
||||||
@@ -520,9 +770,9 @@ export function Hero() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Mini Chart */}
|
{/* Mini Chart - 50% height */}
|
||||||
<div
|
<div
|
||||||
className="glass rounded-xl p-4"
|
className="glass rounded-xl p-4 flex-1 flex flex-col"
|
||||||
style={{
|
style={{
|
||||||
animation: `slide-up 0.6s ease-out forwards`,
|
animation: `slide-up 0.6s ease-out forwards`,
|
||||||
animationDelay: `1.2s`,
|
animationDelay: `1.2s`,
|
||||||
@@ -532,7 +782,7 @@ export function Hero() {
|
|||||||
<span className="text-sm font-semibold text-slate-700 dark:text-slate-300 mb-3 block">
|
<span className="text-sm font-semibold text-slate-700 dark:text-slate-300 mb-3 block">
|
||||||
Processing Volume
|
Processing Volume
|
||||||
</span>
|
</span>
|
||||||
<div className="flex items-end gap-1 h-16">
|
<div className="flex items-end gap-1 flex-1">
|
||||||
{[40, 65, 45, 80, 55, 90, 70, 85, 60, 95, 75, 88].map(
|
{[40, 65, 45, 80, 55, 90, 70, 85, 60, 95, 75, 88].map(
|
||||||
(height, i) => (
|
(height, i) => (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { Features } from "@/components/views/Home/Features";
|
|||||||
import { HowItWorks } from "@/components/views/Home/HowItWorks";
|
import { HowItWorks } from "@/components/views/Home/HowItWorks";
|
||||||
import { Stats } from "@/components/views/Home/Stats";
|
import { Stats } from "@/components/views/Home/Stats";
|
||||||
import { Footer } from "@/components/views/Home/Footer";
|
import { Footer } from "@/components/views/Home/Footer";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
import { Sparkles } from "lucide-react";
|
import { Sparkles } from "lucide-react";
|
||||||
|
|
||||||
function LoadingScreen({ onComplete }: { onComplete: () => void }) {
|
function LoadingScreen({ onComplete }: { onComplete: () => void }) {
|
||||||
@@ -37,9 +38,7 @@ function LoadingScreen({ onComplete }: { onComplete: () => void }) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 className="text-2xl font-bold gradient-text mb-8">
|
<h1 className="text-2xl font-bold gradient-text mb-8">LexiChain</h1>
|
||||||
Smart-Admin Copilot
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<div className="w-64 h-1 bg-slate-800 rounded-full overflow-hidden">
|
<div className="w-64 h-1 bg-slate-800 rounded-full overflow-hidden">
|
||||||
<div
|
<div
|
||||||
@@ -98,7 +97,7 @@ function BackToTop() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<Button
|
||||||
onClick={scrollToTop}
|
onClick={scrollToTop}
|
||||||
className={`fixed bottom-8 right-8 z-50 w-12 h-12 rounded-full bg-gradient-to-r from-blue-600 to-violet-600 text-white shadow-lg hover:shadow-xl hover:scale-110 transition-all duration-300 flex items-center justify-center ${
|
className={`fixed bottom-8 right-8 z-50 w-12 h-12 rounded-full bg-gradient-to-r from-blue-600 to-violet-600 text-white shadow-lg hover:shadow-xl hover:scale-110 transition-all duration-300 flex items-center justify-center ${
|
||||||
isVisible
|
isVisible
|
||||||
@@ -120,7 +119,7 @@ function BackToTop() {
|
|||||||
d="M5 10l7-7m0 0l7 7m-7-7v18"
|
d="M5 10l7-7m0 0l7 7m-7-7v18"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,16 +14,19 @@ import {
|
|||||||
Target,
|
Target,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useScrollAnimation } from "@/hooks/useScrollAnimation";
|
import { useScrollAnimation } from "@/hooks/useScrollAnimation";
|
||||||
|
import { GlowingEffect } from "@/components/ui/glowing-effect";
|
||||||
|
import { BackgroundBeams } from "@/components/ui/background-beams";
|
||||||
|
|
||||||
// Step Card Component
|
// Step Card Component with Glowing Effect
|
||||||
interface StepCardProps {
|
interface StepCardProps {
|
||||||
number: string;
|
number: string;
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
icon: React.ElementType;
|
icon: React.ElementType;
|
||||||
gradient: string;
|
gradient: string;
|
||||||
|
glowColor: string;
|
||||||
delay: number;
|
delay: number;
|
||||||
isLast?: boolean;
|
children?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
function StepCard({
|
function StepCard({
|
||||||
@@ -32,111 +35,95 @@ function StepCard({
|
|||||||
description,
|
description,
|
||||||
icon: Icon,
|
icon: Icon,
|
||||||
gradient,
|
gradient,
|
||||||
|
glowColor,
|
||||||
delay,
|
delay,
|
||||||
isLast = false,
|
children,
|
||||||
}: StepCardProps) {
|
}: StepCardProps) {
|
||||||
const { ref, isVisible } = useScrollAnimation<HTMLDivElement>({
|
const { ref, isVisible } = useScrollAnimation<HTMLDivElement>({
|
||||||
threshold: 0.3,
|
threshold: 0.2,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="relative flex-1">
|
<div
|
||||||
{/* Connector Line - Desktop */}
|
ref={ref}
|
||||||
{!isLast && (
|
className="relative h-full"
|
||||||
<>
|
style={{
|
||||||
{/* Horizontal connector for desktop */}
|
opacity: isVisible ? 1 : 0,
|
||||||
<div className="hidden md:block absolute top-12 left-[60%] w-[80%] h-0.5">
|
transform: isVisible ? "translateY(0)" : "translateY(40px)",
|
||||||
<div className="relative w-full h-full overflow-hidden">
|
transition: `all 0.8s cubic-bezier(0.16, 1, 0.3, 1) ${delay}s`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Glowing Border Card */}
|
||||||
|
<div className="relative h-full rounded-2xl border border-slate-200/80 dark:border-slate-700/80 p-2 hover:border-blue-500/40 dark:hover:border-blue-400/40 transition-colors duration-500 overflow-hidden">
|
||||||
|
{/* Rainbow Glowing Effect */}
|
||||||
|
<GlowingEffect
|
||||||
|
spread={60}
|
||||||
|
glow={true}
|
||||||
|
disabled={false}
|
||||||
|
proximity={100}
|
||||||
|
inactiveZone={0.01}
|
||||||
|
borderWidth={2}
|
||||||
|
variant="default"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="relative h-full flex flex-col rounded-xl p-6 bg-white/90 dark:bg-slate-900/90 backdrop-blur-xl shadow-lg">
|
||||||
|
{/* Modern Number Badge */}
|
||||||
|
<div className="absolute -top-3 -right-3 z-10">
|
||||||
|
<div className="relative">
|
||||||
|
{/* Outer glow ring */}
|
||||||
<div
|
<div
|
||||||
className="absolute inset-0 bg-gradient-to-r from-blue-500 via-violet-500 to-teal-500"
|
className={`absolute inset-0 ${gradient} rounded-2xl blur-xl opacity-60 animate-pulse-glow`}
|
||||||
style={{
|
style={{ padding: "4px" }}
|
||||||
transform: isVisible ? "translateX(0)" : "translateX(-100%)",
|
|
||||||
transition: `transform 1s ease-out ${delay + 0.3}s`,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{/* Animated dots */}
|
|
||||||
<div
|
|
||||||
className="absolute top-1/2 -translate-y-1/2 w-2 h-2 rounded-full bg-violet-500"
|
|
||||||
style={{
|
|
||||||
animationName: isVisible ? "move-right" : "none",
|
|
||||||
animationDuration: isVisible ? "2s" : undefined,
|
|
||||||
animationTimingFunction: isVisible ? "linear" : undefined,
|
|
||||||
animationIterationCount: isVisible ? "infinite" : undefined,
|
|
||||||
animationFillMode: "forwards",
|
|
||||||
animationDelay: isVisible ? `${delay + 0.5}s` : undefined,
|
|
||||||
opacity: isVisible ? 1 : 0,
|
|
||||||
transition: `opacity 0.3s ease-out ${delay + 0.5}s`,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* Badge container */}
|
||||||
|
<div className="relative">
|
||||||
|
{/* Glass background */}
|
||||||
|
<div className="absolute inset-0 bg-white/90 dark:bg-slate-900/90 backdrop-blur-xl rounded-2xl" />
|
||||||
|
|
||||||
|
{/* Gradient border */}
|
||||||
|
<div
|
||||||
|
className={`absolute inset-0 ${gradient} rounded-2xl p-[2px]`}
|
||||||
|
>
|
||||||
|
<div className="w-full h-full bg-white dark:bg-slate-900 rounded-2xl" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Number */}
|
||||||
|
<div className="relative px-4 py-2 flex items-center justify-center">
|
||||||
|
<span
|
||||||
|
className={`text-2xl font-black bg-gradient-to-br ${gradient.replace("bg-", "from-")} to-transparent bg-clip-text text-transparent`}
|
||||||
|
>
|
||||||
|
{number}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Vertical connector for mobile */}
|
{/* Icon with Glow */}
|
||||||
<div className="md:hidden absolute top-20 left-8 w-0.5 h-[calc(100%-40px)]">
|
<div className="relative inline-flex mb-6">
|
||||||
<div
|
<div
|
||||||
className="w-full h-full bg-gradient-to-b from-blue-500 via-violet-500 to-teal-500"
|
className={`absolute inset-0 ${gradient} rounded-2xl blur-2xl opacity-40 animate-pulse-glow`}
|
||||||
style={{
|
|
||||||
transform: isVisible ? "scaleY(1)" : "scaleY(0)",
|
|
||||||
transformOrigin: "top",
|
|
||||||
transition: `transform 1s ease-out ${delay + 0.3}s`,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
<div
|
||||||
</>
|
className={`relative w-20 h-20 rounded-2xl ${gradient} flex items-center justify-center shadow-2xl`}
|
||||||
)}
|
>
|
||||||
|
<Icon className="w-10 h-10 text-white" />
|
||||||
{/* Card */}
|
</div>
|
||||||
<div
|
|
||||||
className="relative"
|
|
||||||
style={{
|
|
||||||
opacity: isVisible ? 1 : 0,
|
|
||||||
transform: isVisible ? "translateY(0)" : "translateY(30px)",
|
|
||||||
transition: `all 0.6s ease-out ${delay}s`,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{/* Icon with Number */}
|
|
||||||
<div className="relative inline-block mb-6">
|
|
||||||
<div
|
|
||||||
className={`w-24 h-24 rounded-full ${gradient} flex items-center justify-center shadow-lg`}
|
|
||||||
>
|
|
||||||
<Icon className="w-10 h-10 text-white" />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Number Badge */}
|
{/* Content */}
|
||||||
<div
|
<div className="flex-1">
|
||||||
className="absolute -top-2 -right-2 w-10 h-10 rounded-full bg-slate-800 dark:bg-slate-700 flex items-center justify-center shadow-lg"
|
<h3 className="text-xl md:text-2xl font-black text-slate-900 dark:text-white mb-3 leading-tight">
|
||||||
style={{
|
{title}
|
||||||
animationName: isVisible ? "bounce-subtle" : "none",
|
</h3>
|
||||||
animationDuration: isVisible ? "0.5s" : undefined,
|
<p className="text-sm md:text-base text-slate-600 dark:text-slate-400 leading-relaxed mb-4">
|
||||||
animationTimingFunction: isVisible ? "ease-out" : undefined,
|
{description}
|
||||||
animationDelay: `${delay + 0.2}s`,
|
</p>
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span className="text-lg font-bold text-white">{number}</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Glow Effect */}
|
{/* Animation Content */}
|
||||||
<div
|
{children && <div className="mt-auto">{children}</div>}
|
||||||
className={`absolute inset-0 rounded-full ${gradient} blur-xl opacity-50`}
|
|
||||||
style={{
|
|
||||||
animationName: isVisible ? "pulse-glow" : "none",
|
|
||||||
animationDuration: isVisible ? "3s" : undefined,
|
|
||||||
animationTimingFunction: isVisible ? "ease-in-out" : undefined,
|
|
||||||
animationIterationCount: isVisible ? "infinite" : undefined,
|
|
||||||
animationFillMode: "forwards",
|
|
||||||
animationDelay: isVisible ? `${delay + 0.5}s` : undefined,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Content */}
|
|
||||||
<div className="glass rounded-2xl p-6 hover-lift">
|
|
||||||
<h3 className="text-xl font-bold text-slate-800 dark:text-slate-200 mb-2">
|
|
||||||
{title}
|
|
||||||
</h3>
|
|
||||||
<p className="text-slate-600 dark:text-slate-400 text-sm leading-relaxed">
|
|
||||||
{description}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -150,52 +137,54 @@ function UploadAnimation() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="mt-6 glass rounded-xl p-4">
|
<div ref={ref} className="mt-4">
|
||||||
{/* Drop Zone */}
|
{/* Drop Zone */}
|
||||||
<div
|
<div
|
||||||
className="border-2 border-dashed border-blue-300 dark:border-blue-700 rounded-lg p-6 text-center"
|
className="relative border-2 border-dashed border-blue-400/60 dark:border-blue-500/60 rounded-xl p-4 text-center overflow-hidden group hover:border-blue-500 dark:hover:border-blue-400 transition-colors"
|
||||||
style={{
|
style={{
|
||||||
opacity: isVisible ? 1 : 0,
|
opacity: isVisible ? 1 : 0,
|
||||||
transform: isVisible ? "scale(1)" : "scale(0.95)",
|
transform: isVisible ? "scale(1)" : "scale(0.95)",
|
||||||
transition: "all 0.5s ease-out 0.3s",
|
transition: "all 0.5s ease-out 0.3s",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-br from-blue-500/5 via-violet-500/5 to-teal-500/5 opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
|
||||||
|
|
||||||
<Upload
|
<Upload
|
||||||
className="w-8 h-8 mx-auto text-blue-500 mb-2"
|
className="w-6 h-6 mx-auto text-blue-500 mb-2 relative z-10"
|
||||||
style={{
|
style={{
|
||||||
animation: isVisible
|
animation: isVisible
|
||||||
? "bounce-subtle 2s ease-in-out infinite"
|
? "bounce-subtle 2s ease-in-out infinite"
|
||||||
: "none",
|
: "none",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<p className="text-sm text-slate-600 dark:text-slate-400">
|
<p className="text-xs text-slate-600 dark:text-slate-400 relative z-10">
|
||||||
Drop files here or click to browse
|
Drop files here
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* File List */}
|
{/* File List */}
|
||||||
<div className="mt-4 space-y-2">
|
<div className="mt-3 space-y-2">
|
||||||
{[
|
{[
|
||||||
{ name: "contract_v2.pdf", size: "2.4 MB", progress: 100 },
|
{ name: "contract.pdf", size: "2.4 MB", progress: 100 },
|
||||||
{ name: "agreement_scan.jpg", size: "1.8 MB", progress: 75 },
|
{ name: "agreement.jpg", size: "1.8 MB", progress: 75 },
|
||||||
].map((file, i) => (
|
].map((file, i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className="flex items-center gap-3 p-2 rounded-lg bg-white/50 dark:bg-slate-800/50"
|
className="flex items-center gap-2 p-2 rounded-lg bg-slate-50/80 dark:bg-slate-800/80 backdrop-blur-sm"
|
||||||
style={{
|
style={{
|
||||||
opacity: isVisible ? 1 : 0,
|
opacity: isVisible ? 1 : 0,
|
||||||
transform: isVisible ? "translateX(0)" : "translateX(-20px)",
|
transform: isVisible ? "translateX(0)" : "translateX(-20px)",
|
||||||
transition: `all 0.4s ease-out ${0.5 + i * 0.2}s`,
|
transition: `all 0.4s ease-out ${0.5 + i * 0.2}s`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FileText className="w-5 h-5 text-blue-500" />
|
<FileText className="w-4 h-4 text-blue-500 flex-shrink-0" />
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<p className="text-sm font-medium text-slate-700 dark:text-slate-300 truncate">
|
<p className="text-xs font-medium text-slate-700 dark:text-slate-300 truncate">
|
||||||
{file.name}
|
{file.name}
|
||||||
</p>
|
</p>
|
||||||
<div className="h-1.5 bg-slate-200 dark:bg-slate-700 rounded-full mt-1 overflow-hidden">
|
<div className="h-1 bg-slate-200 dark:bg-slate-700 rounded-full mt-1 overflow-hidden">
|
||||||
<div
|
<div
|
||||||
className="h-full bg-gradient-to-r from-blue-500 to-violet-500 rounded-full transition-all duration-1000"
|
className="h-full bg-gradient-to-r from-blue-500 via-violet-500 to-teal-500 rounded-full transition-all duration-1000"
|
||||||
style={{
|
style={{
|
||||||
width: isVisible ? `${file.progress}%` : "0%",
|
width: isVisible ? `${file.progress}%` : "0%",
|
||||||
transitionDelay: `${0.8 + i * 0.2}s`,
|
transitionDelay: `${0.8 + i * 0.2}s`,
|
||||||
@@ -203,25 +192,13 @@ function UploadAnimation() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span className="text-xs text-slate-500">{file.size}</span>
|
<span className="text-[10px] text-slate-500">{file.size}</span>
|
||||||
{file.progress === 100 && (
|
{file.progress === 100 && (
|
||||||
<Check className="w-4 h-4 text-emerald-500" />
|
<Check className="w-3 h-3 text-emerald-500" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Format Badges */}
|
|
||||||
<div className="mt-4 flex gap-2 justify-center">
|
|
||||||
{["PDF", "JPG", "PNG"].map((format, i) => (
|
|
||||||
<span
|
|
||||||
key={i}
|
|
||||||
className="px-2 py-1 text-xs font-medium rounded-full bg-blue-500/10 text-blue-600 dark:text-blue-400"
|
|
||||||
>
|
|
||||||
{format}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -241,72 +218,58 @@ function AIAnalysisAnimation() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const analysisPoints = [
|
const analysisPoints = [
|
||||||
{ label: "Clauses detected", value: "47", icon: Target },
|
{ label: "Clauses", value: "47", icon: Target, color: "text-blue-500" },
|
||||||
{
|
{ label: "Risk", value: "Low", icon: Shield, color: "text-emerald-500" },
|
||||||
label: "Risk assessment",
|
{ label: "Speed", value: "2.3s", icon: Zap, color: "text-amber-500" },
|
||||||
value: "Low",
|
|
||||||
icon: Shield,
|
|
||||||
color: "text-emerald-500",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Processing time",
|
|
||||||
value: "2.3s",
|
|
||||||
icon: Zap,
|
|
||||||
color: "text-amber-500",
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="mt-6 glass rounded-xl p-4">
|
<div ref={ref} className="mt-4">
|
||||||
{/* AI Brain */}
|
{/* AI Brain */}
|
||||||
<div className="flex justify-center mb-4">
|
<div className="flex justify-center mb-3">
|
||||||
<div
|
<div className="relative">
|
||||||
className="relative"
|
<div
|
||||||
style={{
|
className="absolute inset-0 bg-gradient-to-br from-violet-500 to-purple-600 rounded-2xl blur-xl opacity-60"
|
||||||
animation: isVisible
|
style={{
|
||||||
? "pulse-glow 2s ease-in-out infinite"
|
animation: isVisible
|
||||||
: "none",
|
? "pulse-glow 2s ease-in-out infinite"
|
||||||
}}
|
: "none",
|
||||||
>
|
}}
|
||||||
<div className="w-16 h-16 rounded-full bg-gradient-to-br from-violet-500 to-purple-600 flex items-center justify-center">
|
/>
|
||||||
<Cpu className="w-8 h-8 text-white" />
|
<div className="relative w-14 h-14 rounded-2xl bg-gradient-to-br from-violet-500 to-purple-600 flex items-center justify-center shadow-xl">
|
||||||
|
<Cpu className="w-7 h-7 text-white" />
|
||||||
</div>
|
</div>
|
||||||
<div className="absolute -top-1 -right-1">
|
<div className="absolute -top-1 -right-1">
|
||||||
<Sparkles className="w-5 h-5 text-amber-400 animate-pulse" />
|
<Sparkles className="w-4 h-4 text-amber-400 animate-pulse" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Analysis Progress */}
|
{/* Analysis Points */}
|
||||||
<div className="space-y-3">
|
<div className="grid grid-cols-3 gap-2">
|
||||||
{analysisPoints.map((point, i) => (
|
{analysisPoints.map((point, i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className="flex items-center justify-between p-2 rounded-lg bg-white/50 dark:bg-slate-800/50"
|
className="p-2 rounded-lg bg-slate-50/80 dark:bg-slate-800/80 backdrop-blur-sm text-center"
|
||||||
style={{
|
style={{
|
||||||
opacity: isVisible ? 1 : 0,
|
opacity: isVisible ? 1 : 0,
|
||||||
transform: isVisible ? "translateY(0)" : "translateY(10px)",
|
transform: isVisible ? "scale(1)" : "scale(0.9)",
|
||||||
transition: `all 0.4s ease-out ${0.3 + i * 0.15}s`,
|
transition: `all 0.4s ease-out ${0.3 + i * 0.15}s`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-2">
|
<point.icon className={`w-4 h-4 mx-auto mb-1 ${point.color}`} />
|
||||||
<point.icon
|
<p className="text-xs font-bold text-slate-800 dark:text-slate-200">
|
||||||
className={`w-4 h-4 ${point.color || "text-blue-500"}`}
|
|
||||||
/>
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
{point.label}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<span className="text-sm font-bold text-slate-800 dark:text-slate-200">
|
|
||||||
{point.value}
|
{point.value}
|
||||||
</span>
|
</p>
|
||||||
|
<p className="text-[10px] text-slate-500">{point.label}</p>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Scanning Effect */}
|
{/* Scanning Bar with Waveform */}
|
||||||
<div className="mt-4 relative h-20 rounded-lg bg-slate-100 dark:bg-slate-800 overflow-hidden">
|
<div className="mt-3 relative h-12 rounded-lg bg-slate-100/80 dark:bg-slate-800/80 overflow-hidden">
|
||||||
<div className="absolute inset-0 flex items-center justify-center gap-1 opacity-30">
|
{/* Background waveform */}
|
||||||
|
<div className="absolute inset-0 flex items-center justify-center gap-0.5 opacity-20">
|
||||||
{scanHeights.map((height, i) => (
|
{scanHeights.map((height, i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
@@ -315,12 +278,13 @@ function AIAnalysisAnimation() {
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
{/* Scanning line */}
|
||||||
<div
|
<div
|
||||||
className="absolute top-0 bottom-0 w-1 bg-gradient-to-b from-blue-500 via-violet-500 to-transparent"
|
className="absolute top-0 bottom-0 w-0.5 bg-gradient-to-b from-violet-500 via-purple-500 to-transparent"
|
||||||
style={{
|
style={{
|
||||||
left: isVisible ? "100%" : "0%",
|
left: isVisible ? "100%" : "0%",
|
||||||
transition: "left 2s ease-in-out 0.5s",
|
transition: "left 2s ease-in-out 0.5s",
|
||||||
boxShadow: "0 0 20px rgba(59, 130, 246, 0.5)",
|
boxShadow: "0 0 20px rgba(139, 92, 246, 0.6)",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -335,20 +299,17 @@ function ChatStepAnimation() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const messages = [
|
const messages = [
|
||||||
{ text: "Explain the termination clause", isUser: true },
|
{ text: "Explain termination clause", isUser: true },
|
||||||
{
|
{ text: "Section 12.3: 30 days notice...", isUser: false },
|
||||||
text: "Section 12.3: Either party may terminate with 30 days written notice...",
|
|
||||||
isUser: false,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="mt-6 glass rounded-xl p-4">
|
<div ref={ref} className="mt-4">
|
||||||
<div className="space-y-3">
|
<div className="space-y-2">
|
||||||
{messages.map((msg, i) => (
|
{messages.map((msg, i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className={`flex ${msg.isUser ? "justify-end" : "justify-start"}`}
|
className={`flex ${msg.isUser ? "justify-end" : "justify-start"} items-end gap-2`}
|
||||||
style={{
|
style={{
|
||||||
opacity: isVisible ? 1 : 0,
|
opacity: isVisible ? 1 : 0,
|
||||||
transform: isVisible ? "translateY(0)" : "translateY(10px)",
|
transform: isVisible ? "translateY(0)" : "translateY(10px)",
|
||||||
@@ -356,12 +317,12 @@ function ChatStepAnimation() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{!msg.isUser && (
|
{!msg.isUser && (
|
||||||
<div className="w-8 h-8 rounded-full bg-gradient-to-br from-teal-500 to-cyan-600 flex items-center justify-center mr-2 flex-shrink-0">
|
<div className="w-6 h-6 rounded-full bg-gradient-to-br from-teal-500 to-cyan-600 flex items-center justify-center flex-shrink-0 shadow-lg">
|
||||||
<Sparkles className="w-4 h-4 text-white" />
|
<Sparkles className="w-3 h-3 text-white" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
className={`max-w-[80%] px-4 py-2 rounded-2xl text-sm ${
|
className={`max-w-[75%] px-3 py-2 rounded-xl text-xs shadow-sm ${
|
||||||
msg.isUser
|
msg.isUser
|
||||||
? "bg-blue-600 text-white rounded-tr-sm"
|
? "bg-blue-600 text-white rounded-tr-sm"
|
||||||
: "bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-300 rounded-tl-sm"
|
: "bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-300 rounded-tl-sm"
|
||||||
@@ -375,27 +336,22 @@ function ChatStepAnimation() {
|
|||||||
|
|
||||||
{/* RAG Indicator */}
|
{/* RAG Indicator */}
|
||||||
<div
|
<div
|
||||||
className="mt-4 flex items-center justify-center gap-2 text-xs text-slate-500"
|
className="mt-3 flex items-center justify-center gap-1.5 text-[10px] text-slate-500"
|
||||||
style={{
|
style={{
|
||||||
opacity: isVisible ? 1 : 0,
|
opacity: isVisible ? 1 : 0,
|
||||||
transition: "opacity 0.4s ease-out 1.2s",
|
transition: "opacity 0.4s ease-out 1.2s",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex gap-1">
|
<div className="flex gap-0.5">
|
||||||
<span
|
{[0, 0.2, 0.4].map((delay, i) => (
|
||||||
className="w-2 h-2 rounded-full bg-teal-500 animate-pulse"
|
<span
|
||||||
style={{ animationDelay: "0s" }}
|
key={i}
|
||||||
/>
|
className="w-1.5 h-1.5 rounded-full bg-teal-500 animate-pulse"
|
||||||
<span
|
style={{ animationDelay: `${delay}s` }}
|
||||||
className="w-2 h-2 rounded-full bg-teal-500 animate-pulse"
|
/>
|
||||||
style={{ animationDelay: "0.2s" }}
|
))}
|
||||||
/>
|
|
||||||
<span
|
|
||||||
className="w-2 h-2 rounded-full bg-teal-500 animate-pulse"
|
|
||||||
style={{ animationDelay: "0.4s" }}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<span>Powered by RAG</span>
|
<span>RAG Powered</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -408,70 +364,59 @@ function BlockchainStepAnimation() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="mt-6 glass rounded-xl p-4">
|
<div ref={ref} className="mt-4">
|
||||||
{/* Blockchain Visual */}
|
{/* Blockchain Chain */}
|
||||||
<div className="relative h-24 mb-4">
|
<div className="flex items-center justify-center gap-2 mb-3">
|
||||||
<div className="flex items-center justify-center gap-4">
|
{[0, 1, 2].map((i) => (
|
||||||
{[0, 1, 2].map((i) => (
|
<div key={i} className="relative">
|
||||||
<div key={i} className="relative">
|
<div
|
||||||
<div
|
className="w-10 h-10 rounded-lg bg-gradient-to-br from-emerald-500 to-green-600 flex items-center justify-center shadow-lg"
|
||||||
className="w-12 h-12 rounded-lg bg-gradient-to-br from-emerald-500 to-green-600 flex items-center justify-center shadow-lg"
|
style={{
|
||||||
style={{
|
opacity: isVisible ? 1 : 0,
|
||||||
opacity: isVisible ? 1 : 0,
|
transform: isVisible ? "scale(1)" : "scale(0.8)",
|
||||||
transform: isVisible ? "scale(1)" : "scale(0.8)",
|
transition: `all 0.4s ease-out ${0.2 + i * 0.2}s`,
|
||||||
transition: `all 0.4s ease-out ${0.2 + i * 0.2}s`,
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<Link className="w-5 h-5 text-white" />
|
||||||
<Link className="w-6 h-6 text-white" />
|
|
||||||
</div>
|
|
||||||
{i < 2 && (
|
|
||||||
<div
|
|
||||||
className="absolute top-1/2 -right-4 w-8 h-0.5 bg-emerald-500/50"
|
|
||||||
style={{
|
|
||||||
transform: isVisible ? "scaleX(1)" : "scaleX(0)",
|
|
||||||
transformOrigin: "left",
|
|
||||||
transition: `transform 0.3s ease-out ${0.4 + i * 0.2}s`,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
{i < 2 && (
|
||||||
</div>
|
<div
|
||||||
|
className="absolute top-1/2 -right-2 w-4 h-0.5 bg-gradient-to-r from-emerald-500 to-green-500"
|
||||||
|
style={{
|
||||||
|
transform: isVisible ? "scaleX(1)" : "scaleX(0)",
|
||||||
|
transformOrigin: "left",
|
||||||
|
transition: `transform 0.3s ease-out ${0.4 + i * 0.2}s`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Certificate */}
|
{/* Certificate */}
|
||||||
<div
|
<div
|
||||||
className="glass rounded-lg p-3 border border-emerald-500/30"
|
className="rounded-xl p-3 bg-gradient-to-br from-emerald-50 to-green-50 dark:from-emerald-950/30 dark:to-green-950/30 border border-emerald-200/50 dark:border-emerald-700/50"
|
||||||
style={{
|
style={{
|
||||||
opacity: isVisible ? 1 : 0,
|
opacity: isVisible ? 1 : 0,
|
||||||
transform: isVisible ? "translateY(0)" : "translateY(10px)",
|
transform: isVisible ? "translateY(0)" : "translateY(10px)",
|
||||||
transition: "all 0.5s ease-out 0.8s",
|
transition: "all 0.5s ease-out 0.8s",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-2">
|
||||||
<div className="w-10 h-10 rounded-full bg-emerald-500/20 flex items-center justify-center">
|
<div className="w-8 h-8 rounded-lg bg-emerald-500/20 flex items-center justify-center flex-shrink-0">
|
||||||
<Shield className="w-5 h-5 text-emerald-500" />
|
<Shield className="w-4 h-4 text-emerald-600 dark:text-emerald-400" />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="flex-1 min-w-0">
|
||||||
<p className="text-sm font-semibold text-slate-800 dark:text-slate-200">
|
<p className="text-xs font-bold text-emerald-900 dark:text-emerald-100">
|
||||||
Verified on Polygon
|
Polygon Verified
|
||||||
|
</p>
|
||||||
|
<p className="text-[10px] font-mono text-emerald-700 dark:text-emerald-300 truncate">
|
||||||
|
0x3f7a...9e2d
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs font-mono text-slate-500">0x3f7a...9e2d</p>
|
|
||||||
</div>
|
</div>
|
||||||
<Check className="w-5 h-5 text-emerald-500" />
|
<Check className="w-4 h-4 text-emerald-600 dark:text-emerald-400 flex-shrink-0" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Timestamp */}
|
|
||||||
<div
|
|
||||||
className="mt-3 text-center text-xs text-slate-500"
|
|
||||||
style={{
|
|
||||||
opacity: isVisible ? 1 : 0,
|
|
||||||
transition: "opacity 0.4s ease-out 1.2s",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Timestamped: {new Date().toLocaleString()}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -483,38 +428,42 @@ export function HowItWorks() {
|
|||||||
const steps = [
|
const steps = [
|
||||||
{
|
{
|
||||||
number: "01",
|
number: "01",
|
||||||
title: "Upload Your Contract",
|
title: "Upload Contract",
|
||||||
description:
|
description:
|
||||||
"PDF, images, or scanned documents. Simply drag and drop or click to browse.",
|
"PDF, images, or scans. Drag and drop or browse to upload instantly.",
|
||||||
icon: Upload,
|
icon: Upload,
|
||||||
gradient: "bg-gradient-to-br from-blue-500 to-blue-600",
|
gradient: "bg-gradient-to-br from-blue-500 to-blue-600",
|
||||||
|
glowColor: "rgba(59, 130, 246, 0.5)",
|
||||||
animation: <UploadAnimation />,
|
animation: <UploadAnimation />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
number: "02",
|
number: "02",
|
||||||
title: "AI Extracts & Analyzes",
|
title: "AI Analysis",
|
||||||
description:
|
description:
|
||||||
"GPT-4 Turbo understands your contract deeply. Automatic extraction of all important clauses and terms.",
|
"GPT-4 Turbo extracts and analyzes every clause, term, and detail automatically.",
|
||||||
icon: Cpu,
|
icon: Cpu,
|
||||||
gradient: "bg-gradient-to-br from-violet-500 to-purple-600",
|
gradient: "bg-gradient-to-br from-violet-500 to-purple-600",
|
||||||
|
glowColor: "rgba(139, 92, 246, 0.5)",
|
||||||
animation: <AIAnalysisAnimation />,
|
animation: <AIAnalysisAnimation />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
number: "03",
|
number: "03",
|
||||||
title: "Chat with AI Assistant",
|
title: "Chat with AI",
|
||||||
description:
|
description:
|
||||||
"Get instant answers to any questions. Powered by RAG for precise, context-aware responses.",
|
"Ask anything. Get instant, precise answers powered by RAG technology.",
|
||||||
icon: MessageSquare,
|
icon: MessageSquare,
|
||||||
gradient: "bg-gradient-to-br from-teal-500 to-cyan-600",
|
gradient: "bg-gradient-to-br from-teal-500 to-cyan-600",
|
||||||
|
glowColor: "rgba(20, 184, 166, 0.5)",
|
||||||
animation: <ChatStepAnimation />,
|
animation: <ChatStepAnimation />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
number: "04",
|
number: "04",
|
||||||
title: "Immutable Certification",
|
title: "Blockchain Proof",
|
||||||
description:
|
description:
|
||||||
"Registered on Polygon blockchain. Legally valid timestamped proof of submission.",
|
"Immutable certification on Polygon. Legally valid timestamped proof.",
|
||||||
icon: Shield,
|
icon: Shield,
|
||||||
gradient: "bg-gradient-to-br from-emerald-500 to-green-600",
|
gradient: "bg-gradient-to-br from-emerald-500 to-green-600",
|
||||||
|
glowColor: "rgba(16, 185, 129, 0.5)",
|
||||||
animation: <BlockchainStepAnimation />,
|
animation: <BlockchainStepAnimation />,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -522,14 +471,14 @@ export function HowItWorks() {
|
|||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
id="how-it-works"
|
id="how-it-works"
|
||||||
className="relative py-24 px-4 sm:px-6 lg:px-8 overflow-hidden"
|
className="relative py-20 px-4 sm:px-6 lg:px-8 overflow-hidden"
|
||||||
>
|
>
|
||||||
{/* Background */}
|
{/* Background with Beams */}
|
||||||
<div className="absolute inset-0 bg-slate-50 dark:bg-slate-900/50">
|
<div className="absolute inset-0 bg-gradient-to-b from-slate-50 via-blue-50/30 to-slate-50 dark:from-slate-950 dark:via-slate-900 dark:to-slate-950">
|
||||||
<div className="absolute inset-0 grid-pattern opacity-50" />
|
<BackgroundBeams className="opacity-55" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="relative max-w-7xl mx-auto">
|
<div className="relative z-10 max-w-7xl mx-auto">
|
||||||
{/* Section Header */}
|
{/* Section Header */}
|
||||||
<div
|
<div
|
||||||
ref={headerRef}
|
ref={headerRef}
|
||||||
@@ -537,58 +486,44 @@ export function HowItWorks() {
|
|||||||
style={{
|
style={{
|
||||||
opacity: headerVisible ? 1 : 0,
|
opacity: headerVisible ? 1 : 0,
|
||||||
transform: headerVisible ? "translateY(0)" : "translateY(30px)",
|
transform: headerVisible ? "translateY(0)" : "translateY(30px)",
|
||||||
transition: "all 0.6s ease-out",
|
transition: "all 0.8s cubic-bezier(0.16, 1, 0.3, 1)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full glass mb-6">
|
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full glass mb-6 shadow-lg">
|
||||||
<Target className="w-4 h-4 text-blue-600 dark:text-blue-400" />
|
<Target className="w-4 h-4 text-blue-600 dark:text-blue-400" />
|
||||||
<span className="text-sm font-medium text-slate-700 dark:text-slate-300">
|
<span className="text-sm font-bold text-slate-700 dark:text-slate-300">
|
||||||
Simple Process
|
Simple Process
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 className="text-4xl md:text-5xl font-bold text-slate-900 dark:text-white mb-4">
|
<h2 className="text-3xl md:text-5xl font-black text-slate-900 dark:text-white mb-4 leading-tight">
|
||||||
From Upload to Certification in{" "}
|
From Upload to Certification in{" "}
|
||||||
<span className="gradient-text">4 Steps</span>
|
<span className="gradient-text">4 Easy Steps</span>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p className="text-xl text-slate-600 dark:text-slate-400 max-w-2xl mx-auto">
|
<p className="text-lg md:text-xl text-slate-600 dark:text-slate-400 max-w-2xl mx-auto">
|
||||||
Our intelligent system handles everything automatically
|
Our intelligent system handles everything automatically
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Steps Grid */}
|
{/* Steps Grid - Better Alignment */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 lg:gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 lg:gap-4">
|
||||||
{steps.map((step, index) => (
|
{steps.map((step, index) => (
|
||||||
<div key={step.number} className="relative">
|
<StepCard
|
||||||
<StepCard
|
key={step.number}
|
||||||
number={step.number}
|
number={step.number}
|
||||||
title={step.title}
|
title={step.title}
|
||||||
description={step.description}
|
description={step.description}
|
||||||
icon={step.icon}
|
icon={step.icon}
|
||||||
gradient={step.gradient}
|
gradient={step.gradient}
|
||||||
delay={index * 0.15}
|
glowColor={step.glowColor}
|
||||||
isLast={index === steps.length - 1}
|
delay={index * 0.1}
|
||||||
/>
|
>
|
||||||
{step.animation}
|
{step.animation}
|
||||||
</div>
|
</StepCard>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Custom Animation Keyframes */}
|
|
||||||
<style>{`
|
|
||||||
@keyframes move-right {
|
|
||||||
0% {
|
|
||||||
left: 0;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
left: 100%;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`}</style>
|
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { useTheme } from "@/hooks/useTheme";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Sparkles, Sun, Moon, X, ArrowRight } from "lucide-react";
|
import { ModeToggle } from "@/components/ui/mode-toggle";
|
||||||
|
import { Sparkles, X, ArrowRight } from "lucide-react";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
const navLinks = [
|
const navLinks = [
|
||||||
{ label: "Features", href: "#features" },
|
{ label: "Features", href: "#features" },
|
||||||
@@ -12,10 +14,14 @@ const navLinks = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export function Navbar() {
|
export function Navbar() {
|
||||||
const { theme, toggleTheme, mounted } = useTheme();
|
|
||||||
const [isScrolled, setIsScrolled] = useState(false);
|
const [isScrolled, setIsScrolled] = useState(false);
|
||||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
||||||
const [activeLink, setActiveLink] = useState("");
|
const [activeLink, setActiveLink] = useState("");
|
||||||
|
const [mounted, setMounted] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setMounted(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleScroll = () => {
|
const handleScroll = () => {
|
||||||
@@ -50,7 +56,7 @@ export function Navbar() {
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Sparkles className="w-6 h-6 text-blue-600" />
|
<Sparkles className="w-6 h-6 text-blue-600" />
|
||||||
<span className="text-xl font-bold gradient-text">
|
<span className="text-xl font-bold gradient-text">
|
||||||
Smart-Admin Copilot
|
LexiChain
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -87,21 +93,50 @@ export function Navbar() {
|
|||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="#"
|
||||||
className="flex items-center gap-2 group"
|
className="flex items-center gap-3 group"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="relative">
|
<div className="relative flex items-center justify-center">
|
||||||
<Sparkles className="w-6 h-6 text-blue-600 dark:text-blue-400 transition-transform duration-300 group-hover:rotate-12" />
|
{/* Subtle background badge */}
|
||||||
<div className="absolute inset-0 bg-blue-500/20 blur-lg rounded-full opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
|
<div
|
||||||
|
className="
|
||||||
|
absolute inset-0
|
||||||
|
rounded-xl
|
||||||
|
bg-gradient-to-tr
|
||||||
|
from-blue-500/10
|
||||||
|
via-purple-500/10
|
||||||
|
to-teal-500/10
|
||||||
|
opacity-0
|
||||||
|
group-hover:opacity-100
|
||||||
|
transition-opacity duration-300
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Logo */}
|
||||||
|
<Image
|
||||||
|
src="/LexiChain.png"
|
||||||
|
alt="LexiChain Logo"
|
||||||
|
width={34}
|
||||||
|
height={34}
|
||||||
|
className="
|
||||||
|
relative z-10
|
||||||
|
w-8 h-8 object-contain
|
||||||
|
transition-all duration-300 ease-out
|
||||||
|
group-hover:scale-110
|
||||||
|
"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span className="text-lg md:text-xl font-bold gradient-text hidden sm:inline">
|
<span
|
||||||
Smart-Admin Copilot
|
className="
|
||||||
</span>
|
text-lg font-semibold
|
||||||
<span className="text-lg font-bold gradient-text sm:hidden">
|
gradient-text
|
||||||
SAC
|
sm:hidden
|
||||||
|
"
|
||||||
|
>
|
||||||
|
LC
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -129,49 +164,29 @@ export function Navbar() {
|
|||||||
{/* Right Section */}
|
{/* Right Section */}
|
||||||
<div className="flex items-center gap-2 md:gap-3">
|
<div className="flex items-center gap-2 md:gap-3">
|
||||||
{/* Theme Toggle */}
|
{/* Theme Toggle */}
|
||||||
<button
|
<ModeToggle />
|
||||||
onClick={toggleTheme}
|
|
||||||
className="relative p-1 rounded-full bg-slate-100 dark:bg-slate-800 transition-colors duration-300"
|
|
||||||
aria-label="Toggle theme"
|
|
||||||
>
|
|
||||||
<div className="flex items-center gap-1">
|
|
||||||
<div
|
|
||||||
className={`p-2 rounded-full transition-all duration-300 ${
|
|
||||||
theme === "light"
|
|
||||||
? "bg-white shadow-sm text-amber-500"
|
|
||||||
: "text-slate-400"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<Sun className="w-4 h-4" />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={`p-2 rounded-full transition-all duration-300 ${
|
|
||||||
theme === "dark"
|
|
||||||
? "bg-slate-900 shadow-sm text-blue-400"
|
|
||||||
: "text-slate-400"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<Moon className="w-4 h-4" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{/* Sign In - Desktop */}
|
{/* Sign In - Desktop */}
|
||||||
<button className="hidden md:flex items-center gap-2 px-5 py-2 text-sm font-medium text-slate-700 dark:text-slate-300 border border-slate-300 dark:border-slate-600 rounded-full hover:bg-slate-50 dark:hover:bg-slate-800 transition-all duration-200">
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="hidden md:flex items-center gap-2 px-5 py-2 text-sm font-medium text-slate-700 dark:text-slate-300 border-slate-300 dark:border-slate-600 rounded-full hover:bg-slate-50 dark:hover:bg-slate-800 transition-all duration-200"
|
||||||
|
>
|
||||||
Sign In
|
Sign In
|
||||||
</button>
|
</Button>
|
||||||
|
|
||||||
{/* Get Started - Desktop */}
|
{/* Get Started - Desktop */}
|
||||||
<button className="hidden md:flex items-center gap-2 px-6 py-2.5 text-sm font-semibold text-white btn-gradient rounded-full group">
|
<Button className="hidden md:flex items-center gap-2 px-6 py-2.5 text-sm font-semibold text-white btn-gradient rounded-full group">
|
||||||
Get Started
|
Get Started
|
||||||
<ArrowRight className="w-4 h-4 transition-transform duration-300 group-hover:translate-x-1" />
|
<ArrowRight className="w-4 h-4 transition-transform duration-300 group-hover:translate-x-1" />
|
||||||
</button>
|
</Button>
|
||||||
|
|
||||||
{/* Mobile Menu Button */}
|
{/* Mobile Menu Button */}
|
||||||
<button
|
<Button
|
||||||
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
||||||
className="lg:hidden p-2 rounded-full hover:bg-slate-100 dark:hover:bg-slate-800 transition-colors duration-200"
|
className="lg:hidden p-2 rounded-full hover:bg-slate-100 dark:hover:bg-slate-800 transition-colors duration-200"
|
||||||
aria-label="Toggle menu"
|
aria-label="Toggle menu"
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
>
|
>
|
||||||
<div className="relative w-6 h-6">
|
<div className="relative w-6 h-6">
|
||||||
<span
|
<span
|
||||||
@@ -190,7 +205,7 @@ export function Navbar() {
|
|||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -216,13 +231,15 @@ export function Navbar() {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="p-6 pt-20">
|
<div className="p-6 pt-20">
|
||||||
<button
|
<Button
|
||||||
onClick={() => setIsMobileMenuOpen(false)}
|
onClick={() => setIsMobileMenuOpen(false)}
|
||||||
className="absolute top-6 right-6 p-2 rounded-full hover:bg-slate-100 dark:hover:bg-slate-800 transition-colors"
|
className="absolute top-6 right-6 p-2 rounded-full hover:bg-slate-100 dark:hover:bg-slate-800 transition-colors"
|
||||||
aria-label="Close menu"
|
aria-label="Close menu"
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
>
|
>
|
||||||
<X className="w-6 h-6" />
|
<X className="w-6 h-6" />
|
||||||
</button>
|
</Button>
|
||||||
|
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
{navLinks.map((link, index) => (
|
{navLinks.map((link, index) => (
|
||||||
@@ -245,13 +262,16 @@ export function Navbar() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-8 flex flex-col gap-3">
|
<div className="mt-8 flex flex-col gap-3">
|
||||||
<button className="w-full px-5 py-3 text-sm font-medium text-slate-700 dark:text-slate-300 border border-slate-300 dark:border-slate-600 rounded-full hover:bg-slate-50 dark:hover:bg-slate-800 transition-all duration-200">
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="w-full px-5 py-3 text-sm font-medium text-slate-700 dark:text-slate-300 border-slate-300 dark:border-slate-600 rounded-full hover:bg-slate-50 dark:hover:bg-slate-800 transition-all duration-200"
|
||||||
|
>
|
||||||
Sign In
|
Sign In
|
||||||
</button>
|
</Button>
|
||||||
<button className="w-full flex items-center justify-center gap-2 px-6 py-3 text-sm font-semibold text-white btn-gradient rounded-full">
|
<Button className="w-full flex items-center justify-center gap-2 px-6 py-3 text-sm font-semibold text-white btn-gradient rounded-full">
|
||||||
Get Started
|
Get Started
|
||||||
<ArrowRight className="w-4 h-4" />
|
<ArrowRight className="w-4 h-4" />
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ import {
|
|||||||
Award,
|
Award,
|
||||||
Check,
|
Check,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
import { BentoGrid } from "@/components/ui/bento-grid";
|
||||||
|
import { Spotlight } from "@/components/ui/spotlight-new";
|
||||||
|
import { GlowingEffect } from "@/components/ui/glowing-effect";
|
||||||
import { useScrollAnimation } from "@/hooks/useScrollAnimation";
|
import { useScrollAnimation } from "@/hooks/useScrollAnimation";
|
||||||
|
|
||||||
// Count Up Hook
|
// Count Up Hook
|
||||||
@@ -55,7 +58,11 @@ function useCountUp(
|
|||||||
|
|
||||||
// Ease out cubic
|
// Ease out cubic
|
||||||
const easeOut = 1 - Math.pow(1 - progress, 3);
|
const easeOut = 1 - Math.pow(1 - progress, 3);
|
||||||
setCount(Math.floor(end * easeOut));
|
const nextValue = end * easeOut;
|
||||||
|
const formattedValue = Number.isInteger(end)
|
||||||
|
? Math.floor(nextValue)
|
||||||
|
: Number(nextValue.toFixed(1));
|
||||||
|
setCount(formattedValue);
|
||||||
|
|
||||||
if (progress < 1) {
|
if (progress < 1) {
|
||||||
animationFrame = requestAnimationFrame(animate);
|
animationFrame = requestAnimationFrame(animate);
|
||||||
@@ -83,6 +90,16 @@ interface StatCardProps {
|
|||||||
label: string;
|
label: string;
|
||||||
icon: React.ElementType;
|
icon: React.ElementType;
|
||||||
gradient: string;
|
gradient: string;
|
||||||
|
className?: string;
|
||||||
|
cardColor?: string;
|
||||||
|
glowColor?: string;
|
||||||
|
spotlight?: {
|
||||||
|
gradientFirst?: string;
|
||||||
|
gradientSecond?: string;
|
||||||
|
gradientThird?: string;
|
||||||
|
duration?: number;
|
||||||
|
xOffset?: number;
|
||||||
|
};
|
||||||
delay: number;
|
delay: number;
|
||||||
additional?: string;
|
additional?: string;
|
||||||
isText?: boolean;
|
isText?: boolean;
|
||||||
@@ -96,6 +113,10 @@ function StatCard({
|
|||||||
label,
|
label,
|
||||||
icon: Icon,
|
icon: Icon,
|
||||||
gradient,
|
gradient,
|
||||||
|
className,
|
||||||
|
cardColor,
|
||||||
|
glowColor,
|
||||||
|
spotlight,
|
||||||
delay,
|
delay,
|
||||||
additional,
|
additional,
|
||||||
isText = false,
|
isText = false,
|
||||||
@@ -108,105 +129,102 @@ function StatCard({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={scrollRef}
|
ref={scrollRef}
|
||||||
className="relative group"
|
className={`relative ${className || ""}`}
|
||||||
style={{
|
style={{
|
||||||
opacity: isVisible ? 1 : 0,
|
opacity: isVisible ? 1 : 0,
|
||||||
transform: isVisible ? "translateY(0)" : "translateY(30px)",
|
transform: isVisible ? "translateY(0)" : "translateY(30px)",
|
||||||
transition: `all 0.6s ease-out ${delay}s`,
|
transition: `all 0.6s ease-out ${delay}s`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="relative glass rounded-3xl p-8 hover-lift overflow-hidden">
|
<div
|
||||||
|
className={`relative h-full overflow-hidden rounded-2xl border border-border/60 p-7 shadow-[0_20px_60px_-30px_rgba(15,23,42,0.25)] backdrop-blur group ${cardColor || "bg-card/80"}`}
|
||||||
|
>
|
||||||
|
{/* Glowing Effect */}
|
||||||
|
<GlowingEffect
|
||||||
|
disabled={false}
|
||||||
|
blur={40}
|
||||||
|
spread={60}
|
||||||
|
proximity={80}
|
||||||
|
variant="default"
|
||||||
|
borderWidth={2}
|
||||||
|
className="opacity-0 group-hover:opacity-100 transition-opacity duration-500"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="absolute inset-0">
|
||||||
|
<Spotlight
|
||||||
|
gradientFirst={spotlight?.gradientFirst}
|
||||||
|
gradientSecond={spotlight?.gradientSecond}
|
||||||
|
gradientThird={spotlight?.gradientThird}
|
||||||
|
duration={spotlight?.duration ?? 8}
|
||||||
|
xOffset={spotlight?.xOffset ?? 120}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Hover Glow */}
|
||||||
|
{glowColor && (
|
||||||
|
<div
|
||||||
|
className={`absolute -inset-1 ${glowColor} opacity-0 group-hover:opacity-20 blur-2xl transition-opacity duration-500 rounded-2xl`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Background Icon */}
|
{/* Background Icon */}
|
||||||
<div className="absolute top-4 right-4 opacity-10">
|
<div className="absolute -top-6 -right-6 opacity-10">
|
||||||
<Icon className="w-24 h-24 text-white" />
|
<Icon className="w-28 h-28 text-foreground" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<div className="relative z-10">
|
<div className="relative z-10 flex h-full flex-col justify-between">
|
||||||
{/* Icon */}
|
<div>
|
||||||
<div
|
{/* Icon */}
|
||||||
className={`inline-flex p-3 rounded-2xl ${gradient} mb-6 shadow-lg`}
|
<div
|
||||||
>
|
className={`inline-flex items-center gap-2 rounded-full ${gradient} px-4 py-2 text-foreground shadow-lg`}
|
||||||
<Icon className="w-8 h-8 text-white" />
|
>
|
||||||
</div>
|
<Icon className="w-4 h-4" />
|
||||||
|
<span className="text-xs font-semibold tracking-widest uppercase text-foreground/80">
|
||||||
{/* Value */}
|
Performance
|
||||||
<div ref={countRef} className="mb-2">
|
|
||||||
{isText ? (
|
|
||||||
<span className="text-5xl md:text-6xl lg:text-7xl font-black text-white tracking-wider">
|
|
||||||
{value}
|
|
||||||
</span>
|
</span>
|
||||||
) : (
|
</div>
|
||||||
<span className="text-5xl md:text-6xl lg:text-7xl font-black text-white">
|
|
||||||
{prefix}
|
|
||||||
{numericValue !== undefined ? count : value}
|
|
||||||
{suffix}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Label */}
|
{/* Value */}
|
||||||
<p className="text-lg md:text-xl font-medium text-white/90 mb-2">
|
<div ref={countRef} className="mt-6">
|
||||||
{label}
|
{isText ? (
|
||||||
</p>
|
<span className="text-4xl md:text-5xl lg:text-6xl font-semibold text-foreground tracking-tight">
|
||||||
|
{value}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className="text-4xl md:text-5xl lg:text-6xl font-semibold text-foreground tracking-tight">
|
||||||
|
{prefix}
|
||||||
|
{numericValue !== undefined && !Number.isInteger(numericValue)
|
||||||
|
? count.toFixed(1)
|
||||||
|
: numericValue !== undefined
|
||||||
|
? count
|
||||||
|
: value}
|
||||||
|
{suffix}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Label */}
|
||||||
|
<p className="mt-4 text-base md:text-lg font-medium text-foreground/90">
|
||||||
|
{label}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Additional Info */}
|
{/* Additional Info */}
|
||||||
{additional && (
|
{additional && (
|
||||||
<div className="flex items-center gap-2 mt-3">
|
<div className="flex items-center gap-2 pt-6">
|
||||||
<TrendingUp className="w-4 h-4 text-emerald-400" />
|
<TrendingUp className="w-4 h-4 text-emerald-500" />
|
||||||
<span className="text-sm text-white/70">{additional}</span>
|
<span className="text-sm text-muted-foreground">
|
||||||
|
{additional}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Glow Effect */}
|
|
||||||
<div
|
|
||||||
className={`absolute -inset-px ${gradient} opacity-0 group-hover:opacity-30 rounded-3xl blur-xl transition-opacity duration-500`}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Floating Badge Component
|
|
||||||
function FloatingBadge({
|
|
||||||
text,
|
|
||||||
icon: Icon,
|
|
||||||
delay,
|
|
||||||
position,
|
|
||||||
}: {
|
|
||||||
text: string;
|
|
||||||
icon: React.ElementType;
|
|
||||||
delay: number;
|
|
||||||
position: { top?: string; bottom?: string; left?: string; right?: string };
|
|
||||||
}) {
|
|
||||||
const { ref, isVisible } = useScrollAnimation<HTMLDivElement>({
|
|
||||||
threshold: 0.5,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
ref={ref}
|
|
||||||
className="absolute glass rounded-full px-3 py-1.5 flex items-center gap-2 shadow-lg"
|
|
||||||
style={{
|
|
||||||
...position,
|
|
||||||
opacity: isVisible ? 1 : 0,
|
|
||||||
transform: isVisible ? "translateY(0)" : "translateY(20px)",
|
|
||||||
transition: `all 0.5s ease-out ${delay}s`,
|
|
||||||
animationName: isVisible ? "float" : "none",
|
|
||||||
animationDuration: isVisible ? "4s" : undefined,
|
|
||||||
animationTimingFunction: isVisible ? "ease-in-out" : undefined,
|
|
||||||
animationIterationCount: isVisible ? "infinite" : undefined,
|
|
||||||
animationFillMode: "forwards",
|
|
||||||
animationDelay: isVisible ? `${delay}s` : undefined,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Icon className="w-4 h-4 text-blue-400" />
|
|
||||||
<span className="text-xs font-medium text-white">{text}</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Stats() {
|
export function Stats() {
|
||||||
const { ref: headerRef, isVisible: headerVisible } =
|
const { ref: headerRef, isVisible: headerVisible } =
|
||||||
useScrollAnimation<HTMLDivElement>();
|
useScrollAnimation<HTMLDivElement>();
|
||||||
@@ -219,6 +237,16 @@ export function Stats() {
|
|||||||
label: string;
|
label: string;
|
||||||
icon: React.ElementType;
|
icon: React.ElementType;
|
||||||
gradient: string;
|
gradient: string;
|
||||||
|
className?: string;
|
||||||
|
cardColor?: string;
|
||||||
|
glowColor?: string;
|
||||||
|
spotlight?: {
|
||||||
|
gradientFirst?: string;
|
||||||
|
gradientSecond?: string;
|
||||||
|
gradientThird?: string;
|
||||||
|
duration?: number;
|
||||||
|
xOffset?: number;
|
||||||
|
};
|
||||||
additional?: string;
|
additional?: string;
|
||||||
isText?: boolean;
|
isText?: boolean;
|
||||||
}
|
}
|
||||||
@@ -226,19 +254,38 @@ export function Stats() {
|
|||||||
const stats: StatItem[] = [
|
const stats: StatItem[] = [
|
||||||
{
|
{
|
||||||
value: "99.9",
|
value: "99.9",
|
||||||
numericValue: 99,
|
numericValue: 99.9,
|
||||||
suffix: "%",
|
suffix: "%",
|
||||||
label: "OCR + AI Accuracy",
|
label: "OCR + AI Accuracy",
|
||||||
icon: Target,
|
icon: Target,
|
||||||
gradient: "bg-gradient-to-br from-blue-500 to-blue-600",
|
gradient: "bg-gradient-to-r from-blue-500 to-indigo-600",
|
||||||
|
cardColor:
|
||||||
|
"bg-gradient-to-br from-blue-50/80 to-indigo-50/80 dark:from-blue-950/30 dark:to-indigo-950/30",
|
||||||
|
glowColor: "bg-blue-500",
|
||||||
|
className: "md:col-span-2",
|
||||||
|
spotlight: {
|
||||||
|
gradientFirst:
|
||||||
|
"radial-gradient(68.54% 68.72% at 55.02% 31.46%, hsla(217, 91%, 60%, .28) 0, hsla(217, 91%, 60%, .12) 55%, hsla(217, 91%, 60%, 0) 80%)",
|
||||||
|
gradientSecond:
|
||||||
|
"radial-gradient(50% 50% at 50% 50%, hsla(258, 90%, 66%, .24) 0, hsla(258, 90%, 66%, .08) 80%, transparent 100%)",
|
||||||
|
gradientThird:
|
||||||
|
"radial-gradient(50% 50% at 50% 50%, hsla(217, 91%, 60%, .18) 0, hsla(217, 91%, 60%, .06) 80%, transparent 100%)",
|
||||||
|
},
|
||||||
additional: "+0.3% this month",
|
additional: "+0.3% this month",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "< 3",
|
value: "< 3",
|
||||||
label: "Average AI Response Time",
|
label: "Average AI Response Time",
|
||||||
icon: Zap,
|
icon: Zap,
|
||||||
gradient: "bg-gradient-to-br from-amber-500 to-orange-600",
|
gradient: "bg-gradient-to-r from-amber-500 to-orange-600",
|
||||||
additional: "Lightning fast",
|
cardColor:
|
||||||
|
"bg-gradient-to-br from-amber-50/80 to-orange-50/80 dark:from-amber-950/30 dark:to-orange-950/30",
|
||||||
|
glowColor: "bg-amber-500",
|
||||||
|
spotlight: {
|
||||||
|
gradientFirst:
|
||||||
|
"radial-gradient(68.54% 68.72% at 55.02% 31.46%, hsla(48, 96%, 53%, .28) 0, hsla(48, 96%, 53%, .12) 55%, hsla(48, 96%, 53%, 0) 80%)",
|
||||||
|
},
|
||||||
|
additional: "Average under 3 seconds",
|
||||||
isText: true,
|
isText: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -247,109 +294,75 @@ export function Stats() {
|
|||||||
suffix: "%",
|
suffix: "%",
|
||||||
label: "Blockchain Verified",
|
label: "Blockchain Verified",
|
||||||
icon: Shield,
|
icon: Shield,
|
||||||
gradient: "bg-gradient-to-br from-violet-500 to-purple-600",
|
gradient: "bg-gradient-to-r from-emerald-500 to-teal-600",
|
||||||
|
cardColor:
|
||||||
|
"bg-gradient-to-br from-emerald-50/80 to-teal-50/80 dark:from-emerald-950/30 dark:to-teal-950/30",
|
||||||
|
glowColor: "bg-emerald-500",
|
||||||
|
spotlight: {
|
||||||
|
gradientFirst:
|
||||||
|
"radial-gradient(68.54% 68.72% at 55.02% 31.46%, hsla(158, 64%, 52%, .28) 0, hsla(158, 64%, 52%, .12) 55%, hsla(158, 64%, 52%, 0) 80%)",
|
||||||
|
},
|
||||||
additional: "All documents certified",
|
additional: "All documents certified",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "GDPR",
|
value: "GDPR",
|
||||||
label: "Full European Compliance",
|
label: "Full European Compliance",
|
||||||
icon: Lock,
|
icon: Lock,
|
||||||
gradient: "bg-gradient-to-br from-emerald-500 to-green-600",
|
gradient: "bg-gradient-to-r from-violet-500 to-purple-600",
|
||||||
additional: "ISO 27001 Certified",
|
cardColor:
|
||||||
|
"bg-gradient-to-br from-violet-50/80 to-purple-50/80 dark:from-violet-950/30 dark:to-purple-950/30",
|
||||||
|
glowColor: "bg-violet-500",
|
||||||
|
className: "md:col-span-2",
|
||||||
|
spotlight: {
|
||||||
|
gradientFirst:
|
||||||
|
"radial-gradient(68.54% 68.72% at 55.02% 31.46%, hsla(258, 90%, 66%, .28) 0, hsla(258, 90%, 66%, .12) 55%, hsla(258, 90%, 66%, 0) 80%)",
|
||||||
|
},
|
||||||
|
additional: "ISO 27001 certified",
|
||||||
isText: true,
|
isText: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const floatingBadges = [
|
|
||||||
{
|
|
||||||
text: "+1 Verified",
|
|
||||||
icon: Check,
|
|
||||||
position: { top: "10%", left: "5%" },
|
|
||||||
delay: 0.8,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "99.9% Uptime",
|
|
||||||
icon: Shield,
|
|
||||||
position: { top: "20%", right: "8%" },
|
|
||||||
delay: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "AI Powered",
|
|
||||||
icon: Zap,
|
|
||||||
position: { bottom: "15%", left: "10%" },
|
|
||||||
delay: 1.2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Secure",
|
|
||||||
icon: Lock,
|
|
||||||
position: { bottom: "25%", right: "5%" },
|
|
||||||
delay: 1.4,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
id="stats"
|
id="stats"
|
||||||
className="relative py-24 px-4 sm:px-6 lg:px-8 overflow-hidden"
|
className="relative py-16 px-4 sm:px-6 lg:px-8 overflow-hidden"
|
||||||
>
|
>
|
||||||
{/* Gradient Background */}
|
{/* Gradient Background */}
|
||||||
<div className="absolute inset-0 bg-gradient-to-br from-blue-600 via-violet-600 to-teal-600">
|
<div className="absolute inset-0 bg-gradient-to-br from-background via-muted/40 to-background">
|
||||||
{/* Grid Pattern Overlay */}
|
{/* Grid Pattern Overlay */}
|
||||||
<div className="absolute inset-0 grid-pattern opacity-20" />
|
<div className="absolute inset-0 grid-pattern opacity-15" />
|
||||||
|
|
||||||
{/* Radial Glow */}
|
{/* Radial Glow */}
|
||||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,rgba(255,255,255,0.1)_0%,transparent_70%)]" />
|
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top,hsla(var(--primary),0.2)_0%,transparent_55%)]" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Floating Badges */}
|
|
||||||
{floatingBadges.map((badge, i) => (
|
|
||||||
<FloatingBadge
|
|
||||||
key={i}
|
|
||||||
text={badge.text}
|
|
||||||
icon={badge.icon}
|
|
||||||
delay={badge.delay}
|
|
||||||
position={badge.position}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
|
|
||||||
<div className="relative max-w-7xl mx-auto">
|
<div className="relative max-w-7xl mx-auto">
|
||||||
{/* Section Header */}
|
{/* Section Header */}
|
||||||
<div
|
<div
|
||||||
ref={headerRef}
|
ref={headerRef}
|
||||||
className="text-center mb-16"
|
className="text-center mb-14"
|
||||||
style={{
|
style={{
|
||||||
opacity: headerVisible ? 1 : 0,
|
opacity: headerVisible ? 1 : 0,
|
||||||
transform: headerVisible ? "translateY(0)" : "translateY(30px)",
|
transform: headerVisible ? "translateY(0)" : "translateY(30px)",
|
||||||
transition: "all 0.6s ease-out",
|
transition: "all 0.6s ease-out",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="inline-block text-sm uppercase tracking-widest text-white/70 mb-4">
|
<span className="inline-flex items-center gap-2 rounded-full border border-border/60 bg-card/60 px-4 py-1 text-xs uppercase tracking-[0.3em] text-muted-foreground">
|
||||||
By The Numbers
|
Platform Metrics
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<h2 className="text-4xl md:text-5xl lg:text-6xl font-black text-white mb-4">
|
<h2 className="mt-6 text-4xl md:text-5xl lg:text-6xl font-semibold text-foreground">
|
||||||
Results That{" "}
|
Corporate-Grade Results, Measured.
|
||||||
<span className="relative">
|
|
||||||
Speak
|
|
||||||
<svg
|
|
||||||
className="absolute -bottom-2 left-0 w-full"
|
|
||||||
viewBox="0 0 200 12"
|
|
||||||
fill="none"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M2 10C50 2 150 2 198 10"
|
|
||||||
stroke="rgba(255,255,255,0.5)"
|
|
||||||
strokeWidth="3"
|
|
||||||
strokeLinecap="round"
|
|
||||||
className="animate-pulse"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
|
<p className="mt-4 text-base md:text-lg text-muted-foreground max-w-2xl mx-auto">
|
||||||
|
Transparent performance benchmarks that prove reliability, accuracy,
|
||||||
|
and compliance at enterprise scale.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Stats Grid */}
|
{/* Stats Grid */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 lg:gap-8">
|
<BentoGrid className="max-w-6xl gap-6 md:auto-rows-[16rem]">
|
||||||
{stats.map((stat, index) => (
|
{stats.map((stat, index) => (
|
||||||
<StatCard
|
<StatCard
|
||||||
key={stat.label}
|
key={stat.label}
|
||||||
@@ -360,39 +373,16 @@ export function Stats() {
|
|||||||
label={stat.label}
|
label={stat.label}
|
||||||
icon={stat.icon}
|
icon={stat.icon}
|
||||||
gradient={stat.gradient}
|
gradient={stat.gradient}
|
||||||
|
className={stat.className}
|
||||||
|
cardColor={stat.cardColor}
|
||||||
|
glowColor={stat.glowColor}
|
||||||
|
spotlight={stat.spotlight}
|
||||||
delay={index * 0.1}
|
delay={index * 0.1}
|
||||||
additional={stat.additional}
|
additional={stat.additional}
|
||||||
isText={stat.isText}
|
isText={stat.isText}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</BentoGrid>
|
||||||
|
|
||||||
{/* Bottom Awards Row */}
|
|
||||||
<div
|
|
||||||
className="mt-16 flex flex-wrap items-center justify-center gap-4"
|
|
||||||
style={{
|
|
||||||
opacity: headerVisible ? 1 : 0,
|
|
||||||
transform: headerVisible ? "translateY(0)" : "translateY(20px)",
|
|
||||||
transition: "all 0.6s ease-out 0.5s",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{[
|
|
||||||
{ icon: Award, text: "Best AI Solution 2024" },
|
|
||||||
{ icon: Shield, text: "SOC 2 Type II Certified" },
|
|
||||||
{ icon: Lock, text: "GDPR Compliant" },
|
|
||||||
{ icon: Check, text: "ISO 27001 Certified" },
|
|
||||||
].map((award, i) => (
|
|
||||||
<div
|
|
||||||
key={i}
|
|
||||||
className="flex items-center gap-2 px-4 py-2 rounded-full bg-white/10 backdrop-blur-sm border border-white/20"
|
|
||||||
>
|
|
||||||
<award.icon className="w-4 h-4 text-white/80" />
|
|
||||||
<span className="text-sm font-medium text-white/90">
|
|
||||||
{award.text}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { useTheme as useNextTheme } from "next-themes";
|
|
||||||
|
|
||||||
export function useTheme() {
|
|
||||||
const { theme, resolvedTheme, setTheme } = useNextTheme();
|
|
||||||
const [mounted, setMounted] = useState(true);
|
|
||||||
|
|
||||||
const currentTheme = resolvedTheme ?? theme ?? "light";
|
|
||||||
|
|
||||||
const toggleTheme = () => {
|
|
||||||
setTheme(currentTheme === "dark" ? "light" : "dark");
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
theme: currentTheme,
|
|
||||||
setTheme,
|
|
||||||
toggleTheme,
|
|
||||||
mounted,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
69
package-lock.json
generated
69
package-lock.json
generated
@@ -43,6 +43,7 @@
|
|||||||
"embla-carousel-react": "^8.6.0",
|
"embla-carousel-react": "^8.6.0",
|
||||||
"input-otp": "^1.4.2",
|
"input-otp": "^1.4.2",
|
||||||
"lucide-react": "^0.564.0",
|
"lucide-react": "^0.564.0",
|
||||||
|
"motion": "^12.34.0",
|
||||||
"next": "16.1.6",
|
"next": "16.1.6",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"react": "19.2.3",
|
"react": "19.2.3",
|
||||||
@@ -5326,6 +5327,33 @@
|
|||||||
"url": "https://github.com/sponsors/rawify"
|
"url": "https://github.com/sponsors/rawify"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/framer-motion": {
|
||||||
|
"version": "12.34.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.34.0.tgz",
|
||||||
|
"integrity": "sha512-+/H49owhzkzQyxtn7nZeF4kdH++I2FWrESQ184Zbcw5cEqNHYkE5yxWxcTLSj5lNx3NWdbIRy5FHqUvetD8FWg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-dom": "^12.34.0",
|
||||||
|
"motion-utils": "^12.29.2",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fsevents": {
|
"node_modules/fsevents": {
|
||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
@@ -6438,6 +6466,47 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/motion": {
|
||||||
|
"version": "12.34.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion/-/motion-12.34.0.tgz",
|
||||||
|
"integrity": "sha512-01Sfa/zgsD/di8zA/uFW5Eb7/SPXoGyUfy+uMRMW5Spa8j0z/UbfQewAYvPMYFCXRlyD6e5aLHh76TxeeJD+RA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"framer-motion": "^12.34.0",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion-dom": {
|
||||||
|
"version": "12.34.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.34.0.tgz",
|
||||||
|
"integrity": "sha512-Lql3NuEcScRDxTAO6GgUsRHBZOWI/3fnMlkMcH5NftzcN37zJta+bpbMAV9px4Nj057TuvRooMK7QrzMCgtz6Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-utils": "^12.29.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion-utils": {
|
||||||
|
"version": "12.29.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.29.2.tgz",
|
||||||
|
"integrity": "sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
"embla-carousel-react": "^8.6.0",
|
"embla-carousel-react": "^8.6.0",
|
||||||
"input-otp": "^1.4.2",
|
"input-otp": "^1.4.2",
|
||||||
"lucide-react": "^0.564.0",
|
"lucide-react": "^0.564.0",
|
||||||
|
"motion": "^12.34.0",
|
||||||
"next": "16.1.6",
|
"next": "16.1.6",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"react": "19.2.3",
|
"react": "19.2.3",
|
||||||
|
|||||||
BIN
public/LexiChain.png
Normal file
BIN
public/LexiChain.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
Reference in New Issue
Block a user