diff --git a/components/icons/credit-bold.tsx b/components/icons/credit-bold.tsx deleted file mode 100644 index 23476ea0..00000000 --- a/components/icons/credit-bold.tsx +++ /dev/null @@ -1,44 +0,0 @@ -// Generated by scripts/generate-icons.mjs from svg/bold/credit.svg. Do not edit. -import type { SVGProps } from 'react'; - -export function CreditBoldIcon(props: SVGProps) { - return ( - - - - - - - - - - - - - - ); -} diff --git a/components/marketing/article-card.tsx b/components/marketing/article-card.tsx deleted file mode 100644 index e43c611f..00000000 --- a/components/marketing/article-card.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { Placeholder } from './placeholder'; - -/** Blog article card. Plain scaffold pending design. */ -export function ArticleCard() { - return ; -} diff --git a/components/marketing/brand-kit-cta.tsx b/components/marketing/brand-kit-cta.tsx deleted file mode 100644 index cf3dfc0f..00000000 --- a/components/marketing/brand-kit-cta.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { Download } from 'lucide-react'; -import Image from 'next/image'; - -import { cn } from '@/lib/utils'; - -import { MarketingButton } from './marketing-button'; -import { Reveal } from './reveal'; -import { Section } from './section'; - -/** Brand kit call to action: logo + heading on the left, download button right. */ -export function BrandKitCta({ className }: { className?: string }) { - return ( -
- -
-
- -
- -
-

- Brand Kit -

-

- Get the latest
- Boundless Brand kit -

-
-
- - - - Download All - - - -
-
- ); -} diff --git a/components/marketing/cta-pill.tsx b/components/marketing/cta-pill.tsx deleted file mode 100644 index e2bbc452..00000000 --- a/components/marketing/cta-pill.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import type { LucideIcon } from 'lucide-react'; - -import { cn } from '@/lib/utils'; - -type CtaPillProps = { - label: string; - icon: LucideIcon; - iconRight?: boolean; - active?: boolean; - className?: string; -}; - -const SHADOW_ACTIVE = - 'shadow-[0px_5px_5px_0px_rgba(0,0,0,0.05),0px_15px_15px_0px_rgba(0,0,0,0.05),0px_30px_30px_0px_rgba(0,0,0,0.1),inset_0px_0px_100px_0px_rgba(212,255,240,0.04)]'; -const SHADOW_IDLE = - 'shadow-[0px_5px_10px_0px_rgba(0,0,0,0.05),0px_15px_30px_0px_rgba(0,0,0,0.05),0px_30px_60px_0px_rgba(0,0,0,0.1),inset_0px_0px_100px_0px_rgba(212,255,240,0.04)]'; - -/** Pill-shaped product CTA. Enlarges and turns solid green when active. */ -export function CtaPill({ - label, - icon: Icon, - iconRight, - active, - className, -}: CtaPillProps) { - const icon = ( - - ); - return ( -
- {!iconRight && icon} - - {label} - - {iconRight && icon} -
- ); -} diff --git a/components/marketing/cta-ticker.tsx b/components/marketing/cta-ticker.tsx deleted file mode 100644 index b6755b62..00000000 --- a/components/marketing/cta-ticker.tsx +++ /dev/null @@ -1,81 +0,0 @@ -'use client'; - -import type { LucideIcon } from 'lucide-react'; -import { ArrowUpRight, Pencil, Plus, Rocket, User } from 'lucide-react'; -import { useEffect, useState } from 'react'; - -import { cn } from '@/lib/utils'; - -import { CtaPill } from './cta-pill'; - -type Cta = { label: string; icon: LucideIcon; iconRight?: boolean }; - -const CTAS: Cta[] = [ - { label: 'Post', icon: Pencil }, - { label: 'Launch', icon: Rocket }, - { label: 'Create', icon: Plus }, - { label: 'Enter', icon: ArrowUpRight, iconRight: true }, - { label: 'Join', icon: User }, -]; - -const ROW = 47; // pitch: 39px pill + 8px gap -const TRACK = [...CTAS, ...CTAS, ...CTAS]; // copies for a seamless loop -const START = CTAS.length + 2; // centers "Create" first, matching the design -const RESET_AT = CTAS.length * 2; // snap back one cycle once we reach the copy -const STEP_MS = 1800; -const SLIDE_MS = 600; - -/** Vertical CTA picker that scrolls action pills through a highlighted center slot. */ -export function CtaTicker({ className }: { className?: string }) { - const [step, setStep] = useState(START); - const [sliding, setSliding] = useState(true); - - useEffect(() => { - if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return; - const id = setInterval(() => setStep(s => s + 1), STEP_MS); - return () => clearInterval(id); - }, []); - - // After sliding into the duplicate copy, jump back a cycle without animating. - useEffect(() => { - if (step < RESET_AT) return; - const id = setTimeout(() => { - setSliding(false); - setStep(s => s - CTAS.length); - }, SLIDE_MS); - return () => clearTimeout(id); - }, [step]); - - useEffect(() => { - if (sliding) return; - const id = requestAnimationFrame(() => setSliding(true)); - return () => cancelAnimationFrame(id); - }, [sliding]); - - return ( -
-
- {TRACK.map((cta, index) => ( -
- -
- ))} -
-
- ); -} diff --git a/components/marketing/escrow-flow.tsx b/components/marketing/escrow-flow.tsx deleted file mode 100644 index 6ddf7cea..00000000 --- a/components/marketing/escrow-flow.tsx +++ /dev/null @@ -1,134 +0,0 @@ -'use client'; - -import { Check, LoaderCircle, Lock } from 'lucide-react'; -import { useReducedMotion } from 'motion/react'; -import { useEffect, useState } from 'react'; - -import { cn } from '@/lib/utils'; - -import { Glow } from './glow'; - -type Step = { title: string; description: string }; - -const STEPS: Step[] = [ - { - title: 'Match', - description: 'Connect with the right contributors or participants.', - }, - { - title: 'Secure', - description: 'Lock funding into escrow before work starts.', - }, -]; - -// Four phases walk the escrow rail through its lifecycle, then loop: -// 0 both pending, 1 Match confirmed, 2 Secure in progress, 3 Secure locked. -const PHASES = 4; -const STEP_MS = 1400; - -/** Pending circle: a dark disc with a faint ring, matching the figma default. */ -function PendingDot() { - return ( - - - - ); -} - -/** Filled circle holding a status icon (check, spinner or lock). */ -function StatusDot({ children }: { children: React.ReactNode }) { - return ( - - {children} - - ); -} - -/** - * "Track Progress" illustration: a glassy escrow card whose Match/Secure rail - * animates through its lifecycle (pending dot, green check, securing spinner, - * locked) with the connector filling green, looping. Honors reduced motion by - * resting on the final secured state. - */ -export function EscrowFlow({ className }: { className?: string }) { - const reduceMotion = useReducedMotion(); - const [step, setStep] = useState(0); - - useEffect(() => { - if (reduceMotion) return; - const id = setInterval(() => setStep(s => (s + 1) % PHASES), STEP_MS); - return () => clearInterval(id); - }, [reduceMotion]); - - // Reduced motion rests on the final secured state instead of looping. - const phase = reduceMotion ? PHASES - 1 : step; - const matchDone = phase >= 1; - const lineFilled = phase >= 1; - - return ( -
- {/* Border glow concentrated at the centre of the left edge (only the - border line glows here), fading to the figma's faint white border. */} -
-
- {/* Green patch near the centre of the right edge (inside, not on the - border). */} - - -
- {/* Indicator rail: Match dot, connector, Secure dot. */} -
- {matchDone ? ( - - - - ) : ( - - )} - - - - - - {phase >= 3 ? ( - - - - ) : phase === 2 ? ( - - - - ) : ( - - )} -
- -
- {STEPS.map(step => ( -
-

- {step.title} -

-

{step.description}

-
- ))} -
-
-
-
- - {/* Top glow: overlays the card from its top edge and bursts out above, - centred and kept transparent so it reads as a soft burst. */} - -
- ); -} diff --git a/components/marketing/explore-path.tsx b/components/marketing/explore-path.tsx deleted file mode 100644 index 85d8da0e..00000000 --- a/components/marketing/explore-path.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { Crown } from 'lucide-react'; - -import { cn } from '@/lib/utils'; - -import { PillarCard } from './pillar-card'; - -/** - * "Explore path" cluster: a crown badge framed by a dashed outline above two - * stacked pillar cards offset so each shows a different product pillar. - */ -export function ExplorePath({ className }: { className?: string }) { - return ( -
- - - - Explore path - -
- - -
-
- ); -} diff --git a/components/marketing/faq-accordion.tsx b/components/marketing/faq-accordion.tsx deleted file mode 100644 index 88685bb8..00000000 --- a/components/marketing/faq-accordion.tsx +++ /dev/null @@ -1,77 +0,0 @@ -'use client'; - -import { Minus, Plus } from 'lucide-react'; -import { useState } from 'react'; - -import { cn } from '@/lib/utils'; - -import type { FaqItem } from './faq-data'; - -interface FaqAccordionProps { - items: FaqItem[]; - /** Indexes open on first render (others collapse). Defaults to none. */ - defaultOpen?: number[]; - className?: string; -} - -/** Expandable FAQ list: each row toggles its answer; multiple can stay open. */ -export function FaqAccordion({ - items, - defaultOpen = [], - className, -}: FaqAccordionProps) { - const [open, setOpen] = useState(defaultOpen); - - const toggle = (index: number) => - setOpen(current => - current.includes(index) - ? current.filter(i => i !== index) - : [...current, index] - ); - - return ( -
- {items.map((item, index) => { - const isOpen = open.includes(index); - - return ( -
- -
- ); - })} -
- ); -} diff --git a/components/marketing/faq-data.ts b/components/marketing/faq-data.ts deleted file mode 100644 index 42262999..00000000 --- a/components/marketing/faq-data.ts +++ /dev/null @@ -1,85 +0,0 @@ -export interface FaqItem { - question: string; - answer: string; -} - -/** When the FAQ content was last reviewed; shown under the page title. */ -export const FAQ_LAST_UPDATED = 'Last Updated June 2026'; - -export const FAQ_ITEMS: FaqItem[] = [ - { - question: 'What types of opportunities are available?', - answer: - 'Hackathons, grants, bounties, crowdfunding campaigns, and community initiatives.', - }, - { - question: 'Can I launch my own program?', - answer: - 'Yes. Organizations and communities can create funding programs, challenges, and campaigns.', - }, - { - question: 'Do I need cryptocurrency to use Boundless?', - answer: - 'No. Boundless is designed to help people discover and participate in opportunities regardless of their technical background.', - }, - { - question: 'Who can use Boundless?', - answer: - 'Developers, designers, researchers, founders, creators, students, nonprofits, and communities.', - }, - { - question: 'What is Boundless?', - answer: - 'Boundless is a platform where people can complete work, join hackathons, raise funds, and apply for grants—all from one account.', - }, - { - question: 'How do I get paid?', - answer: - 'Payments are released directly to your Boundless wallet once work or milestones are approved.', - }, - { - question: 'What kind of work can I find on Boundless?', - answer: - 'You can find opportunities in development, design, writing, research, marketing, community management, and more.', - }, - { - question: 'How does escrow work?', - answer: - 'Funds are locked before work begins and released only when agreed requirements are completed.', - }, - { - question: 'Can teams use Boundless?', - answer: - 'Yes. Teams and organizations can post opportunities, run hackathons, launch campaigns, and manage contributors.', - }, - { - question: "What happens if there's a dispute?", - answer: - 'A review process helps resolve disagreements fairly, using submitted work and project requirements as evidence.', - }, - { - question: 'How does reputation work?', - answer: - 'Your activity and completed work contribute to a reputation score that helps showcase your track record.', - }, - { - question: 'Can I use Boundless from any country?', - answer: - 'Boundless is designed for a global audience, though some features may vary depending on local regulations and availability.', - }, - { - question: 'Is there a fee to join?', - answer: - 'Creating an account and exploring the platform is free. Any applicable fees are clearly shown before transactions are made.', - }, - { - question: 'How do I apply for a grant?', - answer: - 'Browse available grant programs, review the requirements, and submit your proposal through the platform.', - }, - { - question: 'What makes Boundless different?', - answer: - 'Boundless combines opportunities, funding, accountability, and reputation into one platform, making it easier to discover, fund, and complete meaningful work.', - }, -]; diff --git a/components/marketing/faq.tsx b/components/marketing/faq.tsx deleted file mode 100644 index 82924189..00000000 --- a/components/marketing/faq.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { ArrowRight } from 'lucide-react'; -import Link from 'next/link'; - -import { FaqAccordion } from './faq-accordion'; -import { FAQ_ITEMS } from './faq-data'; -import { Section } from './section'; - -// The home section previews the first few questions; the rest live on /faq. -const HOME_FAQS = FAQ_ITEMS.slice(0, 4); - -/** Home "Frequently Asked Questions (FAQs)": heading beside a preview accordion. */ -export function Faq() { - return ( -
-
-

- Frequently Asked - - Questions (FAQs) - -

- -
- - - - See More FAQs - - -
-
-
- ); -} diff --git a/components/marketing/four-steps.tsx b/components/marketing/four-steps.tsx deleted file mode 100644 index e2b667a2..00000000 --- a/components/marketing/four-steps.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { Placeholder } from './placeholder'; -import { Section } from './section'; - -/** "How it works" four-step flow. Plain scaffold pending design. */ -export function FourSteps() { - return ( -
- -
- ); -} diff --git a/components/marketing/funding-paths.tsx b/components/marketing/funding-paths.tsx deleted file mode 100644 index c13969af..00000000 --- a/components/marketing/funding-paths.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { Play } from 'lucide-react'; -import { type ReactNode } from 'react'; - -import { CtaTicker } from './cta-ticker'; -import { EscrowFlow } from './escrow-flow'; -import { ExplorePath } from './explore-path'; -import { Glow } from './glow'; -import { PrizePool } from './prize-pool'; -import { Section } from './section'; - -type Step = { - title: string; - description: string; - illustration: ReactNode; -}; - -const STEPS: Step[] = [ - { - title: 'Discover Opportunities', - description: - 'Find grants, hackathons, bounties and campaigns aligned with your goals.', - illustration: , - }, - { - title: 'Apply or Participate', - description: 'Submit proposals, join teams, or contribute your skills.', - illustration: ( -
- {/* Tight green glow around the highlighted (centre) action. */} - - {/* Arrows pointing at the centre slot. */} - - - -
- ), - }, - { - title: 'Earn Funding or Rewards', - description: - 'Receive support, prizes or payments for successful contributions.', - illustration: , - }, - { - title: 'Track Progress', - description: - 'Stay informed with transparent updates and milestone tracking.', - illustration: , - }, -]; - -/** "Work flows through Boundless in 4 steps": four animated workflow columns. */ -export function FundingPaths() { - return ( -
-

- Work flows through{' '} - Boundless in 4 steps -

- -
- {STEPS.map(step => ( -
-
-

- {step.title} -

-

- {step.description} -

-
- -
- {step.illustration} -
-
- ))} -
-
- ); -} diff --git a/components/marketing/funding-programs.tsx b/components/marketing/funding-programs.tsx deleted file mode 100644 index 5c0a588b..00000000 --- a/components/marketing/funding-programs.tsx +++ /dev/null @@ -1,219 +0,0 @@ -'use client'; - -import { ArrowRight, ArrowUpRight } from 'lucide-react'; -import { useMotionValueEvent, useScroll } from 'motion/react'; -import Link from 'next/link'; -import { Fragment, useRef, useState } from 'react'; - -import { cn } from '@/lib/utils'; - -import { Section } from './section'; - -type Program = { name: string; description: string }; - -const PROGRAMS: Program[] = [ - { - name: 'Bounties', - description: 'Complete tasks and earn rewards for your contributions.', - }, - { - name: 'Hackathons', - description: 'Compete, collaborate, and bring new ideas to life.', - }, - { - name: 'Crowdfunding', - description: - 'Raise support directly from communities that believe in your vision.', - }, - { - name: 'Grants', - description: 'Secure funding for impactful projects and initiatives.', - }, -]; - -const GRADIENT = - 'bg-[linear-gradient(180deg,rgba(13,17,17,0)_48.68%,rgba(46,237,170,0.08)_100%)]'; - -/** Blank placeholder for a program's dashboard screenshot. */ -function DashboardCard({ className }: { className?: string }) { - return ( -
- ); -} - -/** Title, description and arrow shown beneath a dashboard card. */ -function Caption({ program }: { program: Program }) { - return ( -
-
-

- {program.name} -

-

- {program.description} -

-
- -
- ); -} - -/** Heading, copy and the "Get Started" link shared by the desktop panel. */ -function Intro() { - return ( -
-

- Every Funding Path. - One Platform. -

-

- Boundless unifies multiple ways to launch, support and fund projects in - a single accountable system. -

- - Get Started - - -
- ); -} - -/** - * Desktop "Every Funding Path. One Platform.": the section pins while the user - * scrolls, advancing through each program (Bounties, Hackathons, Crowdfunding, - * Grants) before the page continues. The selector is also clickable, scrolling - * to that program's segment. - */ -function DesktopPrograms() { - const ref = useRef(null); - const [active, setActive] = useState(0); - - const { scrollYProgress } = useScroll({ - target: ref, - offset: ['start start', 'end end'], - }); - - useMotionValueEvent(scrollYProgress, 'change', value => { - const index = Math.min( - PROGRAMS.length - 1, - Math.max(0, Math.floor(value * PROGRAMS.length)) - ); - setActive(index); - }); - - // Scroll the window so the clicked program sits in the middle of its segment. - function handleSelect(index: number) { - const el = ref.current; - if (!el) return; - const top = el.getBoundingClientRect().top + window.scrollY; - const distance = el.offsetHeight - window.innerHeight; - const target = top + ((index + 0.5) / PROGRAMS.length) * distance; - const reduce = window.matchMedia( - '(prefers-reduced-motion: reduce)' - ).matches; - window.scrollTo({ top: target, behavior: reduce ? 'auto' : 'smooth' }); - } - - return ( - - ); -} - -/** Mobile "Every Funding Path. One Platform.": every program stacked. */ -function MobilePrograms() { - return ( -
- - -
- {PROGRAMS.map((program, index) => ( - -
- - -
- {index < PROGRAMS.length - 1 ? ( - - ) : null} -
- ))} -
-
- ); -} - -/** - * "Every Funding Path. One Platform.": a program selector beside a - * dashboard-screenshot card. On desktop the section pins and scroll advances - * through each program; on mobile every program stacks vertically. - */ -export function FundingPrograms() { - return ( - <> - - - - ); -} diff --git a/components/marketing/get-started-modal.tsx b/components/marketing/get-started-modal.tsx deleted file mode 100644 index b9ae4d68..00000000 --- a/components/marketing/get-started-modal.tsx +++ /dev/null @@ -1,94 +0,0 @@ -'use client'; - -import { XIcon } from 'lucide-react'; -import Image from 'next/image'; -import type { ReactNode } from 'react'; - -import { Button } from '@/components/ui/button'; -import { - Dialog, - DialogClose, - DialogContent, - DialogDescription, - DialogTitle, - DialogTrigger, -} from '@/components/ui/dialog'; - -interface GetStartedModalProps { - /** Controlled open state. Omit to let the trigger manage it. */ - open?: boolean; - onOpenChange?: (open: boolean) => void; - /** Element that opens the modal. Skip it for fully controlled usage. */ - trigger?: ReactNode; - /** Fired when the primary action is pressed. */ - onGetStarted?: () => void; -} - -/** - * Promotional get-started modal: the Boundless mark, a headline, supporting - * copy and the primary / dismiss actions. Built on the Dialog and Button - * primitives so it inherits the design system focus and overlay behaviour. - */ -export function GetStartedModal({ - open, - onOpenChange, - trigger, - onGetStarted, -}: GetStartedModalProps) { - return ( - - {trigger ? {trigger} : null} - - - - - -
- -
- - Ready to Turn Skills Into Rewards? - - - Access bounties, hackathons, grants, and crowdfunding - opportunities, all in one ecosystem. - -
-
- -
- - - - -
-
-
- ); -} diff --git a/components/marketing/glow.tsx b/components/marketing/glow.tsx deleted file mode 100644 index ec133302..00000000 --- a/components/marketing/glow.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { cn } from '@/lib/utils'; - -/** - * Soft ambient glow: the primary green with a touch of the explore-path badge - * accent (#66c589) mixed in. Size, position, opacity and blur are set by the - * caller (the colour falls off naturally through the blur). - */ -export function Glow({ className }: { className?: string }) { - return ( -
- ); -} diff --git a/components/marketing/intro-section.tsx b/components/marketing/intro-section.tsx deleted file mode 100644 index ca3c35f0..00000000 --- a/components/marketing/intro-section.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { type ReactNode } from 'react'; - -import { cn } from '@/lib/utils'; - -import { Reveal } from './reveal'; -import { Section } from './section'; - -// Mint glow at the top, fading fully to dark so it merges into the section below. -const GLOW = - 'linear-gradient(180deg, rgba(46, 237, 170, 0.08) 0%, rgba(13, 17, 17, 0.00) 100%), #0D1111'; - -interface IntroSectionProps { - eyebrow: ReactNode; - title: ReactNode; - children: ReactNode; - eyebrowClassName?: string; -} - -/** Two-column intro: eyebrow + heading on the left, supporting copy on the right. */ -export function IntroSection({ - eyebrow, - title, - children, - eyebrowClassName, -}: IntroSectionProps) { - return ( -
-
-
- -

- {eyebrow} -

-

- {title} -

-
- - - {children} - -
-
-
- ); -} diff --git a/components/marketing/personas.tsx b/components/marketing/personas.tsx deleted file mode 100644 index 07716efb..00000000 --- a/components/marketing/personas.tsx +++ /dev/null @@ -1,120 +0,0 @@ -'use client'; - -import { useEffect, useState } from 'react'; - -import { cn } from '@/lib/utils'; - -import { Section } from './section'; - -type Persona = { title: string; description: string }; - -const PERSONAS: Persona[] = [ - { - title: 'Designers', - description: - 'Contribute creative work, collaborate with teams and get rewarded.', - }, - { - title: 'Developers', - description: - 'Turn ideas into products and earn through challenges and opportunities.', - }, - { - title: 'Communities', - description: 'Launch programs that engage and support contributors.', - }, - { - title: 'Startups & Founders', - description: - 'Access funding, visibility and opportunities to accelerate growth.', - }, -]; - -const STEP_MS = 3200; - -/** - * "Built for Builders, Creators & Communities": four audience personas as an - * auto-advancing stepper. The active persona's indicator lights up and its - * progress bar fills before moving to the next. - */ -export function Personas() { - const [active, setActive] = useState(0); - - useEffect(() => { - if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return; - const id = setInterval( - () => setActive(current => (current + 1) % PERSONAS.length), - STEP_MS - ); - return () => clearInterval(id); - }, []); - - return ( -
-
-

- Built for{' '} - - Builders, Creators & Communities - -

- -
- {PERSONAS.map((persona, index) => { - const isActive = index === active; - - return ( -
- {/* Oversized faded index, clipped (desktop only). */} -
- - {String(index + 1).padStart(2, '0')} - -
- - {/* Progress: indicator + fill bar. */} -
- - - - - - -
- - {/* Step copy. */} -
-

- {persona.title} -

-

- {persona.description} -

-
-
- ); - })} -
-
-
- ); -} diff --git a/components/marketing/pillar-card.tsx b/components/marketing/pillar-card.tsx deleted file mode 100644 index 6b951389..00000000 --- a/components/marketing/pillar-card.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import type { LucideIcon } from 'lucide-react'; -import { CodeXml, HandCoins, Target, Users } from 'lucide-react'; - -import { cn } from '@/lib/utils'; - -type Pillar = { - icon: LucideIcon; - title: string; - subtitle: string; - cta: string; -}; - -const PILLARS: Pillar[] = [ - { - icon: CodeXml, - title: 'Hackathons', - subtitle: 'Compete & build', - cta: 'Join', - }, - { - icon: HandCoins, - title: 'Grants', - subtitle: 'Secure funding', - cta: 'Apply', - }, - { icon: Target, title: 'Bounties', subtitle: 'Earn rewards', cta: 'Earn' }, - { - icon: Users, - title: 'Crowdfunding', - subtitle: 'Raise support', - cta: 'Fund', - }, -]; - -function PillarRow({ - icon: Icon, - title, - subtitle, - cta, - ariaHidden, -}: Pillar & { ariaHidden?: boolean }) { - return ( -
- -
-
-

{title}

-

- {subtitle} -

-
- - {cta} - -
-
- ); -} - -type PillarCardProps = { - className?: string; - /** Negative CSS time (eg. '-5s') to offset the loop so stacked cards show different pillars. */ - animationDelay?: string; -}; - -/** Glass card that steps through the four Boundless product pillars. */ -export function PillarCard({ className, animationDelay }: PillarCardProps) { - // Duplicate the first pillar so the stepped loop resets seamlessly. - const rows = [...PILLARS, PILLARS[0]]; - return ( -
-
-
- {rows.map((pillar, index) => ( - - ))} -
-
-
- ); -} diff --git a/components/marketing/placeholder.tsx b/components/marketing/placeholder.tsx deleted file mode 100644 index 005002d3..00000000 --- a/components/marketing/placeholder.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { cn } from '@/lib/utils'; - -/** - * Plain scaffold block for marketing sections. The design team replaces these - * with real layouts; until then each section renders a labeled dashed box so - * pages compose and route correctly without committing to a design. - */ -export function Placeholder({ - label, - className, -}: { - label: string; - className?: string; -}) { - return ( -
- - {label} - -
- ); -} diff --git a/components/marketing/prize-pool.tsx b/components/marketing/prize-pool.tsx deleted file mode 100644 index 17f75396..00000000 --- a/components/marketing/prize-pool.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import Image from 'next/image'; - -import { cn } from '@/lib/utils'; - -type PrizeTier = { - place: string; - amount: string; -}; - -const DEFAULT_TIERS: PrizeTier[] = [ - { place: '1st Place', amount: '120,000' }, - { place: '2nd Place', amount: '80,000' }, - { place: '3rd Place', amount: '50,000' }, - { place: '4th Place', amount: '30,000' }, - { place: '5th Place', amount: '20,000' }, -]; - -type PrizePoolProps = { - total?: string; - currency?: string; - label?: string; - tiers?: PrizeTier[]; - className?: string; -}; - -function PrizeRow({ - place, - amount, - currency, -}: PrizeTier & { currency: string }) { - return ( -
- {place} -
- {amount} - {currency} -
- {/* Dot centered on the 2px timeline (34px padding + 1px to its center, - minus half the dot). */} - -
- ); -} - -function TiersBlock({ - tiers, - currency, - ariaHidden, -}: { - tiers: PrizeTier[]; - currency: string; - ariaHidden?: boolean; -}) { - return ( -
- {tiers.map((tier, index) => ( - - ))} -
- ); -} - -/** Total prize pool: a fixed header above an infinitely scrolling tier list. */ -export function PrizePool({ - total = '300,000', - currency = 'USDC', - label = 'Total Prize Pool', - tiers = DEFAULT_TIERS, - className, -}: PrizePoolProps) { - return ( -
- {/* Fixed header */} -
- -
- - {label} - -
- {total} - {currency} -
-
-
- - {/* Only the tiers scroll, in two copies for a seamless loop. */} -
-
- - -
-
-
- ); -} diff --git a/components/marketing/team-section.tsx b/components/marketing/team-section.tsx deleted file mode 100644 index 542a0078..00000000 --- a/components/marketing/team-section.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import Image from 'next/image'; -import { type ReactNode } from 'react'; - -import { Reveal } from './reveal'; -import { Section } from './section'; - -// Mint glow at the top, fading fully to dark so it merges into the section below. -const GLOW = - 'linear-gradient(180deg, rgba(46, 237, 170, 0.08) 0%, rgba(13, 17, 17, 0.00) 100%), #0D1111'; - -interface TeamMember { - name: string; - role: string; - /** Portrait path in `/public`. */ - image: string; - linkedin?: string; -} - -interface TeamSectionProps { - title: ReactNode; - members: TeamMember[]; -} - -/** Team grid: heading above portrait cards with name, role and a LinkedIn link. */ -export function TeamSection({ title, members }: TeamSectionProps) { - return ( -
-
-
- -

{title}

-
- -
    - {members.map((member, i) => ( - -
    -
    - {member.name} -
    -
    - -
    -
    -

    - {member.name} -

    -

    - {member.role} -

    -
    - - {member.linkedin ? ( - - - - ) : null} -
    -
    - ))} -
-
-
-
- ); -} diff --git a/components/marketing/testimonials.tsx b/components/marketing/testimonials.tsx deleted file mode 100644 index ca5328ce..00000000 --- a/components/marketing/testimonials.tsx +++ /dev/null @@ -1,180 +0,0 @@ -import { ArrowUpRight } from 'lucide-react'; -import Image from 'next/image'; - -import { SocialGlyph } from '@/components/layout/brand-icons'; -import { cn } from '@/lib/utils'; - -type Testimonial = { - name: string; - handle: string; - avatar: string; - quote: string; -}; - -// Two rows that scroll in opposite directions. Avatars reuse the team photos. -const ROW_ONE: Testimonial[] = [ - { - name: 'Alex Carter', - handle: '@alexcarterx', - avatar: '/team/team1.svg', - quote: - 'I have used multiple bounty platforms before, but @boundless_fi was the first one that actually enforced delivery and payment through escrow instead of blind trust.', - }, - { - name: 'Daniel Kim', - handle: '@danielbuilds', - avatar: '/team/team2.svg', - quote: - 'Winning a hackathon on @boundless_fi did not feel like the end of the journey. The milestone continuation model helped our team keep building after the event.', - }, - { - name: 'Maya Thompson', - handle: '@mayathompson', - avatar: '/team/team3.svg', - quote: - 'The reputation layer on @boundless_fi makes each milestone meaningful. Your work history actually compounds into something you own.', - }, -]; - -const ROW_TWO: Testimonial[] = [ - { - name: 'James Okoro', - handle: '@jamesbuilds', - avatar: '/team/team4.svg', - quote: - 'What sold me on @boundless_fi was how simple the experience is for the team, while the blockchain infrastructure stays underneath.', - }, - { - name: 'Marcus Reid', - handle: '@marcusreidx', - avatar: '/team/team2.svg', - quote: - 'Most platforms only help you find work. @boundless_fi feels like infrastructure for building long-term reputation in Web3.', - }, - { - name: 'Chloe Bennett', - handle: '@chloebennett', - avatar: '/team/team1.svg', - quote: - 'The milestone tracking UI on @boundless_fi gave our community full visibility into project progress and fund releases.', - }, -]; - -function Card({ name, handle, avatar, quote }: Testimonial) { - return ( -
- {/* Border accent lines (exact Figma specs), over a faint base rim. - Top: a white gradient line across the top edge, fading at both ends. */} - - {/* Bottom: a shorter white gradient line set toward the left. */} - - {/* Green accent on the left edge (Figma: 53px line, gradient fading at - both ends, #4BDD74 at ~0.6 in the middle). */} - -
- {name} -
- {name} - {handle} -
- -
-

{quote}

-
- ); -} - -function Row({ - items, - direction, -}: { - items: Testimonial[]; - direction: 'left' | 'right'; -}) { - // Duplicate the row so the -50% loop lands on an identical copy. - const loop = [...items, ...items]; - return ( -
- {loop.map((item, index) => ( - - ))} -
- ); -} - -/** - * "Trusted by Builders Worldwide": two horizontally scrolling rows of social - * testimonials. Hidden on mobile per the design. - */ -export function Testimonials() { - return ( -
-
-
-
-
-

- Trusted by{' '} - Builders Worldwide -

-

- Hear how communities, founders and contributors are creating - impact through Boundless. -

-
- - {/* Liquid-glass CTA, scaled from a 282px reference to this ~44px - pill. The lit border runs only along the top-left -> bottom-right - diagonal (where light enters and exits): a 135deg gradient ring, - bright at those two corners and transparent at the top-right and - bottom-left, rendered via a masked overlay. A top-left radial - highlight sets the light direction and diagonal inset bevels form - the refractive lens edge. The fill stays dark/translucent over the - 10px backdrop blur, with only a faint inner frost. */} - - - - Follow Boundless - - -
- {/* Marquee breaks out of the centered container to span the full - width; the enclosing section is `overflow-hidden`, so the 100vw - breakout is clipped and the soft edge fade lands at the true edges. */} -
- - -
-
-
-
- ); -} diff --git a/components/marketing/trust-bar.tsx b/components/marketing/trust-bar.tsx deleted file mode 100644 index cd02bf0e..00000000 --- a/components/marketing/trust-bar.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { PartnerLogos } from './partner-logos'; -import { Section } from './section'; - -/** - * Ecosystem trust strip: a label over an auto-scrolling partner-logo marquee. - * The teal-at-top gradient continues the hero's bottom glow so the seam merges. - */ -export function TrustBar() { - return ( -
-

- Trusted By Communities, Ecosystems & Builders -

- -
- ); -} diff --git a/components/marketing/youtube-embed.tsx b/components/marketing/youtube-embed.tsx deleted file mode 100644 index 2ce5a96d..00000000 --- a/components/marketing/youtube-embed.tsx +++ /dev/null @@ -1,44 +0,0 @@ -'use client'; - -import { Play } from 'lucide-react'; -import { useState } from 'react'; - -interface YouTubeEmbedProps { - id: string; - title: string; -} - -/** Lazy YouTube player: shows the poster + play button, loading the iframe on click. */ -export function YouTubeEmbed({ id, title }: YouTubeEmbedProps) { - const [playing, setPlaying] = useState(false); - - if (playing) { - return ( -