fix rbuild
This commit is contained in:
@@ -1,46 +1,43 @@
|
||||
export function CallTo() {
|
||||
return (
|
||||
<div className="bg-transparent">
|
||||
<div className="mx-auto max-w-7xl py-24 px-6 lg:px-4">
|
||||
<div className="relative isolate overflow-hidden bg-stat-gradient py-16 text-center after:pointer-events-none after:absolute after:inset-0 sm:rounded-3xl sm:px-16">
|
||||
<div className="mx-auto max-w-2xl lg:max-w-2xl">
|
||||
<h2 className="text-3xl font-semibold tracking-tight leading-tight text-white lg:text-5xl">
|
||||
Say Hello to Decentralized AI Agents that are Truly Yours
|
||||
</h2>
|
||||
<p className="mx-auto mt-6 mb-4 max-w-xl text-base font-light text-pretty text-white lg:text-lg">
|
||||
import { H2, P } from '@/components/Texts'
|
||||
|
||||
export function CallTo() {
|
||||
return (
|
||||
<div className="relative isolate overflow-hidden max-w-5xl mx-auto py-24">
|
||||
<div className="relative isolate overflow-hidden bg-gray-50/10 px-6 py-24 text-center shadow-md shadow-gray-900/5 sm:rounded-3xl sm:px-16 border border-gray-200">
|
||||
<div className="mx-auto max-w-4xl text-center">
|
||||
<H2 color="primary">
|
||||
Say hello to Decentralized AI Agents that are Truly Yours
|
||||
</H2>
|
||||
<P color="custom" className="mt-8 max-w-3xl">
|
||||
Why hand out your intelligence to centralized giants when you can build your own?
|
||||
</p>
|
||||
<p className="mx-auto max-w-xl text-base font-light text-pretty text-white lg:text-lg">
|
||||
With Project Mycelium’s Decentralized Agentic Cloud, you’re not just adopting AI—you’re claiming your own sovereign, autonomous AI infrastructure that grows and evolves with you.
|
||||
</p>
|
||||
<div className="mt-10 flex items-center justify-center gap-x-6">
|
||||
<a
|
||||
href="#"
|
||||
className="rounded-md bg-white/10 px-3.5 py-2.5 text-base font-semibold text-white hover:bg-white/15"
|
||||
>
|
||||
{' '}
|
||||
Book a Meeting{' '}
|
||||
</a>
|
||||
<a href="#" className="rounded-md bg-white/10 px-3.5 py-2.5 text-base font-semibold text-white hover:bg-white/15">
|
||||
Join the Waitlist
|
||||
</a>
|
||||
</div>
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
aria-hidden="true"
|
||||
className="absolute top-1/2 left-1/2 -z-10 size-256 -translate-x-1/2 mask-[radial-gradient(closest-side,white,transparent)]"
|
||||
</P>
|
||||
<div className="mt-10 flex items-center justify-center gap-x-6">
|
||||
<a
|
||||
href="#"
|
||||
className="rounded-md bg-[#2F3178] px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-[#2F3178]/80 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#2F3178]"
|
||||
>
|
||||
<circle r={512} cx={512} cy={512} fill="url(#827591b1-ce8c-4110-b064-7cb85a0b1217)" fillOpacity="0.7" />
|
||||
<defs>
|
||||
<radialGradient id="827591b1-ce8c-4110-b064-7cb85a0b1217">
|
||||
<stop stopColor="#fff4f8" />
|
||||
<stop offset={1} stopColor="#97979d" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
Book a Meeting
|
||||
</a>
|
||||
<a href="#" className="text-sm/6 font-semibold text-[#2F3178] hover:text-[#2F3178]/80">
|
||||
Join the Waitlist <span aria-hidden="true">→</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
aria-hidden="true"
|
||||
className="absolute top-1/2 left-1/2 -z-10 size-256 -translate-x-1/2 mask-[radial-gradient(closest-side,white,transparent)]"
|
||||
>
|
||||
<circle r={512} cx={512} cy={512} fill="url(#8d958450-c69f-4251-94bc-4e091a323369)" fillOpacity="1" />
|
||||
<defs>
|
||||
<radialGradient id="8d958450-c69f-4251-94bc-4e091a323369">
|
||||
<stop stopColor="#B5A8EF" />
|
||||
<stop offset={1} stopColor="#8479D9" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
@@ -1,8 +1,8 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useEffect, useMemo, useState, useRef } from 'react'
|
||||
import Image from 'next/image'
|
||||
import { motion, AnimatePresence } from 'framer-motion'
|
||||
import { motion, AnimatePresence, useInView } from 'framer-motion'
|
||||
import { wrap } from 'popmotion'
|
||||
import { Button } from '@/components/Button';
|
||||
import { H2, P, H4 } from '@/components/Texts';
|
||||
@@ -34,6 +34,8 @@ const AUTOPLAY_MS = 3200
|
||||
export function ClickableGallery() {
|
||||
const [active, setActive] = useState(0)
|
||||
const [hovering, setHovering] = useState(false)
|
||||
const ref = useRef(null);
|
||||
const isInView = useInView(ref, { once: true });
|
||||
|
||||
// autoplay
|
||||
useEffect(() => {
|
||||
@@ -51,17 +53,20 @@ export function ClickableGallery() {
|
||||
const prev = () => setActive((i) => wrap(0, galleryItems.length, i - 1))
|
||||
|
||||
return (
|
||||
<>
|
||||
<div ref={ref}>
|
||||
<div className="relative isolate pt-24 pb-0 text-center w-full">
|
||||
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 1, delay: 1 }} className="mx-auto max-w-5xl">
|
||||
<motion.div initial={{ opacity: 0, y: 20 }} animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }} transition={{ duration: 0.8, delay: 0.1 }} className="mx-auto max-w-5xl">
|
||||
<H2 className="text-center">One Agent, Endless Possibilities.</H2>
|
||||
</motion.div>
|
||||
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 1, delay: 1.5 }} className="mx-auto max-w-4xl mt-6">
|
||||
<motion.div initial={{ opacity: 0, y: 20 }} animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }} transition={{ duration: 0.8, delay: 0.2 }} className="mx-auto max-w-4xl mt-6">
|
||||
<P className="text-center" color="custom">
|
||||
The future isn’t about more tools. It’s about one intelligent partner that can do it all. This is your gateway to creativity, automation, and discovery.
|
||||
</P>
|
||||
</motion.div>
|
||||
<div
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
||||
transition={{ duration: 1, delay: 0.3 }}
|
||||
aria-hidden="true"
|
||||
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
|
||||
>
|
||||
@@ -72,9 +77,12 @@ export function ClickableGallery() {
|
||||
}}
|
||||
className="relative left-[calc(50%-30rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#93c5fd] to-[#9089fc] opacity-30 sm:left-[calc(50%-36rem)] sm:w-[72.1875rem]"
|
||||
/>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
<section
|
||||
<motion.section
|
||||
initial={{ opacity: 0 }}
|
||||
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
||||
transition={{ duration: 1, delay: 0.4 }}
|
||||
className="relative w-full flex items-center justify-center overflow-hidden bg-background -mt-16 pt-0 pb-32"
|
||||
onMouseEnter={() => setHovering(true)}
|
||||
onMouseLeave={() => setHovering(false)}
|
||||
@@ -180,7 +188,7 @@ export function ClickableGallery() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
</motion.section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@@ -1,4 +1,8 @@
|
||||
'use client'
|
||||
|
||||
import { Container } from '@/components/Container'
|
||||
import { motion, useInView } from 'framer-motion'
|
||||
import { useRef } from 'react'
|
||||
|
||||
const faqs = [
|
||||
[
|
||||
@@ -22,7 +26,7 @@ const faqs = [
|
||||
{
|
||||
question: 'How can I find and use my Mycelium address?',
|
||||
answer:
|
||||
'Upon using the Mycelium app, you\'re assigned a unique Mycelium address. To copy this address, click the button located to the right of the displayed address in the app interface.',
|
||||
"Upon using the Mycelium app, you're assigned a unique Mycelium address. To copy this address, click the button located to the right of the displayed address in the app interface.",
|
||||
},
|
||||
{
|
||||
question: 'Can I deploy workloads on the TFGrid using Mycelium?',
|
||||
@@ -50,17 +54,41 @@ const faqs = [
|
||||
]
|
||||
|
||||
export function Faqs() {
|
||||
const ref = useRef(null);
|
||||
const isInView = useInView(ref, { once: true });
|
||||
|
||||
return (
|
||||
<section
|
||||
id="faqs"
|
||||
ref={ref}
|
||||
aria-labelledby="faqs-title"
|
||||
className="border-t border-gray-200 py-20 sm:py-32"
|
||||
className="border-t border-gray-200 py-20 sm:py-32 relative overflow-hidden"
|
||||
>
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
||||
transition={{ duration: 1, delay: 0.1 }}
|
||||
aria-hidden="true"
|
||||
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
clipPath:
|
||||
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
||||
}}
|
||||
className="relative left-[calc(50%-30rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#93c5fd] to-[#9089fc] opacity-30 sm:left-[calc(50%-36rem)] sm:w-[72.1875rem]"
|
||||
/>
|
||||
</motion.div>
|
||||
<Container>
|
||||
<div className="mx-auto max-w-2xl lg:mx-0">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
||||
transition={{ duration: 0.8, delay: 0.2 }}
|
||||
className="mx-auto max-w-2xl lg:mx-0"
|
||||
>
|
||||
<h2
|
||||
id="faqs-title"
|
||||
className="text-3xl font-medium tracking-tight text-gray-900"
|
||||
className="text-3xl font-medium tracking-tight text-[#2F3178]"
|
||||
>
|
||||
Frequently asked questions
|
||||
</h2>
|
||||
@@ -74,26 +102,34 @@ export function Faqs() {
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
<ul
|
||||
</motion.div>
|
||||
<motion.ul
|
||||
role="list"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
||||
transition={{ duration: 0.5, delay: 0.3, staggerChildren: 0.2 }}
|
||||
className="mx-auto mt-16 grid max-w-2xl grid-cols-1 gap-8 sm:mt-20 lg:max-w-none lg:grid-cols-3"
|
||||
>
|
||||
{faqs.map((column, columnIndex) => (
|
||||
<li key={columnIndex}>
|
||||
<motion.li
|
||||
key={columnIndex}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
||||
transition={{ duration: 0.5, delay: 0.4 + columnIndex * 0.2 }}
|
||||
>
|
||||
<ul role="list" className="space-y-10">
|
||||
{column.map((faq, faqIndex) => (
|
||||
<li key={faqIndex}>
|
||||
<h3 className="text-lg/6 font-semibold text-gray-900">
|
||||
<h3 className="text-lg/6 font-semibold text-[#2F3178]">
|
||||
{faq.question}
|
||||
</h3>
|
||||
<p className="mt-4 text-sm text-gray-700">{faq.answer}</p>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</li>
|
||||
</motion.li>
|
||||
))}
|
||||
</ul>
|
||||
</motion.ul>
|
||||
</Container>
|
||||
</section>
|
||||
)
|
||||
|
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { motion } from 'framer-motion'
|
||||
import { useState, useRef } from 'react'
|
||||
import { motion, useInView } from 'framer-motion'
|
||||
import { TypeAnimation } from 'react-type-animation'
|
||||
import { Dialog, DialogPanel } from '@headlessui/react'
|
||||
import { Bars3Icon, XMarkIcon, ChevronDoubleDownIcon } from '@heroicons/react/24/outline'
|
||||
@@ -37,51 +37,73 @@ const features = [
|
||||
];
|
||||
|
||||
export function HomeAbout() {
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
|
||||
const ref = useRef(null);
|
||||
const isInView = useInView(ref, { once: true });
|
||||
|
||||
return (
|
||||
<div id="about" className="relative h-screen">
|
||||
<div id="about" ref={ref} className="relative h-screen">
|
||||
<div className="relative isolate px-6 lg:px-8">
|
||||
<div className="relative -top-10 mx-auto max-w-8xl h-screen flex items-center justify-center">
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 2, delay: 0.5 }}
|
||||
aria-hidden="true"
|
||||
className="absolute top-10 left-[calc(50%-4rem)] -z-10 transform-gpu blur-3xl sm:left-[calc(50%-18rem)] lg:top-[calc(50%-30rem)] lg:left-48 xl:left-[calc(50%-24rem)]"
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
clipPath:
|
||||
'polygon(73.6% 51.7%, 91.7% 11.8%, 100% 46.4%, 97.4% 82.2%, 92.5% 84.9%, 75.7% 64%, 55.3% 47.5%, 46.5% 49.4%, 45% 62.9%, 50.3% 87.2%, 21.3% 64.1%, 0.1% 100%, 5.4% 51.1%, 21.4% 63.9%, 58.9% 0.2%, 73.6% 51.7%)',
|
||||
}}
|
||||
className="aspect-1108/632 w-277 bg-linear-to-r from-[#80caff] to-[#4f46e5] opacity-20"
|
||||
/>
|
||||
</motion.div>
|
||||
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 1, delay: 1 }} className="absolute top-24 left-0 max-w-xl text-left">
|
||||
<div className="relative -top-10 mx-auto max-w-8xl h-screen flex items-center justify-center">
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
||||
transition={{ duration: 2, delay: 0.5 }}
|
||||
aria-hidden="true"
|
||||
className="absolute top-10 left-[calc(50%-4rem)] -z-10 transform-gpu blur-3xl sm:left-[calc(50%-18rem)] lg:top-[calc(50%-30rem)] lg:left-48 xl:left-[calc(50%-24rem)]"
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
clipPath:
|
||||
'polygon(73.6% 51.7%, 91.7% 11.8%, 100% 46.4%, 97.4% 82.2%, 92.5% 84.9%, 75.7% 64%, 55.3% 47.5%, 46.5% 49.4%, 45% 62.9%, 50.3% 87.2%, 21.3% 64.1%, 0.1% 100%, 5.4% 51.1%, 21.4% 63.9%, 58.9% 0.2%, 73.6% 51.7%)',
|
||||
}}
|
||||
className="aspect-1108/632 w-277 bg-linear-to-r from-[#80caff] to-[#4f46e5] opacity-20"
|
||||
/>
|
||||
</motion.div>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
||||
transition={{ duration: 1, delay: 0.2 }}
|
||||
className="absolute top-24 left-0 max-w-xl text-left"
|
||||
>
|
||||
<H2>
|
||||
Enterprise AI Agents
|
||||
That Never Sleep.
|
||||
</H2>
|
||||
</motion.div>
|
||||
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 1, delay: 1.5 }} className="absolute top-54 left-0 max-w-xl text-left">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
||||
transition={{ duration: 1, delay: 0.4 }}
|
||||
className="absolute top-54 left-0 max-w-xl text-left"
|
||||
>
|
||||
<P color="custom">
|
||||
With Mycelium Cloud, you can deploy purpose-built AI agents to automate any workflow. Keep complete control of your data while scaling from simple tasks to complex decision-making.
|
||||
With Mycelium Cloud, you can deploy purpose-built AI agents to automate any workflow. Keep complete control of your data while scaling from simple tasks to complex decision-making.
|
||||
</P>
|
||||
</motion.div>
|
||||
|
||||
<Candy />
|
||||
|
||||
<div className="absolute bottom-24 right-0 h-96 w-full md:w-2/3 overflow-hidden">
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
||||
transition={{ duration: 1, delay: 0.6 }}
|
||||
>
|
||||
<Candy />
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
||||
transition={{ duration: 1, delay: 0.8 }}
|
||||
className="absolute bottom-24 right-0 h-96 w-full md:w-2/3 overflow-hidden"
|
||||
>
|
||||
<div className="animate-marquee-vertical space-y-8 text-right">
|
||||
{[...features, ...features].map((feature, index) => (
|
||||
<div key={index} className="flex items-center justify-end gap-x-4" aria-hidden={index >= features.length}>
|
||||
<Image src={diamondSvg} alt="" className="h-6 w-6" />
|
||||
<H3 as="p">{feature}</H3>
|
||||
<H3>{feature}</H3>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -19,7 +19,12 @@ export function HomeHero() {
|
||||
|
||||
return (
|
||||
<div className="relative h-screen -top-15">
|
||||
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-[700px] h-[700px] -z-10 rounded-full overflow-hidden">
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 2 }}
|
||||
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-[700px] h-[700px] -z-10 rounded-full overflow-hidden"
|
||||
>
|
||||
<video
|
||||
autoPlay
|
||||
loop
|
||||
@@ -29,7 +34,7 @@ export function HomeHero() {
|
||||
>
|
||||
<source src="/videos/mycelium.mp4" type="video/mp4" />
|
||||
</video>
|
||||
</div>
|
||||
</motion.div>
|
||||
<div className="relative isolate px-6 lg:px-8">
|
||||
<div
|
||||
aria-hidden="true"
|
||||
@@ -40,7 +45,7 @@ export function HomeHero() {
|
||||
clipPath:
|
||||
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
||||
}}
|
||||
className="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#93c5fd] to-[#9089fc] opacity-25 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
|
||||
className="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#a4caf6] to-[#aaa4fa] opacity-15 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
@@ -52,7 +57,7 @@ export function HomeHero() {
|
||||
clipPath:
|
||||
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
||||
}}
|
||||
className="relative bottom-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#93c5fd] to-[#9089fc] opacity-20 sm:left-[calc(50%+30rem)] sm:w-[72.1875rem]"
|
||||
className="relative bottom-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#93c5fd] to-[#9089fc] opacity-15 sm:left-[calc(50%+30rem)] sm:w-[72.1875rem]"
|
||||
/>
|
||||
</div>
|
||||
<div className="relative -top-15 mx-auto max-w-8xl h-screen flex items-center justify-center">
|
||||
|
@@ -13,8 +13,18 @@ export function StackSectionPreview() {
|
||||
return (
|
||||
<section ref={ref} className="w-full h-screen bg-transparent lg:px-0 pt-24 pb-12 px-6 relative">
|
||||
{/* Gradient Blob Component */}
|
||||
<div className="absolute w-[400px] h-[200px] bg-gradient-to-br from-[#505050] to-[#7e7e7e] opacity-40 rounded-full blur-[150px] bottom-[200px] left-[-150px] z-0" />
|
||||
<div className="absolute w-[200px] h-[100px] bg-gradient-to-br from-[#505050] to-[#7e7e7e] opacity-50 rounded-full blur-[150px] top-[200px] right-[-150px] z-0" />
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={isInView ? { opacity: 0.4 } : { opacity: 0 }}
|
||||
transition={{ duration: 1, delay: 0.1 }}
|
||||
className="absolute w-[400px] h-[200px] bg-gradient-to-br from-[#505050] to-[#7e7e7e] rounded-full blur-[150px] bottom-[200px] left-[-150px] z-0"
|
||||
/>
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={isInView ? { opacity: 0.5 } : { opacity: 0 }}
|
||||
transition={{ duration: 1, delay: 0.15 }}
|
||||
className="absolute w-[200px] h-[100px] bg-gradient-to-br from-[#505050] to-[#7e7e7e] rounded-full blur-[150px] top-[200px] right-[-150px] z-0"
|
||||
/>
|
||||
<div className="mx-auto max-w-7xl">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 lg:gap-16 items-center lg:items-start">
|
||||
{/* Left Column - Text (1/3 width) */}
|
||||
|
@@ -1,16 +1,10 @@
|
||||
'use client'
|
||||
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import clsx from 'clsx'
|
||||
import { useInView } from 'framer-motion'
|
||||
import { Container } from '@/components/Container'
|
||||
import React, { useRef } from 'react'
|
||||
import { motion, useInView } from 'framer-motion'
|
||||
import { H2, P, CT, CP } from '@/components/Texts'
|
||||
import { TbCircleNumber1Filled, TbCircleNumber2Filled, TbCircleNumber3Filled } from 'react-icons/tb'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const features = [
|
||||
{
|
||||
name: 'Choose Your Intelligence',
|
||||
@@ -32,29 +26,45 @@ const features = [
|
||||
]
|
||||
|
||||
export function Steps() {
|
||||
const ref = useRef(null);
|
||||
const isInView = useInView(ref, { once: true });
|
||||
|
||||
return (
|
||||
<section id="benefits" className="bg-white pt-0 pb-24 dark:bg-gray-900">
|
||||
<section id="benefits" ref={ref} className="bg-white pt-0 pb-24 dark:bg-gray-900">
|
||||
<div className="mx-auto max-w-7xl px-6 lg:px-0">
|
||||
<div className="mx-auto max-w-5xl lg:mx-0">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
||||
transition={{ duration: 0.8, delay: 0.1 }}
|
||||
className="mx-auto max-w-5xl lg:mx-0"
|
||||
>
|
||||
<H2 className="text-3xl font-medium tracking-tight">
|
||||
Deploy Scalable LLMs and AI Agents in Seconds
|
||||
</H2>
|
||||
<P className="mt-6 text-lg" color="custom">
|
||||
Launch and scale intelligence on your own terms. Mycelium Cloud makes it simple to deploy models, integrate knowledge, and run everything on a network you control.
|
||||
</P>
|
||||
</div>
|
||||
<ul className="mx-auto mt-16 grid max-w-2xl grid-cols-1 gap-x-8 gap-y-16 text-base/7 sm:grid-cols-2 lg:mx-0 lg:max-w-none lg:grid-cols-3">
|
||||
{features.map((feature) => (
|
||||
<li
|
||||
</motion.div>
|
||||
<motion.ul
|
||||
initial={{ opacity: 0 }}
|
||||
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
||||
transition={{ duration: 0.5, delay: 0.2, staggerChildren: 0.2 }}
|
||||
className="mx-auto mt-16 grid max-w-2xl grid-cols-1 gap-x-8 gap-y-16 text-base/7 sm:grid-cols-2 lg:mx-0 lg:max-w-none lg:grid-cols-3"
|
||||
>
|
||||
{features.map((feature, index) => (
|
||||
<motion.li
|
||||
key={feature.name}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
||||
transition={{ duration: 0.5, delay: 0.3 + index * 0.2 }}
|
||||
className="rounded-2xl border border-gray-200 p-8 dark:border-gray-700"
|
||||
>
|
||||
<feature.icon className="h-8 w-8 mb-4 text-[#2F3178]" />
|
||||
<CT as="span" className="font-semibold">{feature.name}</CT>
|
||||
<CP className="mt-2 text-sm" color="custom">{feature.description}</CP>
|
||||
</li>
|
||||
</motion.li>
|
||||
))}
|
||||
</ul>
|
||||
</motion.ul>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
|
@@ -1,48 +1,60 @@
|
||||
import React from 'react';
|
||||
import { cn } from '@/lib/utils';
|
||||
'use client'
|
||||
|
||||
import React from 'react'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const colorVariants = {
|
||||
primary: 'text-[#2F3178]',
|
||||
secondary: 'text-gray-600',
|
||||
custom: 'text-[#1c1c49]',
|
||||
};
|
||||
} as const
|
||||
|
||||
type TextProps<E extends React.ElementType> = {
|
||||
as?: E;
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
color?: keyof typeof colorVariants;
|
||||
} & Omit<React.ComponentPropsWithoutRef<E>, 'as' | 'children' | 'className' | 'color'>;
|
||||
type TextOwnProps = {
|
||||
color?: keyof typeof colorVariants
|
||||
className?: string
|
||||
}
|
||||
|
||||
const createTextComponent = <E extends React.ElementType>(
|
||||
defaultElement: E,
|
||||
// Polymorphic helpers (no forwardRef needed)
|
||||
type PolymorphicProps<E extends React.ElementType, P> =
|
||||
P & { as?: E } &
|
||||
Omit<React.ComponentPropsWithoutRef<E>, keyof P | 'as'>
|
||||
|
||||
const createTextComponent = <DefaultElement extends React.ElementType>(
|
||||
defaultElement: DefaultElement,
|
||||
defaultClassName: string
|
||||
) => {
|
||||
const Component = React.forwardRef<React.ElementRef<E>, TextProps<E>>(
|
||||
({ as, color = 'primary', className, children, ...props }, ref) => {
|
||||
const Tag = as || defaultElement;
|
||||
return (
|
||||
<Tag
|
||||
ref={ref}
|
||||
className={cn(defaultClassName, colorVariants[color], className)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Tag>
|
||||
);
|
||||
}
|
||||
);
|
||||
type Props<E extends React.ElementType = DefaultElement> =
|
||||
PolymorphicProps<E, TextOwnProps>
|
||||
|
||||
Component.displayName = `Text(${defaultElement})`;
|
||||
return Component;
|
||||
};
|
||||
function Text<E extends React.ElementType = DefaultElement>({
|
||||
as,
|
||||
color = 'primary',
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: Props<E>) {
|
||||
const Tag = (as || defaultElement) as React.ElementType
|
||||
return (
|
||||
<Tag
|
||||
className={cn(defaultClassName, colorVariants[color], className)}
|
||||
{...(props as object)}
|
||||
>
|
||||
{children}
|
||||
</Tag>
|
||||
)
|
||||
}
|
||||
|
||||
export const H1 = createTextComponent('h1', 'text-5xl font-medium tracking-tight text-balance lg:text-8xl');
|
||||
export const PL = createTextComponent('p', 'text-2xl font-medium text-pretty leading-[1.2] lg:text-3xl');
|
||||
export const H2 = createTextComponent('h2', 'text-4xl font-medium text-pretty lg:text-5xl');
|
||||
export const P = createTextComponent('p', 'text-xl font-normal text-pretty lg:text-2xl');
|
||||
export const H3 = createTextComponent('h3', 'text-3xl lg:text-4xl font-medium');
|
||||
export const H4 = createTextComponent('h4', 'text-2xl lg:text-3xl font-semibold leading-tight');
|
||||
export const CT = createTextComponent('span', 'text-base lg:text-xl font-semibold text-center');
|
||||
export const CP = createTextComponent('p', 'text-sm lg:text-base leading-relaxed font-light');
|
||||
export const NL = createTextComponent('span', 'text-lg font-semibold leading-6');
|
||||
;(Text as any).displayName = `Text(${typeof defaultElement === 'string' ? defaultElement : 'Component'})`
|
||||
return Text
|
||||
}
|
||||
|
||||
// Exports
|
||||
export const H1 = createTextComponent('h1', 'text-5xl font-medium tracking-tight text-balance lg:text-8xl')
|
||||
export const PL = createTextComponent('p', 'text-2xl font-medium text-pretty leading-[1.2] lg:text-3xl')
|
||||
export const H2 = createTextComponent('h2', 'text-4xl font-medium text-pretty lg:text-5xl')
|
||||
export const P = createTextComponent('p', 'text-xl font-normal text-pretty lg:text-2xl')
|
||||
export const H3 = createTextComponent('h3', 'text-3xl lg:text-4xl font-medium')
|
||||
export const H4 = createTextComponent('h4', 'text-2xl lg:text-3xl font-semibold leading-tight')
|
||||
export const CT = createTextComponent('span', 'text-base lg:text-xl font-semibold text-center')
|
||||
export const CP = createTextComponent('p', 'text-sm lg:text-base leading-relaxed font-light')
|
||||
export const NL = createTextComponent('span', 'text-lg font-semibold leading-6')
|
||||
|
@@ -2,7 +2,6 @@
|
||||
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import clsx from 'clsx'
|
||||
import { useInView } from 'framer-motion'
|
||||
import {
|
||||
ArchiveBoxIcon,
|
||||
CodeBracketIcon,
|
||||
@@ -16,6 +15,7 @@ import {
|
||||
|
||||
import { Container } from '@/components/Container'
|
||||
import { H2, P, CT, CP } from '@/components/Texts'
|
||||
import { motion, useInView } from 'framer-motion'
|
||||
|
||||
interface Review {
|
||||
title: string
|
||||
@@ -94,7 +94,7 @@ function Review({
|
||||
>
|
||||
<blockquote className="text-gray-900">
|
||||
{React.createElement(getReviewIcon(title), { className: "h-6 w-6 text-[#2F3178] mb-2" })}
|
||||
<CT as="h3" color="primary" className="mt-4 text-lg/6 font-semibold">
|
||||
<CT color="primary" className="mt-4 text-lg/6 font-semibold">
|
||||
{title}
|
||||
</CT>
|
||||
<CP color="custom" className="mt-3 text-sm">{body}</CP>
|
||||
@@ -213,14 +213,23 @@ function ReviewGrid() {
|
||||
}
|
||||
|
||||
export function UseCases() {
|
||||
const ref = useRef(null);
|
||||
const isInView = useInView(ref, { once: true });
|
||||
|
||||
return (
|
||||
<section
|
||||
id="usecases"
|
||||
ref={ref}
|
||||
aria-labelledby="usecases-title"
|
||||
className="py-12"
|
||||
>
|
||||
<Container className=''>
|
||||
<div className="mx-auto max-w-2xl lg:max-w-5xl">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
||||
transition={{ duration: 0.8, delay: 0.1 }}
|
||||
className="mx-auto max-w-2xl lg:max-w-5xl"
|
||||
>
|
||||
<H2
|
||||
id="usecases-title"
|
||||
color="primary"
|
||||
@@ -231,7 +240,22 @@ export function UseCases() {
|
||||
<P className="mt-6 text-center" color="custom">
|
||||
Mycelium Cloud is evolving to bring even more powerful decentralized features, designed to enhance your experience and expand possibilities. Be the first to explore what's coming next by staying connected with our latest updates.
|
||||
</P>
|
||||
</div>
|
||||
</motion.div>
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
||||
transition={{ duration: 1, delay: 0.2 }}
|
||||
aria-hidden="true"
|
||||
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
clipPath:
|
||||
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
||||
}}
|
||||
className="relative left-[calc(50%-30rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#93c5fd] to-[#9089fc] opacity-30 sm:left-[calc(50%-36rem)] sm:w-[72.1875rem]"
|
||||
/>
|
||||
</motion.div>
|
||||
<ReviewGrid />
|
||||
</Container>
|
||||
</section>
|
||||
|
0
src/components/logos/NousResearch.tsx
Normal file
0
src/components/logos/NousResearch.tsx
Normal file
Reference in New Issue
Block a user