Compare commits
	
		
			5 Commits
		
	
	
		
			886e7557df
			...
			f30006a983
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f30006a983 | |||
| 044f9cf38b | |||
| 5bd2459855 | |||
| 6c0ed3cd65 | |||
| fa0a55d846 | 
							
								
								
									
										10924
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										10924
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										40
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								package.json
									
									
									
									
									
								
							@@ -10,34 +10,44 @@
 | 
				
			|||||||
    "preview": "vite preview"
 | 
					    "preview": "vite preview"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "@headlessui/react": "^2.1.0",
 | 
					    "@headlessui/react": "^2.2.9",
 | 
				
			||||||
    "@tailwindcss/forms": "^0.5.3",
 | 
					    "@heroicons/react": "^2.2.0",
 | 
				
			||||||
    "@tailwindcss/postcss": "^4.1.7",
 | 
					    "@lobehub/icons": "^1.97.2",
 | 
				
			||||||
    "@types/node": "^20.10.8",
 | 
					    "@tabler/icons-react": "^3.35.0",
 | 
				
			||||||
    "@types/react": "^18.2.47",
 | 
					    "@tailwindcss/forms": "^0.5.10",
 | 
				
			||||||
    "@types/react-dom": "^18.2.18",
 | 
					    "@types/node": "^20.19.23",
 | 
				
			||||||
 | 
					    "@types/react": "^18.3.26",
 | 
				
			||||||
 | 
					    "@types/react-dom": "^18.3.7",
 | 
				
			||||||
    "@types/react-router-dom": "^5.3.3",
 | 
					    "@types/react-router-dom": "^5.3.3",
 | 
				
			||||||
 | 
					    "class-variance-authority": "^0.7.1",
 | 
				
			||||||
    "clsx": "^2.1.1",
 | 
					    "clsx": "^2.1.1",
 | 
				
			||||||
    "cobe": "^0.6.5",
 | 
					    "cobe": "^0.6.5",
 | 
				
			||||||
    "framer-motion": "^10.15.0",
 | 
					    "framer-motion": "^10.18.0",
 | 
				
			||||||
    "react": "^18.2.0",
 | 
					    "lucide-react": "^0.544.0",
 | 
				
			||||||
 | 
					    "motion": "^12.23.24",
 | 
				
			||||||
 | 
					    "next": "^14.2.33",
 | 
				
			||||||
 | 
					    "popmotion": "^11.0.5",
 | 
				
			||||||
 | 
					    "react": "^18.3.1",
 | 
				
			||||||
    "react-countup": "^6.5.3",
 | 
					    "react-countup": "^6.5.3",
 | 
				
			||||||
    "react-dom": "^18.2.0",
 | 
					    "react-dom": "^18.3.1",
 | 
				
			||||||
    "react-icons": "^5.5.0",
 | 
					    "react-icons": "^5.5.0",
 | 
				
			||||||
    "react-router-dom": "^7.9.4",
 | 
					    "react-router-dom": "^7.9.4",
 | 
				
			||||||
    "react-type-animation": "^3.2.0",
 | 
					    "react-type-animation": "^3.2.0",
 | 
				
			||||||
    "tailwind-merge": "^3.3.1",
 | 
					    "tailwind-merge": "^3.3.1",
 | 
				
			||||||
    "tailwindcss": "^4.1.7",
 | 
					    "tailwindcss": "^4.1.15",
 | 
				
			||||||
    "typescript": "^5.3.3",
 | 
					    "typescript": "^5.9.3",
 | 
				
			||||||
    "use-debounce": "^10.0.6"
 | 
					    "use-debounce": "^10.0.6"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
 | 
					    "@tailwindcss/postcss": "^4.1.15",
 | 
				
			||||||
    "@vitejs/plugin-react": "^5.0.4",
 | 
					    "@vitejs/plugin-react": "^5.0.4",
 | 
				
			||||||
    "autoprefixer": "^10.4.20",
 | 
					    "autoprefixer": "^10.4.20",
 | 
				
			||||||
    "eslint": "^8.56.0",
 | 
					    "eslint": "^8.57.1",
 | 
				
			||||||
    "prettier": "^3.3.2",
 | 
					    "eslint-config-next": "^14.2.33",
 | 
				
			||||||
    "prettier-plugin-tailwindcss": "^0.6.11",
 | 
					    "prettier": "^3.6.2",
 | 
				
			||||||
    "sharp": "0.33.1",
 | 
					    "prettier-plugin-tailwindcss": "^0.6.14",
 | 
				
			||||||
 | 
					    "sharp": "^0.33.1",
 | 
				
			||||||
 | 
					    "tw-animate-css": "^1.4.0",
 | 
				
			||||||
    "vite": "^7.1.7"
 | 
					    "vite": "^7.1.7"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
		 Before Width: | Height: | Size: 718 KiB  | 
							
								
								
									
										3
									
								
								src/components/logos/Ai21.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/components/logos/Ai21.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					import { Ai21 } from '@lobehub/icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default () => <Ai21.Brand size={30} />;
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/components/logos/AlibabaCloud.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/components/logos/AlibabaCloud.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					import { AlibabaCloud } from '@lobehub/icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default () => <AlibabaCloud.Text size={30} />;
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/components/logos/BaiduCloud.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/components/logos/BaiduCloud.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					import { BaiduCloud } from '@lobehub/icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default () => <BaiduCloud.Combine size={30} />;
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/components/logos/ByteDance.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/components/logos/ByteDance.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					import { ByteDance } from '@lobehub/icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default () => <ByteDance.Text size={30} />;
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/components/logos/Claude.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/components/logos/Claude.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					import { Claude } from '@lobehub/icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default () => <Claude.Combine size={30} />;
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/components/logos/DeepMind.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/components/logos/DeepMind.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					import { DeepMind } from '@lobehub/icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default () => <DeepMind.Combine size={30} />;
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/components/logos/DeepSeek.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/components/logos/DeepSeek.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					import { DeepSeek } from '@lobehub/icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default () => <DeepSeek.Combine size={30} />;
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/components/logos/Minimax.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/components/logos/Minimax.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					import { Minimax } from '@lobehub/icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default () => <Minimax.Combine size={30} />;
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/components/logos/Mistral.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/components/logos/Mistral.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					import { Mistral } from '@lobehub/icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default () => <Mistral.Combine size={30} />;
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/components/logos/Moonshot.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/components/logos/Moonshot.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					import { Moonshot } from '@lobehub/icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default () => <Moonshot.Combine size={30} />;
 | 
				
			||||||
							
								
								
									
										0
									
								
								src/components/logos/NousResearch.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/components/logos/NousResearch.tsx
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										3
									
								
								src/components/logos/OpenAI.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/components/logos/OpenAI.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					import { OpenAI } from '@lobehub/icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default () => <OpenAI.Combine size={30} />;
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/components/logos/TencentCloud.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/components/logos/TencentCloud.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					import { TencentCloud } from '@lobehub/icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default () => <TencentCloud.Combine size={30} />;
 | 
				
			||||||
							
								
								
									
										23
									
								
								src/components/logos/XAI.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/components/logos/XAI.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					const XAILogo = () => (
 | 
				
			||||||
 | 
					  <svg
 | 
				
			||||||
 | 
					    version="1.1"
 | 
				
			||||||
 | 
					    id="katman_1"
 | 
				
			||||||
 | 
					    xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					    xmlnsXlink="http://www.w3.org/1999/xlink"
 | 
				
			||||||
 | 
					    x="0px"
 | 
				
			||||||
 | 
					    y="0px"
 | 
				
			||||||
 | 
					    viewBox="0 0 841.89 595.28"
 | 
				
			||||||
 | 
					        xmlSpace="preserve"
 | 
				
			||||||
 | 
					    width="30"
 | 
				
			||||||
 | 
					    height="30"
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
 | 
					    <g>
 | 
				
			||||||
 | 
					      <polygon points="557.09,211.99 565.4,538.36 631.96,538.36 640.28,93.18 	" />
 | 
				
			||||||
 | 
					      <polygon points="640.28,56.91 538.72,56.91 379.35,284.53 430.13,357.05 	" />
 | 
				
			||||||
 | 
					      <polygon points="201.61,538.36 303.17,538.36 353.96,465.84 303.17,393.31 	" />
 | 
				
			||||||
 | 
					      <polygon points="201.61,211.99 430.13,538.36 531.69,538.36 303.17,211.99 	" />
 | 
				
			||||||
 | 
					    </g>
 | 
				
			||||||
 | 
					  </svg>
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default XAILogo;
 | 
				
			||||||
							
								
								
									
										105
									
								
								src/components/magicui/infinite-moving-cards.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/components/magicui/infinite-moving-cards.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
				
			|||||||
 | 
					"use client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { cn } from "@/lib/utils";
 | 
				
			||||||
 | 
					import React, { useCallback, useEffect, useState } from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const InfiniteMovingCards = ({
 | 
				
			||||||
 | 
					  items,
 | 
				
			||||||
 | 
					  direction = "left",
 | 
				
			||||||
 | 
					  speed = "fast",
 | 
				
			||||||
 | 
					  pauseOnHover = true,
 | 
				
			||||||
 | 
					  className,
 | 
				
			||||||
 | 
					}: {
 | 
				
			||||||
 | 
					  items: React.ReactNode[];
 | 
				
			||||||
 | 
					  direction?: "left" | "right";
 | 
				
			||||||
 | 
					  speed?: "fast" | "normal" | "slow";
 | 
				
			||||||
 | 
					  pauseOnHover?: boolean;
 | 
				
			||||||
 | 
					  className?: string;
 | 
				
			||||||
 | 
					}): JSX.Element => {
 | 
				
			||||||
 | 
					  const containerRef = React.useRef<HTMLDivElement>(null);
 | 
				
			||||||
 | 
					  const scrollerRef = React.useRef<HTMLUListElement>(null);
 | 
				
			||||||
 | 
					  const [start, setStart] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const getDirection = useCallback(() => {
 | 
				
			||||||
 | 
					    if (containerRef.current) {
 | 
				
			||||||
 | 
					      if (direction === "left") {
 | 
				
			||||||
 | 
					        containerRef.current.style.setProperty("--animation-direction", "forwards");
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        containerRef.current.style.setProperty("--animation-direction", "reverse");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }, [direction]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const getSpeed = useCallback(() => {
 | 
				
			||||||
 | 
					    if (containerRef.current) {
 | 
				
			||||||
 | 
					      if (speed === "fast") {
 | 
				
			||||||
 | 
					        containerRef.current.style.setProperty("--animation-duration", "20s");
 | 
				
			||||||
 | 
					      } else if (speed === "normal") {
 | 
				
			||||||
 | 
					        containerRef.current.style.setProperty("--animation-duration", "40s");
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        containerRef.current.style.setProperty("--animation-duration", "80s");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }, [speed]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const addAnimation = useCallback(() => {
 | 
				
			||||||
 | 
					    if (containerRef.current && scrollerRef.current) {
 | 
				
			||||||
 | 
					      const scrollerContent = Array.from(scrollerRef.current.children);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      scrollerContent.forEach((item) => {
 | 
				
			||||||
 | 
					        const duplicatedItem = item.cloneNode(true);
 | 
				
			||||||
 | 
					        if (scrollerRef.current) {
 | 
				
			||||||
 | 
					          scrollerRef.current.appendChild(duplicatedItem);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      getDirection();
 | 
				
			||||||
 | 
					      getSpeed();
 | 
				
			||||||
 | 
					      setStart(true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }, [getDirection, getSpeed]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    addAnimation();
 | 
				
			||||||
 | 
					  }, [addAnimation]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div
 | 
				
			||||||
 | 
					      ref={containerRef}
 | 
				
			||||||
 | 
					      className={cn(
 | 
				
			||||||
 | 
					        "scroller relative z-20 max-w-7xl overflow-hidden [mask-image:linear-gradient(to_right,transparent,white_20%,white_80%,transparent)]",
 | 
				
			||||||
 | 
					        className
 | 
				
			||||||
 | 
					      )}
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <ul
 | 
				
			||||||
 | 
					        ref={scrollerRef}
 | 
				
			||||||
 | 
					        className={cn(
 | 
				
			||||||
 | 
					          "flex min-w-full shrink-0 gap-4 py-4 w-max flex-nowrap",
 | 
				
			||||||
 | 
					          start && "animate-scroll",
 | 
				
			||||||
 | 
					          pauseOnHover && "hover:[animation-play-state:paused]"
 | 
				
			||||||
 | 
					        )}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        {items.map((item, idx) => (
 | 
				
			||||||
 | 
					          <li
 | 
				
			||||||
 | 
					            className="w-[350px] max-w-full relative rounded-2xl border border-b-0 flex-shrink-0 border-slate-700 px-8 py-6 md:w-[450px]"
 | 
				
			||||||
 | 
					            style={{
 | 
				
			||||||
 | 
					              background:
 | 
				
			||||||
 | 
					                "linear-gradient(180deg, var(--slate-800), var(--slate-900))",
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            key={idx}
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            <blockquote>
 | 
				
			||||||
 | 
					              <div
 | 
				
			||||||
 | 
					                aria-hidden="true"
 | 
				
			||||||
 | 
					                className="user-select-none -z-1 pointer-events-none absolute -left-0.5 -top-0.5 h-[calc(100%_+_4px)] w-[calc(100%_+_4px)]"
 | 
				
			||||||
 | 
					              ></div>
 | 
				
			||||||
 | 
					              <span className="relative z-20 text-sm leading-[1.6] text-gray-100 font-normal">
 | 
				
			||||||
 | 
					                {item}
 | 
				
			||||||
 | 
					              </span>
 | 
				
			||||||
 | 
					            </blockquote>
 | 
				
			||||||
 | 
					          </li>
 | 
				
			||||||
 | 
					        ))}
 | 
				
			||||||
 | 
					      </ul>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										131
									
								
								src/components/ui/Cube.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								src/components/ui/Cube.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,131 @@
 | 
				
			|||||||
 | 
					"use client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					import { motion } from "framer-motion";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface CubeProps {
 | 
				
			||||||
 | 
					  title: string;
 | 
				
			||||||
 | 
					  descriptionTitle: string;
 | 
				
			||||||
 | 
					  description: string;
 | 
				
			||||||
 | 
					  isActive: boolean;
 | 
				
			||||||
 | 
					  index: number;
 | 
				
			||||||
 | 
					  onHover: () => void;
 | 
				
			||||||
 | 
					  onLeave: () => void;
 | 
				
			||||||
 | 
					  onClick: () => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const CubeSvg: React.FC<React.SVGProps<SVGSVGElement> & { index: number }> = ({ index, ...props }) => (
 | 
				
			||||||
 | 
					  <svg
 | 
				
			||||||
 | 
					    xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					    width="507"
 | 
				
			||||||
 | 
					    height="234"
 | 
				
			||||||
 | 
					    fill="none"
 | 
				
			||||||
 | 
					    viewBox="0 0 507 234"
 | 
				
			||||||
 | 
					    {...props}
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
 | 
					    <path
 | 
				
			||||||
 | 
					      fill={`url(#cube-gradient-${index})`}
 | 
				
			||||||
 | 
					      d="M491.651 144.747L287.198 227.339C265.219 236.22 241.783 236.22 219.802 227.339L15.3486 144.747C-5.11621 136.479 -5.11621 97.5191 15.3486 89.2539L219.802 6.65884C241.783 -2.21961 265.219 -2.21961 287.198 6.65884L491.651 89.2539C512.116 97.5191 512.116 136.479 491.651 144.747Z"
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
 | 
					    <defs>
 | 
				
			||||||
 | 
					      <linearGradient
 | 
				
			||||||
 | 
					        id={`cube-gradient-${index}`}
 | 
				
			||||||
 | 
					        x1="185.298"
 | 
				
			||||||
 | 
					        x2="185.298"
 | 
				
			||||||
 | 
					        y1="-27.5515"
 | 
				
			||||||
 | 
					        y2="206.448"
 | 
				
			||||||
 | 
					        gradientUnits="userSpaceOnUse"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <stop />
 | 
				
			||||||
 | 
					        <stop offset="1" stopColor="#3F3B3E" />
 | 
				
			||||||
 | 
					      </linearGradient>
 | 
				
			||||||
 | 
					    </defs>
 | 
				
			||||||
 | 
					  </svg>
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function Cube({ title, descriptionTitle, description, isActive, index, onHover, onLeave, onClick }: CubeProps) {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div className="relative flex flex-col items-center">
 | 
				
			||||||
 | 
					      <motion.div
 | 
				
			||||||
 | 
					        className="relative cursor-pointer"
 | 
				
			||||||
 | 
					        onMouseEnter={onHover}
 | 
				
			||||||
 | 
					        onMouseLeave={onLeave}
 | 
				
			||||||
 | 
					        onClick={onClick}
 | 
				
			||||||
 | 
					        style={{
 | 
				
			||||||
 | 
					          zIndex: 10 - index,
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        animate={{
 | 
				
			||||||
 | 
					          scale: isActive ? 1.05 : 1,
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        transition={{
 | 
				
			||||||
 | 
					          duration: 0.3,
 | 
				
			||||||
 | 
					          ease: "easeOut",
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        {/* SVG Cube */}
 | 
				
			||||||
 | 
					        <CubeSvg 
 | 
				
			||||||
 | 
					          index={index}
 | 
				
			||||||
 | 
					          className="w-48 sm:w-64 lg:w-80 h-auto drop-shadow-lg opacity-50"
 | 
				
			||||||
 | 
					          style={{
 | 
				
			||||||
 | 
					            filter: isActive ? 'brightness(1.2) drop-shadow(0 0 20px rgba(156, 163, 175, 0.5))' : 'brightness(0.9)',
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        {/* Title overlay */}
 | 
				
			||||||
 | 
					        <div className="absolute inset-0 flex items-center justify-center">
 | 
				
			||||||
 | 
					          <h3 
 | 
				
			||||||
 | 
					            className="text-white text-sm lg:text-base font-medium text-center px-4 drop-shadow-lg"
 | 
				
			||||||
 | 
					            style={{ 
 | 
				
			||||||
 | 
					              transform: 'rotate(0deg) skewX(0deg)',
 | 
				
			||||||
 | 
					              transformOrigin: 'center'
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {title}
 | 
				
			||||||
 | 
					          </h3>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {/* Description with arrow line - Desktop */}
 | 
				
			||||||
 | 
					        {isActive && (
 | 
				
			||||||
 | 
					          <motion.div
 | 
				
			||||||
 | 
					            initial={{ opacity: 0 }}
 | 
				
			||||||
 | 
					            animate={{ opacity: 1 }}
 | 
				
			||||||
 | 
					            exit={{ opacity: 0 }}
 | 
				
			||||||
 | 
					            transition={{ duration: 0.3 }}
 | 
				
			||||||
 | 
					            className="hidden lg:block absolute left-full top-1/2 -translate-y-1/2 z-50"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {/* Arrow line */}
 | 
				
			||||||
 | 
					            <svg
 | 
				
			||||||
 | 
					              className="absolute left-0 top-1/2 -translate-y-1/2"
 | 
				
			||||||
 | 
					              width="120"
 | 
				
			||||||
 | 
					              height="2"
 | 
				
			||||||
 | 
					              viewBox="0 0 120 2"
 | 
				
			||||||
 | 
					              fill="none"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <line
 | 
				
			||||||
 | 
					                x1="0"
 | 
				
			||||||
 | 
					                y1="1"
 | 
				
			||||||
 | 
					                x2="120"
 | 
				
			||||||
 | 
					                y2="1"
 | 
				
			||||||
 | 
					                stroke="white"
 | 
				
			||||||
 | 
					                strokeWidth="1"
 | 
				
			||||||
 | 
					                opacity="0.6"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </svg>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            {/* Description text */}
 | 
				
			||||||
 | 
					            <div className="ml-32 w-80">
 | 
				
			||||||
 | 
					              <h4 className="text-white text-base font-semibold mb-2">
 | 
				
			||||||
 | 
					                {descriptionTitle}
 | 
				
			||||||
 | 
					              </h4>
 | 
				
			||||||
 | 
					              <p className="text-white text-sm leading-relaxed font-light">
 | 
				
			||||||
 | 
					                {description}
 | 
				
			||||||
 | 
					              </p>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </motion.div>
 | 
				
			||||||
 | 
					        )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {/* Description for Mobile - Below cube */}
 | 
				
			||||||
 | 
					              </motion.div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										131
									
								
								src/components/ui/CubeLight.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								src/components/ui/CubeLight.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,131 @@
 | 
				
			|||||||
 | 
					"use client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					import { motion } from "framer-motion";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface CubeProps {
 | 
				
			||||||
 | 
					  title: string;
 | 
				
			||||||
 | 
					  descriptionTitle: string;
 | 
				
			||||||
 | 
					  description: string;
 | 
				
			||||||
 | 
					  isActive: boolean;
 | 
				
			||||||
 | 
					  index: number;
 | 
				
			||||||
 | 
					  onHover: () => void;
 | 
				
			||||||
 | 
					  onLeave: () => void;
 | 
				
			||||||
 | 
					  onClick: () => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const CubeSvg: React.FC<React.SVGProps<SVGSVGElement> & { index: number }> = ({ index, ...props }) => (
 | 
				
			||||||
 | 
					  <svg
 | 
				
			||||||
 | 
					    xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					    width="507"
 | 
				
			||||||
 | 
					    height="234"
 | 
				
			||||||
 | 
					    fill="none"
 | 
				
			||||||
 | 
					    viewBox="0 0 507 234"
 | 
				
			||||||
 | 
					    {...props}
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
 | 
					    <path
 | 
				
			||||||
 | 
					      fill={`url(#cube-gradient-${index})`}
 | 
				
			||||||
 | 
					      d="M491.651 144.747L287.198 227.339C265.219 236.22 241.783 236.22 219.802 227.339L15.3486 144.747C-5.11621 136.479 -5.11621 97.5191 15.3486 89.2539L219.802 6.65884C241.783 -2.21961 265.219 -2.21961 287.198 6.65884L491.651 89.2539C512.116 97.5191 512.116 136.479 491.651 144.747Z"
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
 | 
					    <defs>
 | 
				
			||||||
 | 
					      <linearGradient
 | 
				
			||||||
 | 
					        id={`cube-gradient-${index}`}
 | 
				
			||||||
 | 
					        x1="185.298"
 | 
				
			||||||
 | 
					        x2="185.298"
 | 
				
			||||||
 | 
					        y1="-27.5515"
 | 
				
			||||||
 | 
					        y2="206.448"
 | 
				
			||||||
 | 
					        gradientUnits="userSpaceOnUse"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <stop stopColor="#E5E7EB" />
 | 
				
			||||||
 | 
					        <stop offset="1" stopColor="#9CA3AF" />
 | 
				
			||||||
 | 
					      </linearGradient>
 | 
				
			||||||
 | 
					    </defs>
 | 
				
			||||||
 | 
					  </svg>
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function CubeLight({ title, descriptionTitle, description, isActive, index, onHover, onLeave, onClick }: CubeProps) {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div className="relative flex flex-col items-center">
 | 
				
			||||||
 | 
					      <motion.div
 | 
				
			||||||
 | 
					        className="relative cursor-pointer"
 | 
				
			||||||
 | 
					        onMouseEnter={onHover}
 | 
				
			||||||
 | 
					        onMouseLeave={onLeave}
 | 
				
			||||||
 | 
					        onClick={onClick}
 | 
				
			||||||
 | 
					        style={{
 | 
				
			||||||
 | 
					          zIndex: 10 - index,
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        animate={{
 | 
				
			||||||
 | 
					          scale: isActive ? 1.05 : 1,
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        transition={{
 | 
				
			||||||
 | 
					          duration: 0.3,
 | 
				
			||||||
 | 
					          ease: "easeOut",
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        {/* SVG Cube */}
 | 
				
			||||||
 | 
					        <CubeSvg 
 | 
				
			||||||
 | 
					          index={index}
 | 
				
			||||||
 | 
					          className="w-48 sm:w-64 lg:w-80 h-auto drop-shadow-lg opacity-80"
 | 
				
			||||||
 | 
					          style={{
 | 
				
			||||||
 | 
					            filter: isActive ? 'brightness(1.1) drop-shadow(0 0 15px rgba(0, 0, 0, 0.2))' : 'brightness(1)',
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        {/* Title overlay */}
 | 
				
			||||||
 | 
					        <div className="absolute inset-0 flex items-center justify-center">
 | 
				
			||||||
 | 
					          <h3 
 | 
				
			||||||
 | 
					            className="text-black text-sm lg:text-base font-medium text-center px-4 drop-shadow-sm"
 | 
				
			||||||
 | 
					            style={{ 
 | 
				
			||||||
 | 
					              transform: 'rotate(0deg) skewX(0deg)',
 | 
				
			||||||
 | 
					              transformOrigin: 'center'
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {title}
 | 
				
			||||||
 | 
					          </h3>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {/* Description with arrow line - Desktop */}
 | 
				
			||||||
 | 
					        {isActive && (
 | 
				
			||||||
 | 
					          <motion.div
 | 
				
			||||||
 | 
					            initial={{ opacity: 0 }}
 | 
				
			||||||
 | 
					            animate={{ opacity: 1 }}
 | 
				
			||||||
 | 
					            exit={{ opacity: 0 }}
 | 
				
			||||||
 | 
					            transition={{ duration: 0.3 }}
 | 
				
			||||||
 | 
					            className="hidden lg:block absolute left-full top-1/2 -translate-y-1/2 z-50"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {/* Arrow line */}
 | 
				
			||||||
 | 
					            <svg
 | 
				
			||||||
 | 
					              className="absolute left-0 top-1/2 -translate-y-1/2"
 | 
				
			||||||
 | 
					              width="120"
 | 
				
			||||||
 | 
					              height="2"
 | 
				
			||||||
 | 
					              viewBox="0 0 120 2"
 | 
				
			||||||
 | 
					              fill="none"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <line
 | 
				
			||||||
 | 
					                x1="0"
 | 
				
			||||||
 | 
					                y1="1"
 | 
				
			||||||
 | 
					                x2="120"
 | 
				
			||||||
 | 
					                y2="1"
 | 
				
			||||||
 | 
					                stroke="black"
 | 
				
			||||||
 | 
					                strokeWidth="1"
 | 
				
			||||||
 | 
					                opacity="0.6"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </svg>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            {/* Description text */}
 | 
				
			||||||
 | 
					            <div className="ml-32 w-80">
 | 
				
			||||||
 | 
					              <h4 className="text-black text-base font-semibold mb-2">
 | 
				
			||||||
 | 
					                {descriptionTitle}
 | 
				
			||||||
 | 
					              </h4>
 | 
				
			||||||
 | 
					              <p className="text-gray-800 text-sm leading-relaxed font-light">
 | 
				
			||||||
 | 
					                {description}
 | 
				
			||||||
 | 
					              </p>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </motion.div>
 | 
				
			||||||
 | 
					        )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {/* Description for Mobile - Below cube */}
 | 
				
			||||||
 | 
					              </motion.div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										22
									
								
								src/components/ui/ScrollDown.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/components/ui/ScrollDown.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					'use client'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { ChevronDoubleDownIcon } from '@heroicons/react/24/outline'
 | 
				
			||||||
 | 
					import { useScroll } from '@/hooks/useScroll'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function ScrollDown() {
 | 
				
			||||||
 | 
					  const { isAtBottom, scrollToNext } = useScroll()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (isAtBottom) {
 | 
				
			||||||
 | 
					    return null
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <button
 | 
				
			||||||
 | 
					      onClick={scrollToNext}
 | 
				
			||||||
 | 
					      className="fixed bottom-8 right-8 z-50 flex items-center gap-x-2 text-2xl font-medium text-white lg:text-3xl animate-blink"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <span>scroll</span>
 | 
				
			||||||
 | 
					      <ChevronDoubleDownIcon className="h-6 w-6" />
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										22
									
								
								src/components/ui/ScrollUp.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/components/ui/ScrollUp.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					'use client'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { ChevronDoubleUpIcon } from '@heroicons/react/24/outline'
 | 
				
			||||||
 | 
					import { useScroll } from '@/hooks/useScroll'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function ScrollUp() {
 | 
				
			||||||
 | 
					  const { isAtBottom, scrollToTop } = useScroll()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!isAtBottom) {
 | 
				
			||||||
 | 
					    return null
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <button
 | 
				
			||||||
 | 
					      onClick={scrollToTop}
 | 
				
			||||||
 | 
					      className="fixed bottom-8 right-8 z-50 flex items-center gap-x-2 text-2xl font-medium text-[#1c1c49] lg:text-3xl animate-blink"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <span>top</span>
 | 
				
			||||||
 | 
					      <ChevronDoubleUpIcon className="h-6 w-6" />
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										95
									
								
								src/components/ui/StackedCubes.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								src/components/ui/StackedCubes.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
				
			|||||||
 | 
					"use client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useState } from "react";
 | 
				
			||||||
 | 
					import { motion } from "framer-motion";
 | 
				
			||||||
 | 
					import { Cube } from "@/components/ui/Cube"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const stackData = [
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: "agent",
 | 
				
			||||||
 | 
					    title: "Agent Layer",
 | 
				
			||||||
 | 
					    descriptionTitle: "Your sovereign agent with private memory and permissioned data access—always under your control.",
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      "Choose from a wide library of open-source LLMs, paired with built-in semantic search and retrieval.\nIt coordinates across people, apps, and other agents to plan, create, and execute.\nIt operates inside a compliant legal & financial sandbox, ready for real-world transactions and operations.\nMore than just an assistant—an intelligent partner that learns and does your way.",
 | 
				
			||||||
 | 
					    position: "top",
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: "network",
 | 
				
			||||||
 | 
					    title: "Network Layer",
 | 
				
			||||||
 | 
					    descriptionTitle: "A global, end-to-end encrypted overlay that simply doesn’t break.",
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      "Shortest-path routing moves your traffic the fastest way, every time.\nInstant discovery with integrated DNS, semantic search, and indexing.\nA distributed CDN and edge delivery keep content available and tamper-resistant worldwide.\nBuilt-in tool services and secure coding sandboxes—seamless on phones, desktops, and edge.",
 | 
				
			||||||
 | 
					    position: "middle",
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: "cloud",
 | 
				
			||||||
 | 
					    title: "Cloud Layer",
 | 
				
			||||||
 | 
					    descriptionTitle: "An autonomous, stateless OS that enforces pre-deterministic deployments you define.",
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      "Workloads are cryptographically bound to your private key—location and access are yours.\nNo cloud vendor or middleman in the path: end-to-end ownership and isolation by default.\nGeo-aware placement delivers locality, compliance, and ultra-low latency where it matters.\nEncrypted, erasure-coded storage, decentralized compute and GPU on demand—including LLMs.",
 | 
				
			||||||
 | 
					    position: "bottom",
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function StackedCubes() {
 | 
				
			||||||
 | 
					  const [active, setActive] = useState<string | null>("agent");
 | 
				
			||||||
 | 
					  const [selectedForMobile, setSelectedForMobile] = useState<string | null>("agent");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleCubeClick = (id: string) => {
 | 
				
			||||||
 | 
					    setSelectedForMobile(prev => (prev === id ? null : id));
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const selectedMobileLayer = stackData.find(layer => layer.id === selectedForMobile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div className="flex flex-col items-center">
 | 
				
			||||||
 | 
					    <div 
 | 
				
			||||||
 | 
					      className="relative w-full flex items-center justify-center lg:justify-center min-h-[450px] lg:min-h-[400px]"
 | 
				
			||||||
 | 
					      onMouseLeave={() => setActive("agent")}
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <motion.div
 | 
				
			||||||
 | 
					        className="relative lg:pl-0 pl-6 h-[300px] lg:h-[400px] w-64 sm:w-80 lg:w-96 scale-120 lg:scale-100"
 | 
				
			||||||
 | 
					        animate={{ y: ["-8px", "8px"] }}
 | 
				
			||||||
 | 
					        transition={{
 | 
				
			||||||
 | 
					          duration: 4,
 | 
				
			||||||
 | 
					          repeat: Infinity,
 | 
				
			||||||
 | 
					          repeatType: "reverse",
 | 
				
			||||||
 | 
					          ease: "easeInOut",
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        {stackData.map((layer, index) => (
 | 
				
			||||||
 | 
					          <div
 | 
				
			||||||
 | 
					            key={layer.id}
 | 
				
			||||||
 | 
					            className="absolute"
 | 
				
			||||||
 | 
					            style={{
 | 
				
			||||||
 | 
					              top: `calc(${index * 30}% - ${index * 10}px)`,
 | 
				
			||||||
 | 
					              zIndex: active === layer.id ? 20 : 10 - index,
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            <Cube
 | 
				
			||||||
 | 
					              title={layer.title}
 | 
				
			||||||
 | 
					              descriptionTitle={layer.descriptionTitle}
 | 
				
			||||||
 | 
					              description={layer.description}
 | 
				
			||||||
 | 
					              isActive={active === layer.id}
 | 
				
			||||||
 | 
					              index={index}
 | 
				
			||||||
 | 
					              onHover={() => setActive(layer.id)}
 | 
				
			||||||
 | 
					              onLeave={() => {}}
 | 
				
			||||||
 | 
					              onClick={() => handleCubeClick(layer.id)}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        ))}
 | 
				
			||||||
 | 
					      </motion.div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    {selectedMobileLayer && (
 | 
				
			||||||
 | 
					      <div className="lg:hidden w-full max-w-md p-6 -mt-8 bg-gray-800/50 rounded-lg">
 | 
				
			||||||
 | 
					        <h4 className="text-white text-lg font-semibold mb-2 text-center">
 | 
				
			||||||
 | 
					          {selectedMobileLayer.descriptionTitle}
 | 
				
			||||||
 | 
					        </h4>
 | 
				
			||||||
 | 
					        <p className="text-gray-300 text-sm leading-relaxed text-center">
 | 
				
			||||||
 | 
					          {selectedMobileLayer.description}
 | 
				
			||||||
 | 
					        </p>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    )}
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										95
									
								
								src/components/ui/StackedCubesLight.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								src/components/ui/StackedCubesLight.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
				
			|||||||
 | 
					"use client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useState } from "react";
 | 
				
			||||||
 | 
					import { motion } from "framer-motion";
 | 
				
			||||||
 | 
					import { CubeLight } from "@/components/ui/CubeLight"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const stackData = [
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: "agent",
 | 
				
			||||||
 | 
					    title: "Agent Layer",
 | 
				
			||||||
 | 
					    descriptionTitle: "Your sovereign agent with private memory and permissioned data access—always under your control.",
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      "Choose from a wide library of open-source LLMs, paired with built-in semantic search and retrieval.\nIt coordinates across people, apps, and other agents to plan, create, and execute.\nIt operates inside a compliant legal & financial sandbox, ready for real-world transactions and operations.\nMore than just an assistant—an intelligent partner that learns and does your way.",
 | 
				
			||||||
 | 
					    position: "top",
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: "network",
 | 
				
			||||||
 | 
					    title: "Network Layer",
 | 
				
			||||||
 | 
					    descriptionTitle: "A global, end-to-end encrypted overlay that simply doesn’t break.",
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      "Shortest-path routing moves your traffic the fastest way, every time.\nInstant discovery with integrated DNS, semantic search, and indexing.\nA distributed CDN and edge delivery keep content available and tamper-resistant worldwide.\nBuilt-in tool services and secure coding sandboxes—seamless on phones, desktops, and edge.",
 | 
				
			||||||
 | 
					    position: "middle",
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: "cloud",
 | 
				
			||||||
 | 
					    title: "Cloud Layer",
 | 
				
			||||||
 | 
					    descriptionTitle: "An autonomous, stateless OS that enforces pre-deterministic deployments you define.",
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      "Workloads are cryptographically bound to your private key—location and access are yours.\nNo cloud vendor or middleman in the path: end-to-end ownership and isolation by default.\nGeo-aware placement delivers locality, compliance, and ultra-low latency where it matters.\nEncrypted, erasure-coded storage, decentralized compute and GPU on demand—including LLMs.",
 | 
				
			||||||
 | 
					    position: "bottom",
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function StackedCubesLight() {
 | 
				
			||||||
 | 
					  const [active, setActive] = useState<string | null>("agent");
 | 
				
			||||||
 | 
					  const [selectedForMobile, setSelectedForMobile] = useState<string | null>("agent");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleCubeClick = (id: string) => {
 | 
				
			||||||
 | 
					    setSelectedForMobile(prev => (prev === id ? null : id));
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const selectedMobileLayer = stackData.find(layer => layer.id === selectedForMobile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div className="flex flex-col items-center">
 | 
				
			||||||
 | 
					    <div 
 | 
				
			||||||
 | 
					      className="relative w-full flex items-center justify-center lg:justify-center min-h-[450px] lg:min-h-[400px]"
 | 
				
			||||||
 | 
					      onMouseLeave={() => setActive("agent")}
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <motion.div
 | 
				
			||||||
 | 
					        className="relative lg:pl-0 pl-6 h-[300px] lg:h-[400px] w-64 sm:w-80 lg:w-96 scale-120 lg:scale-100"
 | 
				
			||||||
 | 
					        animate={{ y: ["-8px", "8px"] }}
 | 
				
			||||||
 | 
					        transition={{
 | 
				
			||||||
 | 
					          duration: 4,
 | 
				
			||||||
 | 
					          repeat: Infinity,
 | 
				
			||||||
 | 
					          repeatType: "reverse",
 | 
				
			||||||
 | 
					          ease: "easeInOut",
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        {stackData.map((layer, index) => (
 | 
				
			||||||
 | 
					          <div
 | 
				
			||||||
 | 
					            key={layer.id}
 | 
				
			||||||
 | 
					            className="absolute"
 | 
				
			||||||
 | 
					            style={{
 | 
				
			||||||
 | 
					              top: `calc(${index * 30}% - ${index * 10}px)`,
 | 
				
			||||||
 | 
					              zIndex: active === layer.id ? 20 : 10 - index,
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            <CubeLight
 | 
				
			||||||
 | 
					              title={layer.title}
 | 
				
			||||||
 | 
					              descriptionTitle={layer.descriptionTitle}
 | 
				
			||||||
 | 
					              description={layer.description}
 | 
				
			||||||
 | 
					              isActive={active === layer.id}
 | 
				
			||||||
 | 
					              index={index}
 | 
				
			||||||
 | 
					              onHover={() => setActive(layer.id)}
 | 
				
			||||||
 | 
					              onLeave={() => {}}
 | 
				
			||||||
 | 
					              onClick={() => handleCubeClick(layer.id)}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        ))}
 | 
				
			||||||
 | 
					      </motion.div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    {selectedMobileLayer && (
 | 
				
			||||||
 | 
					      <div className="lg:hidden w-full max-w-md p-6 -mt-8 bg-gray-200/50 rounded-lg">
 | 
				
			||||||
 | 
					        <h4 className="text-black text-lg font-semibold mb-2 text-center">
 | 
				
			||||||
 | 
					          {selectedMobileLayer.descriptionTitle}
 | 
				
			||||||
 | 
					        </h4>
 | 
				
			||||||
 | 
					        <p className="text-gray-700 text-sm leading-relaxed text-center">
 | 
				
			||||||
 | 
					          {selectedMobileLayer.description}
 | 
				
			||||||
 | 
					        </p>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    )}
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										79
									
								
								src/components/ui/bento-grid.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/components/ui/bento-grid.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,79 @@
 | 
				
			|||||||
 | 
					import { cn } from "@/lib/utils";
 | 
				
			||||||
 | 
					import { CT, CP } from "@/components/Texts";
 | 
				
			||||||
 | 
					import Image from 'next/image';
 | 
				
			||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import { motion } from 'framer-motion';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const BentoGrid = ({
 | 
				
			||||||
 | 
					  className,
 | 
				
			||||||
 | 
					  children,
 | 
				
			||||||
 | 
					}: {
 | 
				
			||||||
 | 
					  className?: string;
 | 
				
			||||||
 | 
					  children?: React.ReactNode;
 | 
				
			||||||
 | 
					}) => {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div
 | 
				
			||||||
 | 
					      className={cn(
 | 
				
			||||||
 | 
					        "mx-4 grid max-w-6xl grid-cols-1 gap-4 lg:grid-cols-3",
 | 
				
			||||||
 | 
					        className,
 | 
				
			||||||
 | 
					      )}
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      {children}
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface BentoGridItemProps {
 | 
				
			||||||
 | 
					  className?: string;
 | 
				
			||||||
 | 
					  title?: string | React.ReactNode;
 | 
				
			||||||
 | 
					  subtitle?: string | React.ReactNode;
 | 
				
			||||||
 | 
					  description?: string | React.ReactNode;
 | 
				
			||||||
 | 
					  img?: string;
 | 
				
			||||||
 | 
					  video?: string;
 | 
				
			||||||
 | 
					  rowHeight?: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const BentoGridItem = React.forwardRef<HTMLDivElement, BentoGridItemProps>(
 | 
				
			||||||
 | 
					  ({ className, title, subtitle, description, img, video, rowHeight }, ref) => {
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <div
 | 
				
			||||||
 | 
					        ref={ref}
 | 
				
			||||||
 | 
					        className={cn(
 | 
				
			||||||
 | 
					          "group/bento shadow-input row-span-1 flex flex-col justify-between rounded-xl border border-black bg-black/10 backdrop-blur-md transition-all duration-300 ease-in-out hover:scale-105 hover:border-black hover:bg-black/40",
 | 
				
			||||||
 | 
					          rowHeight ? rowHeight : "h-full",
 | 
				
			||||||
 | 
					          className
 | 
				
			||||||
 | 
					        )}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					                <div className="relative w-full h-[65%] min-h-[6rem] bg-transparent overflow-hidden">
 | 
				
			||||||
 | 
					          {video ? (
 | 
				
			||||||
 | 
					            <video
 | 
				
			||||||
 | 
					              src={video}
 | 
				
			||||||
 | 
					              autoPlay
 | 
				
			||||||
 | 
					              loop
 | 
				
			||||||
 | 
					              muted
 | 
				
			||||||
 | 
					              playsInline
 | 
				
			||||||
 | 
					              className="w-full h-full object-cover opacity-90 group-hover/bento:opacity-100 transition-opacity duration-300"
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          ) : img ? (
 | 
				
			||||||
 | 
					            <Image
 | 
				
			||||||
 | 
					              src={img}
 | 
				
			||||||
 | 
					              alt={title as string}
 | 
				
			||||||
 | 
					              width={300}
 | 
				
			||||||
 | 
					              height={300}
 | 
				
			||||||
 | 
					              className="w-full h-full object-cover opacity-90 group-hover/bento:opacity-100 transition-opacity duration-300"
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          ) : null}
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div className="p-4 transition bg-white/5 hover:bg-white/7 backdrop-blur-md duration-200 group-hover/bento:translate-x-2 ">
 | 
				
			||||||
 | 
					          <CT>{title}</CT>
 | 
				
			||||||
 | 
					          <CP className="font-medium">{subtitle}</CP>
 | 
				
			||||||
 | 
					          <CP className="mt-2">{description}</CP>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BentoGridItem.displayName = "BentoGridItem";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const MotionBentoGridItem = motion(BentoGridItem);
 | 
				
			||||||
							
								
								
									
										308
									
								
								src/components/ui/dotted-glow-background.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										308
									
								
								src/components/ui/dotted-glow-background.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,308 @@
 | 
				
			|||||||
 | 
					"use client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import React, { useEffect, useRef, useState } from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DottedGlowBackgroundProps = {
 | 
				
			||||||
 | 
					  className?: string;
 | 
				
			||||||
 | 
					  /** distance between dot centers in pixels */
 | 
				
			||||||
 | 
					  gap?: number;
 | 
				
			||||||
 | 
					  /** base radius of each dot in CSS px */
 | 
				
			||||||
 | 
					  radius?: number;
 | 
				
			||||||
 | 
					  /** dot color (will pulse by alpha) */
 | 
				
			||||||
 | 
					  color?: string;
 | 
				
			||||||
 | 
					  /** optional dot color for dark mode */
 | 
				
			||||||
 | 
					  darkColor?: string;
 | 
				
			||||||
 | 
					  /** shadow/glow color for bright dots */
 | 
				
			||||||
 | 
					  glowColor?: string;
 | 
				
			||||||
 | 
					  /** optional glow color for dark mode */
 | 
				
			||||||
 | 
					  darkGlowColor?: string;
 | 
				
			||||||
 | 
					  /** optional CSS variable name for light dot color (e.g. --color-zinc-900) */
 | 
				
			||||||
 | 
					  colorLightVar?: string;
 | 
				
			||||||
 | 
					  /** optional CSS variable name for dark dot color (e.g. --color-zinc-100) */
 | 
				
			||||||
 | 
					  colorDarkVar?: string;
 | 
				
			||||||
 | 
					  /** optional CSS variable name for light glow color */
 | 
				
			||||||
 | 
					  glowColorLightVar?: string;
 | 
				
			||||||
 | 
					  /** optional CSS variable name for dark glow color */
 | 
				
			||||||
 | 
					  glowColorDarkVar?: string;
 | 
				
			||||||
 | 
					  /** global opacity for the whole layer */
 | 
				
			||||||
 | 
					  opacity?: number;
 | 
				
			||||||
 | 
					  /** background radial fade opacity (0 = transparent background) */
 | 
				
			||||||
 | 
					  backgroundOpacity?: number;
 | 
				
			||||||
 | 
					  /** minimum per-dot speed in rad/s */
 | 
				
			||||||
 | 
					  speedMin?: number;
 | 
				
			||||||
 | 
					  /** maximum per-dot speed in rad/s */
 | 
				
			||||||
 | 
					  speedMax?: number;
 | 
				
			||||||
 | 
					  /** global speed multiplier for all dots */
 | 
				
			||||||
 | 
					  speedScale?: number;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Canvas-based dotted background that randomly glows and dims.
 | 
				
			||||||
 | 
					 * - Uses a stable grid of dots.
 | 
				
			||||||
 | 
					 * - Each dot gets its own phase + speed producing organic shimmering.
 | 
				
			||||||
 | 
					 * - Handles high-DPI and resizes via ResizeObserver.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function DottedGlowBackground({
 | 
				
			||||||
 | 
					  className,
 | 
				
			||||||
 | 
					  gap = 12,
 | 
				
			||||||
 | 
					  radius = 2,
 | 
				
			||||||
 | 
					  color = "rgba(0,0,0,0.7)",
 | 
				
			||||||
 | 
					  darkColor,
 | 
				
			||||||
 | 
					  glowColor = "rgba(0, 170, 255, 0.85)",
 | 
				
			||||||
 | 
					  darkGlowColor,
 | 
				
			||||||
 | 
					  colorLightVar,
 | 
				
			||||||
 | 
					  colorDarkVar,
 | 
				
			||||||
 | 
					  glowColorLightVar,
 | 
				
			||||||
 | 
					  glowColorDarkVar,
 | 
				
			||||||
 | 
					  opacity = 0.6,
 | 
				
			||||||
 | 
					  backgroundOpacity = 0,
 | 
				
			||||||
 | 
					  speedMin = 0.4,
 | 
				
			||||||
 | 
					  speedMax = 1.3,
 | 
				
			||||||
 | 
					  speedScale = 1,
 | 
				
			||||||
 | 
					}: DottedGlowBackgroundProps) {
 | 
				
			||||||
 | 
					  const canvasRef = useRef<HTMLCanvasElement | null>(null);
 | 
				
			||||||
 | 
					  const containerRef = useRef<HTMLDivElement | null>(null);
 | 
				
			||||||
 | 
					  const [resolvedColor, setResolvedColor] = useState<string>(color);
 | 
				
			||||||
 | 
					  const [resolvedGlowColor, setResolvedGlowColor] = useState<string>(glowColor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Resolve CSS variable value from the container or root
 | 
				
			||||||
 | 
					  const resolveCssVariable = (
 | 
				
			||||||
 | 
					    el: Element,
 | 
				
			||||||
 | 
					    variableName?: string,
 | 
				
			||||||
 | 
					  ): string | null => {
 | 
				
			||||||
 | 
					    if (!variableName) return null;
 | 
				
			||||||
 | 
					    const normalized = variableName.startsWith("--")
 | 
				
			||||||
 | 
					      ? variableName
 | 
				
			||||||
 | 
					      : `--${variableName}`;
 | 
				
			||||||
 | 
					    const fromEl = getComputedStyle(el as Element)
 | 
				
			||||||
 | 
					      .getPropertyValue(normalized)
 | 
				
			||||||
 | 
					      .trim();
 | 
				
			||||||
 | 
					    if (fromEl) return fromEl;
 | 
				
			||||||
 | 
					    const root = document.documentElement;
 | 
				
			||||||
 | 
					    const fromRoot = getComputedStyle(root).getPropertyValue(normalized).trim();
 | 
				
			||||||
 | 
					    return fromRoot || null;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const detectDarkMode = (): boolean => {
 | 
				
			||||||
 | 
					    const root = document.documentElement;
 | 
				
			||||||
 | 
					    if (root.classList.contains("dark")) return true;
 | 
				
			||||||
 | 
					    if (root.classList.contains("light")) return false;
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      window.matchMedia &&
 | 
				
			||||||
 | 
					      window.matchMedia("(prefers-color-scheme: dark)").matches
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Keep resolved colors in sync with theme changes and prop updates
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    const container = containerRef.current ?? document.documentElement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const compute = () => {
 | 
				
			||||||
 | 
					      const isDark = detectDarkMode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      let nextColor: string = color;
 | 
				
			||||||
 | 
					      let nextGlow: string = glowColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (isDark) {
 | 
				
			||||||
 | 
					        const varDot = resolveCssVariable(container, colorDarkVar);
 | 
				
			||||||
 | 
					        const varGlow = resolveCssVariable(container, glowColorDarkVar);
 | 
				
			||||||
 | 
					        nextColor = varDot || darkColor || nextColor;
 | 
				
			||||||
 | 
					        nextGlow = varGlow || darkGlowColor || nextGlow;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        const varDot = resolveCssVariable(container, colorLightVar);
 | 
				
			||||||
 | 
					        const varGlow = resolveCssVariable(container, glowColorLightVar);
 | 
				
			||||||
 | 
					        nextColor = varDot || nextColor;
 | 
				
			||||||
 | 
					        nextGlow = varGlow || nextGlow;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      setResolvedColor(nextColor);
 | 
				
			||||||
 | 
					      setResolvedGlowColor(nextGlow);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    compute();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const mql = window.matchMedia
 | 
				
			||||||
 | 
					      ? window.matchMedia("(prefers-color-scheme: dark)")
 | 
				
			||||||
 | 
					      : null;
 | 
				
			||||||
 | 
					    const handleMql = () => compute();
 | 
				
			||||||
 | 
					    mql?.addEventListener?.("change", handleMql);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const mo = new MutationObserver(() => compute());
 | 
				
			||||||
 | 
					    mo.observe(document.documentElement, {
 | 
				
			||||||
 | 
					      attributes: true,
 | 
				
			||||||
 | 
					      attributeFilter: ["class", "style"],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return () => {
 | 
				
			||||||
 | 
					      mql?.removeEventListener?.("change", handleMql);
 | 
				
			||||||
 | 
					      mo.disconnect();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  }, [
 | 
				
			||||||
 | 
					    color,
 | 
				
			||||||
 | 
					    darkColor,
 | 
				
			||||||
 | 
					    glowColor,
 | 
				
			||||||
 | 
					    darkGlowColor,
 | 
				
			||||||
 | 
					    colorLightVar,
 | 
				
			||||||
 | 
					    colorDarkVar,
 | 
				
			||||||
 | 
					    glowColorLightVar,
 | 
				
			||||||
 | 
					    glowColorDarkVar,
 | 
				
			||||||
 | 
					  ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    const el = canvasRef.current;
 | 
				
			||||||
 | 
					    const container = containerRef.current;
 | 
				
			||||||
 | 
					    if (!el || !container) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const ctx = el.getContext("2d");
 | 
				
			||||||
 | 
					    if (!ctx) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let raf = 0;
 | 
				
			||||||
 | 
					    let stopped = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const dpr = Math.max(1, window.devicePixelRatio || 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const resize = () => {
 | 
				
			||||||
 | 
					      const { width, height } = container.getBoundingClientRect();
 | 
				
			||||||
 | 
					      el.width = Math.max(1, Math.floor(width * dpr));
 | 
				
			||||||
 | 
					      el.height = Math.max(1, Math.floor(height * dpr));
 | 
				
			||||||
 | 
					      el.style.width = `${Math.floor(width)}px`;
 | 
				
			||||||
 | 
					      el.style.height = `${Math.floor(height)}px`;
 | 
				
			||||||
 | 
					      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const ro = new ResizeObserver(resize);
 | 
				
			||||||
 | 
					    ro.observe(container);
 | 
				
			||||||
 | 
					    resize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Precompute dot metadata for a medium-sized grid and regenerate on resize
 | 
				
			||||||
 | 
					    let dots: { x: number; y: number; phase: number; speed: number }[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const regenDots = () => {
 | 
				
			||||||
 | 
					      dots = [];
 | 
				
			||||||
 | 
					      const { width, height } = container.getBoundingClientRect();
 | 
				
			||||||
 | 
					      const cols = Math.ceil(width / gap) + 2;
 | 
				
			||||||
 | 
					      const rows = Math.ceil(height / gap) + 2;
 | 
				
			||||||
 | 
					      const min = Math.min(speedMin, speedMax);
 | 
				
			||||||
 | 
					      const max = Math.max(speedMin, speedMax);
 | 
				
			||||||
 | 
					      for (let i = -1; i < cols; i++) {
 | 
				
			||||||
 | 
					        for (let j = -1; j < rows; j++) {
 | 
				
			||||||
 | 
					          const x = i * gap + (j % 2 === 0 ? 0 : gap * 0.5); // offset every other row
 | 
				
			||||||
 | 
					          const y = j * gap;
 | 
				
			||||||
 | 
					          // Randomize phase and speed slightly per dot
 | 
				
			||||||
 | 
					          const phase = Math.random() * Math.PI * 2;
 | 
				
			||||||
 | 
					          const span = Math.max(max - min, 0);
 | 
				
			||||||
 | 
					          const speed = min + Math.random() * span; // configurable rad/s
 | 
				
			||||||
 | 
					          dots.push({ x, y, phase, speed });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const regenThrottled = () => {
 | 
				
			||||||
 | 
					      regenDots();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    regenDots();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let last = performance.now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const draw = (now: number) => {
 | 
				
			||||||
 | 
					      if (stopped) return;
 | 
				
			||||||
 | 
					      const dt = (now - last) / 1000; // seconds
 | 
				
			||||||
 | 
					      last = now;
 | 
				
			||||||
 | 
					      const { width, height } = container.getBoundingClientRect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      ctx.clearRect(0, 0, el.width, el.height);
 | 
				
			||||||
 | 
					      ctx.globalAlpha = opacity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // optional subtle background fade for depth (defaults to 0 = transparent)
 | 
				
			||||||
 | 
					      if (backgroundOpacity > 0) {
 | 
				
			||||||
 | 
					        const grad = ctx.createRadialGradient(
 | 
				
			||||||
 | 
					          width * 0.5,
 | 
				
			||||||
 | 
					          height * 0.4,
 | 
				
			||||||
 | 
					          Math.min(width, height) * 0.1,
 | 
				
			||||||
 | 
					          width * 0.5,
 | 
				
			||||||
 | 
					          height * 0.5,
 | 
				
			||||||
 | 
					          Math.max(width, height) * 0.7,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        grad.addColorStop(0, "rgba(0,0,0,0)");
 | 
				
			||||||
 | 
					        grad.addColorStop(
 | 
				
			||||||
 | 
					          1,
 | 
				
			||||||
 | 
					          `rgba(0,0,0,${Math.min(Math.max(backgroundOpacity, 0), 1)})`,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        ctx.fillStyle = grad as unknown as CanvasGradient;
 | 
				
			||||||
 | 
					        ctx.fillRect(0, 0, width, height);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // animate dots
 | 
				
			||||||
 | 
					      ctx.save();
 | 
				
			||||||
 | 
					      ctx.fillStyle = resolvedColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const time = (now / 1000) * Math.max(speedScale, 0);
 | 
				
			||||||
 | 
					      for (let i = 0; i < dots.length; i++) {
 | 
				
			||||||
 | 
					        const d = dots[i];
 | 
				
			||||||
 | 
					        // Linear triangle wave 0..1..0 for linear glow/dim
 | 
				
			||||||
 | 
					        const mod = (time * d.speed + d.phase) % 2;
 | 
				
			||||||
 | 
					        const lin = mod < 1 ? mod : 2 - mod; // 0..1..0
 | 
				
			||||||
 | 
					        const a = 0.25 + 0.55 * lin; // 0.25..0.8 linearly
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // draw glow when bright
 | 
				
			||||||
 | 
					        if (a > 0.6) {
 | 
				
			||||||
 | 
					          const glow = (a - 0.6) / 0.4; // 0..1
 | 
				
			||||||
 | 
					          ctx.shadowColor = resolvedGlowColor;
 | 
				
			||||||
 | 
					          ctx.shadowBlur = 6 * glow;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          ctx.shadowColor = "transparent";
 | 
				
			||||||
 | 
					          ctx.shadowBlur = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ctx.globalAlpha = a * opacity;
 | 
				
			||||||
 | 
					        ctx.beginPath();
 | 
				
			||||||
 | 
					        ctx.arc(d.x, d.y, radius, 0, Math.PI * 2);
 | 
				
			||||||
 | 
					        ctx.fill();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      ctx.restore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      raf = requestAnimationFrame(draw);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const handleResize = () => {
 | 
				
			||||||
 | 
					      resize();
 | 
				
			||||||
 | 
					      regenThrottled();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    window.addEventListener("resize", handleResize);
 | 
				
			||||||
 | 
					    raf = requestAnimationFrame(draw);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return () => {
 | 
				
			||||||
 | 
					      stopped = true;
 | 
				
			||||||
 | 
					      cancelAnimationFrame(raf);
 | 
				
			||||||
 | 
					      window.removeEventListener("resize", handleResize);
 | 
				
			||||||
 | 
					      ro.disconnect();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  }, [
 | 
				
			||||||
 | 
					    gap,
 | 
				
			||||||
 | 
					    radius,
 | 
				
			||||||
 | 
					    resolvedColor,
 | 
				
			||||||
 | 
					    resolvedGlowColor,
 | 
				
			||||||
 | 
					    opacity,
 | 
				
			||||||
 | 
					    backgroundOpacity,
 | 
				
			||||||
 | 
					    speedMin,
 | 
				
			||||||
 | 
					    speedMax,
 | 
				
			||||||
 | 
					    speedScale,
 | 
				
			||||||
 | 
					  ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div
 | 
				
			||||||
 | 
					      ref={containerRef}
 | 
				
			||||||
 | 
					      className={className}
 | 
				
			||||||
 | 
					      style={{ position: "absolute", inset: 0 }}
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <canvas
 | 
				
			||||||
 | 
					        ref={canvasRef}
 | 
				
			||||||
 | 
					        style={{ display: "block", width: "100%", height: "100%" }}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default DottedGlowBackground;
 | 
				
			||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
import { AnimatedSection } from '../../components/AnimatedSection'
 | 
					import { AnimatedSection } from '../../components/AnimatedSection'
 | 
				
			||||||
import { DeploySection } from './DeploySection'
 | 
					import { DeploySection } from './DeploySection'
 | 
				
			||||||
import { GallerySection } from './GallerySection'
 | 
					import { GallerySection } from './GallerySection'
 | 
				
			||||||
 | 
					import { Companies } from './Companies'
 | 
				
			||||||
import { BentoSection } from './BentoSection'
 | 
					import { BentoSection } from './BentoSection'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function AgentsPage() {
 | 
					export default function AgentsPage() {
 | 
				
			||||||
@@ -10,6 +11,11 @@ export default function AgentsPage() {
 | 
				
			|||||||
        <DeploySection />
 | 
					        <DeploySection />
 | 
				
			||||||
      </AnimatedSection>
 | 
					      </AnimatedSection>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <AnimatedSection>
 | 
				
			||||||
 | 
					        <Companies />
 | 
				
			||||||
 | 
					      </AnimatedSection>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
      <AnimatedSection>
 | 
					      <AnimatedSection>
 | 
				
			||||||
        <GallerySection />
 | 
					        <GallerySection />
 | 
				
			||||||
      </AnimatedSection>
 | 
					      </AnimatedSection>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										76
									
								
								src/pages/agents/Companies.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/pages/agents/Companies.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
				
			|||||||
 | 
					"use client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					import { motion } from "framer-motion";
 | 
				
			||||||
 | 
					import { P, Eyebrow } from '@/components/Texts';
 | 
				
			||||||
 | 
					import { InfiniteMovingCards } from "@/components/magicui/infinite-moving-cards";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import Ai21 from '@/components/logos/Ai21';
 | 
				
			||||||
 | 
					import Claude from '@/components/logos/Claude';
 | 
				
			||||||
 | 
					import BaiduCloud from '@/components/logos/BaiduCloud';
 | 
				
			||||||
 | 
					import ByteDance from '@/components/logos/ByteDance';
 | 
				
			||||||
 | 
					import DeepSeek from '@/components/logos/DeepSeek';
 | 
				
			||||||
 | 
					import DeepMind from '@/components/logos/DeepMind';
 | 
				
			||||||
 | 
					import Minimax from '@/components/logos/Minimax';
 | 
				
			||||||
 | 
					import Mistral from '@/components/logos/Mistral';
 | 
				
			||||||
 | 
					import Moonshot from '@/components/logos/Moonshot';
 | 
				
			||||||
 | 
					import TencentCloud from '@/components/logos/TencentCloud';
 | 
				
			||||||
 | 
					import OpenAI from '@/components/logos/OpenAI';
 | 
				
			||||||
 | 
					import XAI from '@/components/logos/XAI';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const logos = [
 | 
				
			||||||
 | 
					  <Ai21 key="ai21" />,
 | 
				
			||||||
 | 
					  <Claude key="claude" />,
 | 
				
			||||||
 | 
					  <BaiduCloud key="baidu" />,
 | 
				
			||||||
 | 
					  <ByteDance key="bytedance" />,
 | 
				
			||||||
 | 
					  <DeepSeek key="deepseek" />,
 | 
				
			||||||
 | 
					  <DeepMind key="deepmind" />,
 | 
				
			||||||
 | 
					  <Minimax key="minimax" />,
 | 
				
			||||||
 | 
					  <Mistral key="mistral" />,
 | 
				
			||||||
 | 
					  <Moonshot key="moonshot" />,
 | 
				
			||||||
 | 
					  <TencentCloud key="tencent" />,
 | 
				
			||||||
 | 
					  <OpenAI key="openai" />,
 | 
				
			||||||
 | 
					  <XAI key="xai" />,
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const row1 = logos.slice(0, 6);
 | 
				
			||||||
 | 
					const row2 = logos.slice(6);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function Companies() {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div id="companies" className="relative bg-black flex flex-col items-center justify-center w-full overflow-hidden antialiased  py-4 mb-12">
 | 
				
			||||||
 | 
					      <div className="relative z-10 mx-auto w-full max-w-6xl p-4">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {/* Heading */}
 | 
				
			||||||
 | 
					        <motion.div
 | 
				
			||||||
 | 
					          className="flex flex-col justify-center max-w-4xl items-center mb-8 mx-auto"
 | 
				
			||||||
 | 
					          initial={{ opacity: 0, y: 20 }}
 | 
				
			||||||
 | 
					          animate={{ opacity: 1, y: 0 }}
 | 
				
			||||||
 | 
					          transition={{ duration: 1 }}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          <Eyebrow color="accent"></Eyebrow>
 | 
				
			||||||
 | 
					          <P className="hidden min-xl:text-gray-100 text-center mb-6">
 | 
				
			||||||
 | 
					            Mycelium Cloud allows you to deploy and scale AI agents from top global providers on a decentralized, privacy-first infrastructure.
 | 
				
			||||||
 | 
					          </P>
 | 
				
			||||||
 | 
					        </motion.div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {/* Logos grid */}
 | 
				
			||||||
 | 
					        <div className="flex flex-col items-center gap-y-6 text-white">
 | 
				
			||||||
 | 
					          <InfiniteMovingCards
 | 
				
			||||||
 | 
					            items={row1}
 | 
				
			||||||
 | 
					            direction="right"
 | 
				
			||||||
 | 
					            speed="slow"
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					          <InfiniteMovingCards
 | 
				
			||||||
 | 
					            className=""
 | 
				
			||||||
 | 
					            items={row2}
 | 
				
			||||||
 | 
					            direction="left"
 | 
				
			||||||
 | 
					            speed="slow"
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user