feat: update layout, styling, story sections, footer, and add Header and ScrollProgress components
This commit is contained in:
@@ -32,30 +32,52 @@
|
|||||||
:root {
|
:root {
|
||||||
--font-sora: 'Sora', sans-serif;
|
--font-sora: 'Sora', sans-serif;
|
||||||
--font-inter: 'Inter', sans-serif;
|
--font-inter: 'Inter', sans-serif;
|
||||||
|
|
||||||
|
/* Section gutters (ported from the loyaly website).
|
||||||
|
--sec-gutter = left/right side margin; --sec-gap = vertical gap between
|
||||||
|
stacked sections; --hdr-gutter = header side padding. */
|
||||||
|
--sec-gutter: 20px;
|
||||||
|
--sec-gap: 20px;
|
||||||
|
--hdr-gutter: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Custom Scrollbar */
|
/* Phones — full-bleed sections, tighter header padding */
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
:root {
|
||||||
|
--sec-gutter: 12px;
|
||||||
|
--sec-gap: 12px;
|
||||||
|
--hdr-gutter: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom Scrollbar — neobrutalist, on-theme (no track border) */
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 8px;
|
width: 14px;
|
||||||
}
|
}
|
||||||
::-webkit-scrollbar-track {
|
::-webkit-scrollbar-track {
|
||||||
background: #090909;
|
background: #FBF3DD;
|
||||||
}
|
}
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
background: #333333;
|
background: linear-gradient(180deg, #FFC72C 0%, #FF2E88 60%, #8B3DFF 100%);
|
||||||
border-radius: 4px;
|
border: 2px solid #0a0a0a;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-clip: padding-box;
|
||||||
}
|
}
|
||||||
::-webkit-scrollbar-thumb:hover {
|
::-webkit-scrollbar-thumb:hover {
|
||||||
background: #FFC72C;
|
background: linear-gradient(180deg, #FFD95A 0%, #FF2E88 55%, #8B3DFF 100%);
|
||||||
|
background-clip: padding-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Base Body Styles */
|
/* Base Body Styles */
|
||||||
html, body {
|
html, body {
|
||||||
background-color: #090909;
|
background-color: #FBF3DD;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
font-family: var(--font-inter), sans-serif;
|
font-family: var(--font-inter), sans-serif;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
|
color-scheme: light;
|
||||||
|
scrollbar-width: auto;
|
||||||
|
scrollbar-color: #FF2E88 #FBF3DD;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export default function RootLayout({
|
|||||||
className={`${sora.variable} ${inter.variable} h-full antialiased`}
|
className={`${sora.variable} ${inter.variable} h-full antialiased`}
|
||||||
suppressHydrationWarning
|
suppressHydrationWarning
|
||||||
>
|
>
|
||||||
<body className="min-h-full flex flex-col bg-dark text-white selection:bg-primary selection:text-dark">
|
<body className="min-h-full flex flex-col bg-[#FBF3DD] text-white selection:bg-primary selection:text-dark">
|
||||||
<Providers>
|
<Providers>
|
||||||
{children}
|
{children}
|
||||||
</Providers>
|
</Providers>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import SideNav, { NavSection } from "@/components/layout/SideNav";
|
import Header from "@/components/layout/Header";
|
||||||
|
import Footer from "@/components/layout/Footer";
|
||||||
|
import ScrollProgress from "@/components/layout/ScrollProgress";
|
||||||
import {
|
import {
|
||||||
Intro,
|
Intro,
|
||||||
TheWhy,
|
TheWhy,
|
||||||
@@ -21,30 +23,11 @@ import {
|
|||||||
ThePromise,
|
ThePromise,
|
||||||
} from "@/components/story/SectionsB";
|
} from "@/components/story/SectionsB";
|
||||||
|
|
||||||
const sections: NavSection[] = [
|
|
||||||
{ id: "intro", label: "Intro" },
|
|
||||||
{ id: "the-why", label: "The Why" },
|
|
||||||
{ id: "the-problem", label: "The Problem" },
|
|
||||||
{ id: "the-shift", label: "The Shift" },
|
|
||||||
{ id: "lyts", label: "Meet LYTs" },
|
|
||||||
{ id: "one-day", label: "One Day" },
|
|
||||||
{ id: "feelings", label: "Feelings" },
|
|
||||||
{ id: "difference", label: "Difference" },
|
|
||||||
{ id: "the-loop", label: "The Loop" },
|
|
||||||
{ id: "for-you", label: "For You" },
|
|
||||||
{ id: "for-business", label: "For Business" },
|
|
||||||
{ id: "why-now", label: "Why Now" },
|
|
||||||
{ id: "how-it-works", label: "How It Works" },
|
|
||||||
{ id: "old-vs-new", label: "Old vs New" },
|
|
||||||
{ id: "the-vision", label: "The Vision" },
|
|
||||||
{ id: "our-belief", label: "Our Belief" },
|
|
||||||
{ id: "the-promise", label: "The Promise" },
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
<main className="relative w-full">
|
<main className="relative w-full">
|
||||||
<SideNav sections={sections} />
|
<ScrollProgress />
|
||||||
|
<Header />
|
||||||
<Intro />
|
<Intro />
|
||||||
<TheWhy />
|
<TheWhy />
|
||||||
<TheProblem />
|
<TheProblem />
|
||||||
@@ -62,6 +45,7 @@ export default function Home() {
|
|||||||
<TheVision />
|
<TheVision />
|
||||||
<OurBelief />
|
<OurBelief />
|
||||||
<ThePromise />
|
<ThePromise />
|
||||||
|
<Footer />
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export default function Providers({ children }: { children: React.ReactNode }) {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider attribute="class" defaultTheme="dark" enableSystem={false}>
|
<ThemeProvider attribute="class" defaultTheme="dark" enableSystem={false} enableColorScheme={false}>
|
||||||
<UserProvider>
|
<UserProvider>
|
||||||
{children}
|
{children}
|
||||||
</UserProvider>
|
</UserProvider>
|
||||||
|
|||||||
@@ -1,152 +1,246 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import { useState } from "react";
|
import { useState, useEffect } from 'react';
|
||||||
import { Send, Instagram, Twitter, MessageSquare, Heart } from "lucide-react";
|
import Link from 'next/link';
|
||||||
import Link from "next/link";
|
import Image from 'next/image';
|
||||||
|
|
||||||
|
const INK = '#0a0a0a';
|
||||||
|
|
||||||
|
const NAV = [
|
||||||
|
{
|
||||||
|
title: 'Earn',
|
||||||
|
color: '#C8FF37', // lime
|
||||||
|
links: [
|
||||||
|
{ label: 'Walk to Earn', href: '#for-you' },
|
||||||
|
{ label: 'Play & Win', href: '#for-you' },
|
||||||
|
{ label: 'Refer Friends', href: '#for-you' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Platform',
|
||||||
|
color: '#FF2E88', // pink
|
||||||
|
links: [
|
||||||
|
{ label: 'For You', href: '#for-you' },
|
||||||
|
{ label: 'For Business', href: '#for-business' },
|
||||||
|
{ label: 'How It Works', href: '#how-it-works' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Company',
|
||||||
|
color: '#8B3DFF', // purple
|
||||||
|
links: [
|
||||||
|
{ label: 'The Vision', href: '#the-vision' },
|
||||||
|
{ label: 'The Why', href: '#the-why' },
|
||||||
|
{ label: 'Contact Us', href: '#for-business' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const SOCIALS = [
|
||||||
|
{
|
||||||
|
label: 'Instagram', href: 'https://instagram.com/lytsup', bg: '#FF2E88',
|
||||||
|
icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"/></svg>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'X / Twitter', href: 'https://twitter.com/lytsup', bg: '#8B3DFF',
|
||||||
|
icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M13.98 10.62 20.54 3h-1.55l-5.7 6.62L8.74 3H3.5l6.88 10.01L3.5 21h1.55l6.01-6.99L15.87 21h5.24l-7.13-10.38zm-2.13 2.47-.7-1-5.54-7.93H8l4.47 6.4.7 1 5.82 8.32h-2.39l-4.74-6.79z"/></svg>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'YouTube', href: 'https://www.youtube.com/@lytsup', bg: '#FF6B35',
|
||||||
|
icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M21.8 8s-.2-1.38-.8-1.99c-.76-.8-1.61-.8-2-.85C16.2 5 12 5 12 5s-4.2 0-7 .17c-.39.05-1.24.05-2 .85C2.4 6.62 2.2 8 2.2 8S2 9.62 2 11.24v1.52c0 1.62.2 3.24.2 3.24s.2 1.38.8 1.99c.76.8 1.76.77 2.2.85C6.8 19 12 19.03 12 19.03s4.2-.01 7-.22c.39-.05 1.24-.05 2-.85.6-.61.8-1.99.8-1.99S22 14.38 22 12.76v-1.52C22 9.62 21.8 8 21.8 8zm-11.87 6.59V8.79l5.4 2.82-5.4 2.98z"/></svg>,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export default function Footer() {
|
export default function Footer() {
|
||||||
const [email, setEmail] = useState("");
|
const [showScroll, setShowScroll] = useState(false);
|
||||||
const [subscribed, setSubscribed] = useState(false);
|
|
||||||
|
|
||||||
const handleSubscribe = (e: React.FormEvent) => {
|
useEffect(() => {
|
||||||
e.preventDefault();
|
const onScroll = () => setShowScroll(window.scrollY > 400);
|
||||||
if (email) {
|
window.addEventListener('scroll', onScroll, { passive: true });
|
||||||
setSubscribed(true);
|
return () => window.removeEventListener('scroll', onScroll);
|
||||||
setEmail("");
|
}, []);
|
||||||
setTimeout(() => setSubscribed(false), 5000);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className="relative bg-[#060606] border-t border-white/5 pt-16 pb-8 overflow-hidden">
|
<>
|
||||||
{/* Ambient background light glows */}
|
<footer className="lu-footer bg-night font-sora" style={{
|
||||||
<div className="absolute top-0 left-1/4 -translate-y-1/2 w-80 h-80 rounded-full bg-accent-purple/10 blur-[80px] pointer-events-none" />
|
color: '#fff',
|
||||||
<div className="absolute top-0 right-1/4 -translate-y-1/2 w-80 h-80 rounded-full bg-accent-pink/10 blur-[80px] pointer-events-none" />
|
position: 'relative',
|
||||||
|
overflow: 'hidden',
|
||||||
|
margin: '0 var(--sec-gutter) var(--sec-gap)',
|
||||||
|
border: `4px solid ${INK}`,
|
||||||
|
borderRadius: 28,
|
||||||
|
boxShadow: `0 12px 0 0 rgba(0,0,0,0.35)`,
|
||||||
|
}}>
|
||||||
|
{/* ── BIG CTA STICKER CARD ── */}
|
||||||
|
<div className="lu-cta-wrap" style={{ padding: '56px 48px 40px' }}>
|
||||||
|
<div className="lu-cta bg-cream" style={{
|
||||||
|
position: 'relative',
|
||||||
|
color: INK,
|
||||||
|
border: `4px solid ${INK}`,
|
||||||
|
borderRadius: 24,
|
||||||
|
boxShadow: `8px 8px 0 0 ${INK}`,
|
||||||
|
padding: '44px 48px',
|
||||||
|
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
|
||||||
|
flexWrap: 'wrap', gap: 28,
|
||||||
|
overflow: 'hidden',
|
||||||
|
}}>
|
||||||
|
{/* corner sticker */}
|
||||||
|
<span style={{
|
||||||
|
position: 'absolute', top: -18, right: 34, transform: 'rotate(8deg)',
|
||||||
|
background: '#FF2E88', color: '#fff', border: `3px solid ${INK}`,
|
||||||
|
borderRadius: 12, padding: '6px 14px', fontSize: 12, fontWeight: 900,
|
||||||
|
textTransform: 'uppercase', letterSpacing: '0.05em', boxShadow: `3px 3px 0 0 ${INK}`,
|
||||||
|
}}>join the loop</span>
|
||||||
|
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
|
<div style={{ maxWidth: 620 }}>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-12 mb-16">
|
<span style={{ display: 'inline-block', background: '#8B3DFF', color: '#fff', border: `3px solid ${INK}`, borderRadius: 10, padding: '5px 12px', fontSize: 11, fontWeight: 900, textTransform: 'uppercase', letterSpacing: '0.14em', marginBottom: 18, boxShadow: `3px 3px 0 0 ${INK}` }}>
|
||||||
{/* Brand Info */}
|
Earn. Spend. Live More.
|
||||||
<div className="space-y-4 col-span-1 md:col-span-1">
|
|
||||||
<Link href="/" className="inline-block">
|
|
||||||
<span className="text-2xl font-extrabold tracking-wider font-sora text-white">
|
|
||||||
Lyts<span className="text-primary text-glow-yellow">Up</span>
|
|
||||||
</span>
|
</span>
|
||||||
|
<h2 className="lu-cta-heading" style={{ fontSize: 'clamp(32px, 4.6vw, 60px)', fontWeight: 800, letterSpacing: '-0.03em', lineHeight: 0.98, margin: 0 }}>
|
||||||
|
Turn everyday moments<br />
|
||||||
|
<span style={{ position: 'relative', display: 'inline-block' }}>
|
||||||
|
into <span style={{ color: '#FF2E88' }}>real value.</span>
|
||||||
|
</span>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Link href="#for-business" className="lu-cta-btn" style={{
|
||||||
|
display: 'inline-flex', alignItems: 'center', gap: 10,
|
||||||
|
padding: '18px 36px', background: '#FFC72C', color: INK,
|
||||||
|
fontSize: 17, fontWeight: 900, textTransform: 'uppercase', letterSpacing: '0.03em',
|
||||||
|
border: `4px solid ${INK}`, borderRadius: 16, textDecoration: 'none',
|
||||||
|
boxShadow: `5px 5px 0 0 ${INK}`, whiteSpace: 'nowrap',
|
||||||
|
transition: 'transform 0.12s ease, box-shadow 0.12s ease',
|
||||||
|
}}>
|
||||||
|
Get Started
|
||||||
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
|
||||||
</Link>
|
</Link>
|
||||||
<p className="text-white/60 text-sm leading-relaxed max-w-xs">
|
|
||||||
The premier social currency app for Gen Z. Earn rewards for walking, playing, and living your best life.
|
|
||||||
</p>
|
|
||||||
<p className="text-primary font-semibold text-xs tracking-wider uppercase">
|
|
||||||
Earn. Spend. Live More.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Site Navigation */}
|
|
||||||
<div className="space-y-4">
|
|
||||||
<h4 className="text-white font-bold text-sm tracking-wider uppercase font-sora">Navigate</h4>
|
|
||||||
<ul className="space-y-2.5">
|
|
||||||
<li>
|
|
||||||
<a href="#earn" className="text-white/60 hover:text-primary transition-colors text-sm">Earn Points</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#spend" className="text-white/60 hover:text-primary transition-colors text-sm">Redeem Rewards</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#play" className="text-white/60 hover:text-primary transition-colors text-sm">Mini-Game</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#leaderboard" className="text-white/60 hover:text-primary transition-colors text-sm">Leaderboard</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Corporate Links */}
|
|
||||||
<div className="space-y-4">
|
|
||||||
<h4 className="text-white font-bold text-sm tracking-wider uppercase font-sora">Partnerships</h4>
|
|
||||||
<ul className="space-y-2.5">
|
|
||||||
<li>
|
|
||||||
<Link href="#" className="text-white/60 hover:text-primary transition-colors text-sm">Become a Partner</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link href="#" className="text-white/60 hover:text-primary transition-colors text-sm">Brands Portal</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link href="#" className="text-white/60 hover:text-primary transition-colors text-sm">API Integration</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link href="#" className="text-white/60 hover:text-primary transition-colors text-sm">Support Hub</Link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Newsletter subscription */}
|
|
||||||
<div className="space-y-4">
|
|
||||||
<h4 className="text-white font-bold text-sm tracking-wider uppercase font-sora">Get Secret Drops</h4>
|
|
||||||
<p className="text-white/60 text-xs">
|
|
||||||
Subscribe to get notified about ultra-rare brand voucher drops.
|
|
||||||
</p>
|
|
||||||
<form onSubmit={handleSubscribe} className="relative flex">
|
|
||||||
<input
|
|
||||||
type="email"
|
|
||||||
placeholder="your.email@gmail.com"
|
|
||||||
value={email}
|
|
||||||
onChange={(e) => setEmail(e.target.value)}
|
|
||||||
required
|
|
||||||
className="w-full bg-white/5 border border-white/10 rounded-xl px-4 py-2.5 text-sm text-white focus:outline-none focus:border-primary/50 transition-colors pr-10"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="absolute right-1 top-1 bottom-1 bg-primary text-dark font-bold px-3.5 rounded-lg hover:bg-primary/95 transition-colors flex items-center justify-center cursor-pointer"
|
|
||||||
aria-label="Subscribe"
|
|
||||||
>
|
|
||||||
<Send className="w-4 h-4" />
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
{subscribed && (
|
|
||||||
<p className="text-accent-lime text-xs font-semibold animate-pulse">
|
|
||||||
You're in! Check your inbox for secret codes.
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr className="border-white/5 mb-8" />
|
{/* ── COLUMNS ── */}
|
||||||
|
<div className="lu-columns" style={{
|
||||||
{/* Socials & Copyright */}
|
display: 'grid',
|
||||||
<div className="flex flex-col sm:flex-row justify-between items-center space-y-4 sm:space-y-0">
|
gridTemplateColumns: '1.6fr 1fr 1fr 1fr',
|
||||||
<div className="flex items-center space-x-2 text-xs text-white/40">
|
gap: 40, padding: '24px 48px 44px',
|
||||||
<span>© {new Date().getFullYear()} LytsUp.com. All rights reserved.</span>
|
alignItems: 'start',
|
||||||
<span className="hidden sm:inline">•</span>
|
}}>
|
||||||
<span className="flex items-center">
|
{/* Brand */}
|
||||||
Made with <Heart className="w-3.5 h-3.5 text-accent-pink fill-current mx-1" /> for Gen Z
|
<div className="lu-brand" style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start' }}>
|
||||||
</span>
|
<Link href="#intro" aria-label="LytsUp home" style={{
|
||||||
|
display: 'inline-flex', marginBottom: 20, textDecoration: 'none',
|
||||||
|
background: '#fff', border: `3px solid ${INK}`, borderRadius: 14,
|
||||||
|
padding: '10px 14px', boxShadow: `4px 4px 0 0 ${INK}`,
|
||||||
|
}}>
|
||||||
|
<Image src="/images/lytsup_app.png" alt="LytsUp" width={2048} height={554} style={{ height: 30, width: 'auto', display: 'block' }} />
|
||||||
|
</Link>
|
||||||
|
<p style={{ fontSize: 14.5, lineHeight: 1.7, color: 'rgba(255,255,255,0.6)', margin: '0 0 24px', maxWidth: 300 }}>
|
||||||
|
Social currency for real life. Earn LYTs for the things you already do — then spend them on stuff you actually want.
|
||||||
|
</p>
|
||||||
|
<div style={{ display: 'flex', gap: 12 }}>
|
||||||
|
{SOCIALS.map(({ label, href, icon, bg }) => (
|
||||||
|
<a key={label} href={href} target="_blank" rel="noopener noreferrer" aria-label={label}
|
||||||
|
className="lu-social"
|
||||||
|
style={{
|
||||||
|
width: 42, height: 42, borderRadius: 12,
|
||||||
|
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||||
|
background: bg, color: '#fff', border: `3px solid ${INK}`,
|
||||||
|
boxShadow: `3px 3px 0 0 ${INK}`,
|
||||||
|
transition: 'transform 0.12s ease, box-shadow 0.12s ease',
|
||||||
|
}}
|
||||||
|
>{icon}</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Social Icons */}
|
{/* Nav columns */}
|
||||||
<div className="flex space-x-4">
|
{NAV.map(col => (
|
||||||
<a
|
<nav key={col.title} className="lu-nav" aria-label={col.title}>
|
||||||
href="#"
|
<h4 style={{ display: 'inline-block', margin: '0 0 18px', fontSize: 12, fontWeight: 900, letterSpacing: '0.08em', textTransform: 'uppercase', color: INK, background: col.color, border: `2px solid ${INK}`, borderRadius: 8, padding: '4px 10px', boxShadow: `2px 2px 0 0 ${INK}` }}>
|
||||||
className="w-8 h-8 rounded-full bg-white/5 flex items-center justify-center text-white/60 hover:bg-accent-pink hover:text-white transition-all scale-95 hover:scale-100"
|
{col.title}
|
||||||
aria-label="Instagram"
|
</h4>
|
||||||
>
|
<ul style={{ listStyle: 'none', margin: 0, padding: 0, display: 'flex', flexDirection: 'column', gap: 12 }}>
|
||||||
<Instagram className="w-4 h-4" />
|
{col.links.map(({ label, href }) => (
|
||||||
</a>
|
<li key={label}>
|
||||||
<a
|
<Link href={href} className="lu-link" style={{ textDecoration: 'none', fontSize: 15, color: 'rgba(255,255,255,0.65)', fontWeight: 600, transition: 'color 0.15s, transform 0.15s', display: 'inline-block' }}
|
||||||
href="#"
|
onMouseEnter={e => { const el = e.currentTarget as HTMLElement; el.style.color = col.color; el.style.transform = 'translateX(4px)'; }}
|
||||||
className="w-8 h-8 rounded-full bg-white/5 flex items-center justify-center text-white/60 hover:bg-accent-purple hover:text-white transition-all scale-95 hover:scale-100"
|
onMouseLeave={e => { const el = e.currentTarget as HTMLElement; el.style.color = 'rgba(255,255,255,0.65)'; el.style.transform = 'translateX(0)'; }}
|
||||||
aria-label="Twitter"
|
>{label}</Link>
|
||||||
>
|
</li>
|
||||||
<Twitter className="w-4 h-4" />
|
))}
|
||||||
</a>
|
</ul>
|
||||||
<a
|
</nav>
|
||||||
href="#"
|
))}
|
||||||
className="w-8 h-8 rounded-full bg-white/5 flex items-center justify-center text-white/60 hover:bg-primary hover:text-dark transition-all scale-95 hover:scale-100"
|
</div>
|
||||||
aria-label="Discord"
|
|
||||||
>
|
{/* ── BOTTOM BAR ── */}
|
||||||
<MessageSquare className="w-4 h-4" />
|
<div className="lu-bottom" style={{
|
||||||
</a>
|
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
|
||||||
|
flexWrap: 'wrap', gap: 14,
|
||||||
|
padding: '18px 48px 30px',
|
||||||
|
borderTop: `2px dashed rgba(255,255,255,0.2)`,
|
||||||
|
fontSize: 13, color: 'rgba(255,255,255,0.5)',
|
||||||
|
}}>
|
||||||
|
<span style={{ display: 'inline-flex', alignItems: 'center', gap: 8, fontWeight: 600 }}>
|
||||||
|
© {new Date().getFullYear()} LytsUp. Made with
|
||||||
|
<span style={{ color: '#FF2E88' }}>♥</span> for Gen Z.
|
||||||
|
</span>
|
||||||
|
<div style={{ display: 'flex', gap: 20 }}>
|
||||||
|
{[['Terms', '#'], ['Privacy', '#'], ['Cookies', '#']].map(([l, h]) => (
|
||||||
|
<Link key={l} href={h} style={{ textDecoration: 'none', color: 'inherit', fontWeight: 600, transition: 'color 0.15s' }}
|
||||||
|
onMouseEnter={e => ((e.currentTarget as HTMLElement).style.color = '#FFC72C')}
|
||||||
|
onMouseLeave={e => ((e.currentTarget as HTMLElement).style.color = 'rgba(255,255,255,0.5)')}
|
||||||
|
>{l}</Link>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</footer>
|
<style>{`
|
||||||
|
.lu-cta-btn:hover, .lu-social:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 0 ${INK} !important; }
|
||||||
|
.lu-cta-btn:active { transform: translate(1px, 1px); box-shadow: 2px 2px 0 0 ${INK} !important; }
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
.lu-footer { margin: 0 12px 12px; border-radius: 22px; }
|
||||||
|
.lu-cta-wrap { padding: 32px 20px 24px !important; }
|
||||||
|
.lu-cta { padding: 32px 26px !important; align-items: flex-start !important; }
|
||||||
|
.lu-cta-btn { width: 100%; justify-content: center; }
|
||||||
|
.lu-columns { grid-template-columns: 1fr 1fr !important; gap: 32px 24px !important; padding: 16px 24px 36px !important; }
|
||||||
|
.lu-brand { grid-column: 1 / -1; }
|
||||||
|
.lu-bottom { padding: 18px 24px 26px !important; flex-direction: column !important; align-items: flex-start !important; }
|
||||||
|
}
|
||||||
|
@media (max-width: 520px) {
|
||||||
|
.lu-columns { grid-template-columns: 1fr !important; }
|
||||||
|
.lu-cta-heading { font-size: clamp(26px, 8vw, 40px) !important; }
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
{/* Scroll-to-top — neobrutalist */}
|
||||||
|
<style>{`
|
||||||
|
@keyframes luBounce { 0%,100% { transform: translateY(0);} 40% { transform: translateY(-4px);} 60% { transform: translateY(-2px);} }
|
||||||
|
.lu-stt:hover { transform: translate(-2px,-2px) !important; box-shadow: 6px 6px 0 0 ${INK} !important; }
|
||||||
|
.lu-stt:active { transform: translate(1px,1px) !important; box-shadow: 1px 1px 0 0 ${INK} !important; }
|
||||||
|
.lu-stt-arrow { animation: luBounce 1.5s ease-in-out infinite; }
|
||||||
|
`}</style>
|
||||||
|
<button
|
||||||
|
onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
|
||||||
|
aria-label="Scroll to top"
|
||||||
|
className="lu-stt"
|
||||||
|
style={{
|
||||||
|
position: 'fixed', bottom: 28, right: 28, zIndex: 9999,
|
||||||
|
width: 60, height: 60, borderRadius: 16,
|
||||||
|
background: '#FFC72C', color: INK, border: `3px solid ${INK}`,
|
||||||
|
cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||||
|
boxShadow: `4px 4px 0 0 ${INK}`,
|
||||||
|
opacity: showScroll ? 1 : 0,
|
||||||
|
transform: showScroll ? 'translateY(0)' : 'translateY(16px)',
|
||||||
|
pointerEvents: showScroll ? 'auto' : 'none',
|
||||||
|
transition: 'opacity 0.25s ease, transform 0.15s ease, box-shadow 0.15s ease',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="lu-stt-arrow" style={{ display: 'flex' }}>
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><path d="M12 19V5M5 12l7-7 7 7"/></svg>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
383
src/components/layout/Header.tsx
Normal file
383
src/components/layout/Header.tsx
Normal file
@@ -0,0 +1,383 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useState, useEffect, useRef } from 'react';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import Image from 'next/image';
|
||||||
|
|
||||||
|
const INK = '#0a0a0a';
|
||||||
|
|
||||||
|
const NAV_LINKS = [
|
||||||
|
{ label: 'Earn', href: '#for-you', color: '#C8FF37' }, // lime
|
||||||
|
{ label: 'Spend', href: '#difference', color: '#FF2E88' }, // pink
|
||||||
|
{ label: 'Live', href: '#the-vision', color: '#8B3DFF' }, // purple
|
||||||
|
];
|
||||||
|
|
||||||
|
const MOBILE_QUERY = '(max-width: 1023px)';
|
||||||
|
|
||||||
|
export default function Header() {
|
||||||
|
const [mobileOpen, setMobileOpen] = useState(false);
|
||||||
|
const [scrolled, setScrolled] = useState(false);
|
||||||
|
const [hidden, setHidden] = useState(false);
|
||||||
|
const mobileMenuRef = useRef<HTMLDivElement>(null);
|
||||||
|
const lastScrollYRef = useRef(0);
|
||||||
|
|
||||||
|
// Hide on scroll-down, reveal on scroll-up; deepen the shadow once scrolled.
|
||||||
|
useEffect(() => {
|
||||||
|
lastScrollYRef.current = window.scrollY;
|
||||||
|
const onScroll = () => {
|
||||||
|
const y = window.scrollY;
|
||||||
|
setScrolled(y > 40);
|
||||||
|
const lastY = lastScrollYRef.current;
|
||||||
|
if (y <= 80) setHidden(false);
|
||||||
|
else if (y > lastY + 4) setHidden(true);
|
||||||
|
else if (y < lastY - 4) setHidden(false);
|
||||||
|
lastScrollYRef.current = y;
|
||||||
|
};
|
||||||
|
window.addEventListener('scroll', onScroll, { passive: true });
|
||||||
|
return () => window.removeEventListener('scroll', onScroll);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (mobileOpen) setHidden(false);
|
||||||
|
}, [mobileOpen]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!mobileOpen) return;
|
||||||
|
const handler = (e: MouseEvent) => {
|
||||||
|
if (mobileMenuRef.current && !mobileMenuRef.current.contains(e.target as Node)) {
|
||||||
|
setMobileOpen(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.addEventListener('mousedown', handler);
|
||||||
|
return () => document.removeEventListener('mousedown', handler);
|
||||||
|
}, [mobileOpen]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.body.style.overflow = mobileOpen ? 'hidden' : '';
|
||||||
|
return () => { document.body.style.overflow = ''; };
|
||||||
|
}, [mobileOpen]);
|
||||||
|
|
||||||
|
const [isMobileViewport, setIsMobileViewport] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
const mql = window.matchMedia(MOBILE_QUERY);
|
||||||
|
setIsMobileViewport(mql.matches);
|
||||||
|
const update = () => setIsMobileViewport(mql.matches);
|
||||||
|
mql.addEventListener('change', update);
|
||||||
|
return () => mql.removeEventListener('change', update);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div suppressHydrationWarning>
|
||||||
|
{/* Mobile menu overlay */}
|
||||||
|
{mobileOpen && (
|
||||||
|
<div
|
||||||
|
onClick={() => setMobileOpen(false)}
|
||||||
|
aria-hidden="true"
|
||||||
|
style={{ position: 'fixed', inset: 0, zIndex: 99999998, background: 'rgba(10,4,20,0.6)' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Mobile slide-in panel — night dot-grid, neobrutalist links */}
|
||||||
|
<div
|
||||||
|
ref={mobileMenuRef}
|
||||||
|
role="dialog"
|
||||||
|
aria-label="Navigation menu"
|
||||||
|
aria-modal="true"
|
||||||
|
className="bg-night"
|
||||||
|
style={{
|
||||||
|
position: 'fixed',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
height: '100%',
|
||||||
|
width: 'min(330px, 86vw)',
|
||||||
|
zIndex: 999999999,
|
||||||
|
color: '#fff',
|
||||||
|
transform: mobileOpen ? 'translateX(0)' : 'translateX(-100%)',
|
||||||
|
transition: 'transform 0.32s cubic-bezier(0.34,1.3,0.64,1)',
|
||||||
|
overflowY: 'auto',
|
||||||
|
padding: '22px 24px 40px',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: '28px',
|
||||||
|
// Border + shadow only while open, so nothing bleeds onto the screen's
|
||||||
|
// left edge when the panel is parked off-screen.
|
||||||
|
borderRight: mobileOpen ? `4px solid ${INK}` : 'none',
|
||||||
|
boxShadow: mobileOpen ? `8px 0 0 0 rgba(0,0,0,0.35)` : 'none',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
|
<span style={{ display: 'inline-flex', background: '#fff', border: `3px solid ${INK}`, borderRadius: 14, padding: '8px 12px', boxShadow: `4px 4px 0 0 ${INK}` }}>
|
||||||
|
<Image src="/images/lytsup_app.png" alt="LytsUp" width={2048} height={554} priority style={{ height: 24, width: 'auto', display: 'block' }} />
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
onClick={() => setMobileOpen(false)}
|
||||||
|
aria-label="Close menu"
|
||||||
|
style={{ background: '#FF2E88', color: '#fff', border: `3px solid ${INK}`, borderRadius: 12, width: 40, height: 40, fontSize: 20, fontWeight: 900, cursor: 'pointer', lineHeight: 1, boxShadow: `3px 3px 0 0 ${INK}` }}
|
||||||
|
>
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav>
|
||||||
|
<ul style={{ listStyle: 'none', margin: 0, padding: 0, display: 'flex', flexDirection: 'column', gap: '12px' }}>
|
||||||
|
{NAV_LINKS.map(({ label, href, color }) => (
|
||||||
|
<li key={href}>
|
||||||
|
<Link
|
||||||
|
href={href}
|
||||||
|
onClick={() => setMobileOpen(false)}
|
||||||
|
className="font-sora"
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
padding: '14px 18px',
|
||||||
|
color: INK,
|
||||||
|
background: color,
|
||||||
|
textDecoration: 'none',
|
||||||
|
fontSize: '18px',
|
||||||
|
fontWeight: 800,
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
letterSpacing: '0.02em',
|
||||||
|
border: `3px solid ${INK}`,
|
||||||
|
borderRadius: 14,
|
||||||
|
boxShadow: `4px 4px 0 0 ${INK}`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p className="font-sora" style={{ margin: '0 0 12px', fontWeight: 800, textTransform: 'uppercase', fontSize: '11px', letterSpacing: '0.12em', color: '#FFC72C' }}>
|
||||||
|
Follow us
|
||||||
|
</p>
|
||||||
|
<div style={{ display: 'flex', gap: '12px' }}>
|
||||||
|
{SOCIALS.map(({ href, label, icon }) => (
|
||||||
|
<a
|
||||||
|
key={label}
|
||||||
|
href={href}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
aria-label={label}
|
||||||
|
style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', width: 40, height: 40, borderRadius: 12, background: '#fff', color: INK, border: `3px solid ${INK}`, boxShadow: `3px 3px 0 0 ${INK}` }}
|
||||||
|
>
|
||||||
|
{icon}
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Link
|
||||||
|
href="#for-business"
|
||||||
|
onClick={() => setMobileOpen(false)}
|
||||||
|
className="font-sora"
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
marginTop: 'auto',
|
||||||
|
padding: '16px 24px',
|
||||||
|
background: '#FFC72C',
|
||||||
|
color: INK,
|
||||||
|
border: `3px solid ${INK}`,
|
||||||
|
borderRadius: 14,
|
||||||
|
fontWeight: 900,
|
||||||
|
fontSize: 16,
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
textDecoration: 'none',
|
||||||
|
textAlign: 'center',
|
||||||
|
boxShadow: `5px 5px 0 0 ${INK}`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Get Started →
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* ——— Funky neobrutalist floating bar ——— */}
|
||||||
|
<header
|
||||||
|
style={{
|
||||||
|
position: 'fixed',
|
||||||
|
top: isMobileViewport ? '14px' : '18px',
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
width: isMobileViewport ? 'auto' : '70%',
|
||||||
|
maxWidth: 'calc(100% - 2 * var(--hdr-gutter))',
|
||||||
|
marginLeft: isMobileViewport ? 'var(--hdr-gutter)' : 'auto',
|
||||||
|
marginRight: isMobileViewport ? 'var(--hdr-gutter)' : 'auto',
|
||||||
|
zIndex: 99999999,
|
||||||
|
background: '#FFFDF5',
|
||||||
|
border: `3px solid ${INK}`,
|
||||||
|
borderRadius: '20px',
|
||||||
|
boxShadow: scrolled ? `8px 8px 0 0 ${INK}` : `5px 6px 0 0 ${INK}`,
|
||||||
|
transform: hidden ? 'translateY(-160%)' : 'translateY(0)',
|
||||||
|
transition: 'transform 0.35s cubic-bezier(0.4,0,0.2,1), box-shadow 0.25s ease',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="header-inner" style={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
padding: '0 22px',
|
||||||
|
height: '72px',
|
||||||
|
width: '100%',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
gap: 16,
|
||||||
|
}}>
|
||||||
|
{/* Logo */}
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||||
|
<Link href="#intro" aria-label="LytsUp home" style={{ display: 'inline-flex', alignItems: 'center', textDecoration: 'none' }}>
|
||||||
|
<Image
|
||||||
|
src="/images/lytsup_app.png"
|
||||||
|
alt="LytsUp"
|
||||||
|
width={2048}
|
||||||
|
height={554}
|
||||||
|
priority
|
||||||
|
className="header-logo-img"
|
||||||
|
style={{ height: 34, width: 'auto', objectFit: 'contain', display: 'block' }}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Desktop nav — boxy neobrutalist sticker tabs */}
|
||||||
|
<nav aria-label="Main navigation" className="desktop-nav">
|
||||||
|
<ul className="header-nav-row" style={{
|
||||||
|
display: 'flex',
|
||||||
|
listStyle: 'none',
|
||||||
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 12,
|
||||||
|
}}>
|
||||||
|
{NAV_LINKS.map(({ label, href, color }, i) => {
|
||||||
|
const tilt = i % 2 === 0 ? -2 : 2;
|
||||||
|
return (
|
||||||
|
<li key={href}>
|
||||||
|
<Link
|
||||||
|
href={href}
|
||||||
|
className="header-nav-tab font-sora"
|
||||||
|
style={{
|
||||||
|
display: 'inline-flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 8,
|
||||||
|
padding: '8px 16px',
|
||||||
|
color: INK,
|
||||||
|
textDecoration: 'none',
|
||||||
|
fontWeight: 800,
|
||||||
|
fontSize: '13px',
|
||||||
|
letterSpacing: '0.05em',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
borderRadius: '12px',
|
||||||
|
background: '#fff',
|
||||||
|
border: `2.5px solid ${INK}`,
|
||||||
|
boxShadow: `3px 3px 0 0 ${INK}`,
|
||||||
|
transition: 'transform 0.15s, background 0.15s, box-shadow 0.15s',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
transform: `rotate(${tilt}deg)`,
|
||||||
|
['--hov' as string]: color,
|
||||||
|
['--tilt' as string]: `${tilt}deg`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
style={{ width: 8, height: 8, borderRadius: 3, background: color, border: `1.5px solid ${INK}`, flexShrink: 0 }}
|
||||||
|
/>
|
||||||
|
{label}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{/* Right actions */}
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
|
||||||
|
<Link
|
||||||
|
href="#for-business"
|
||||||
|
className="header-cta desktop-nav font-sora"
|
||||||
|
style={{
|
||||||
|
display: 'inline-flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
padding: '11px 26px',
|
||||||
|
background: '#FFC72C',
|
||||||
|
color: INK,
|
||||||
|
border: `3px solid ${INK}`,
|
||||||
|
borderRadius: '50px',
|
||||||
|
fontWeight: 900,
|
||||||
|
textDecoration: 'none',
|
||||||
|
fontSize: '14px',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
letterSpacing: '0.03em',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
boxShadow: `3px 3px 0 0 ${INK}`,
|
||||||
|
transition: 'transform 0.12s ease, box-shadow 0.12s ease, background 0.15s',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Get Started
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
{/* Hamburger — mobile only */}
|
||||||
|
<button
|
||||||
|
className="menu-trigger"
|
||||||
|
onClick={() => setMobileOpen(true)}
|
||||||
|
aria-label="Open navigation menu"
|
||||||
|
aria-expanded={mobileOpen}
|
||||||
|
style={{ background: '#8B3DFF', border: `3px solid ${INK}`, borderRadius: 12, cursor: 'pointer', padding: 0, width: 44, height: 44, display: 'none', alignItems: 'center', justifyContent: 'center', boxShadow: `3px 3px 0 0 ${INK}` }}
|
||||||
|
>
|
||||||
|
<span style={{ display: 'flex', flexDirection: 'column', gap: '4px', width: '20px' }}>
|
||||||
|
<span style={{ display: 'block', height: '3px', background: '#fff', borderRadius: '2px' }} />
|
||||||
|
<span style={{ display: 'block', height: '3px', background: '#fff', borderRadius: '2px' }} />
|
||||||
|
<span style={{ display: 'block', height: '3px', background: '#fff', borderRadius: '2px' }} />
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<style>{`
|
||||||
|
@media (max-width: 1023px) {
|
||||||
|
.desktop-nav { display: none !important; }
|
||||||
|
.menu-trigger { display: flex !important; }
|
||||||
|
.header-inner { height: 60px !important; }
|
||||||
|
.header-logo-img { height: 28px !important; }
|
||||||
|
}
|
||||||
|
@media (min-width: 1024px) and (max-width: 1200px) {
|
||||||
|
.header-nav-tab { padding: 7px 12px !important; font-size: 11px !important; letter-spacing: 0.03em !important; }
|
||||||
|
.header-cta { padding: 9px 18px !important; font-size: 12px !important; }
|
||||||
|
.header-logo-img { height: 30px !important; }
|
||||||
|
}
|
||||||
|
.header-nav-tab:hover {
|
||||||
|
background: var(--hov) !important;
|
||||||
|
transform: translateY(-3px) rotate(var(--tilt));
|
||||||
|
box-shadow: 5px 5px 0 0 ${INK} !important;
|
||||||
|
}
|
||||||
|
.header-nav-tab:active {
|
||||||
|
transform: translateY(1px) rotate(var(--tilt));
|
||||||
|
box-shadow: 1px 1px 0 0 ${INK} !important;
|
||||||
|
}
|
||||||
|
.header-cta:hover {
|
||||||
|
background: #FFD95A !important;
|
||||||
|
transform: translate(-2px, -2px);
|
||||||
|
box-shadow: 5px 5px 0 0 ${INK} !important;
|
||||||
|
}
|
||||||
|
.header-cta:active {
|
||||||
|
transform: translate(1px, 1px);
|
||||||
|
box-shadow: 1px 1px 0 0 ${INK} !important;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ——— Inline SVG social icons ——— */
|
||||||
|
const SOCIALS = [
|
||||||
|
{
|
||||||
|
label: 'Instagram', href: 'https://instagram.com/lytsup',
|
||||||
|
icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 2.16c3.2 0 3.58.01 4.85.07 3.25.15 4.77 1.69 4.92 4.92.06 1.27.07 1.65.07 4.85 0 3.2-.01 3.58-.07 4.85-.15 3.23-1.66 4.77-4.92 4.92-1.27.06-1.64.07-4.85.07-3.2 0-3.58-.01-4.85-.07-3.26-.15-4.77-1.7-4.92-4.92-.06-1.27-.07-1.64-.07-4.85 0-3.2.01-3.58.07-4.85.15-3.23 1.66-4.77 4.92-4.92C8.42 2.17 8.8 2.16 12 2.16zm0-2.16C8.74 0 8.33.01 7.05.07 2.7.27.27 2.69.07 7.05.01 8.33 0 8.74 0 12s.01 3.67.07 4.95c.2 4.36 2.62 6.78 6.98 6.98C8.33 23.99 8.74 24 12 24s3.67-.01 4.95-.07c4.35-.2 6.78-2.62 6.98-6.98.06-1.28.07-1.69.07-4.95s-.01-3.67-.07-4.95c-.2-4.35-2.62-6.78-6.98-6.98C15.67.01 15.26 0 12 0zm0 5.84a6.16 6.16 0 100 12.32 6.16 6.16 0 000-12.32zM12 16a4 4 0 110-8 4 4 0 010 8zm6.41-11.85a1.44 1.44 0 100 2.88 1.44 1.44 0 000-2.88z"/></svg>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'X / Twitter', href: 'https://twitter.com/lytsup',
|
||||||
|
icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M13.98 10.62 20.54 3h-1.55l-5.7 6.62L8.74 3H3.5l6.88 10.01L3.5 21h1.55l6.01-6.99L15.87 21h5.24l-7.13-10.38zm-2.13 2.47-.7-1-5.54-7.93H8l4.47 6.4.7 1 5.82 8.32h-2.39l-4.74-6.79z"/></svg>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'YouTube', href: 'https://www.youtube.com/@lytsup',
|
||||||
|
icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M21.8 8s-.2-1.38-.8-1.99c-.76-.8-1.61-.8-2-.85C16.2 5 12 5 12 5s-4.2 0-7 .17c-.39.05-1.24.05-2 .85C2.4 6.62 2.2 8 2.2 8S2 9.62 2 11.24v1.52c0 1.62.2 3.24.2 3.24s.2 1.38.8 1.99c.76.8 1.76.77 2.2.85C6.8 19 12 19.03 12 19.03s4.2-.01 7-.22c.39-.05 1.24-.05 2-.85.6-.61.8-1.99.8-1.99S22 14.38 22 12.76v-1.52C22 9.62 21.8 8 21.8 8zm-11.87 6.59V8.79l5.4 2.82-5.4 2.98z"/></svg>,
|
||||||
|
},
|
||||||
|
];
|
||||||
38
src/components/layout/ScrollProgress.tsx
Normal file
38
src/components/layout/ScrollProgress.tsx
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
|
/* Site-wide reading-progress bar — sits at the very top edge and fills with the
|
||||||
|
brand gradient as you scroll. Driven by a rAF lerp so it glides smoothly and
|
||||||
|
works with Lenis smooth-scroll (reads native window.scrollY). */
|
||||||
|
export default function ScrollProgress() {
|
||||||
|
const barRef = useRef<HTMLDivElement>(null);
|
||||||
|
const target = useRef(0);
|
||||||
|
const current = useRef(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let raf = 0;
|
||||||
|
const tick = () => {
|
||||||
|
// Read scroll position every frame so it tracks regardless of how the
|
||||||
|
// smooth-scroll library emits events.
|
||||||
|
const max = document.documentElement.scrollHeight - window.innerHeight;
|
||||||
|
target.current = max > 0 ? Math.min(1, Math.max(0, window.scrollY / max)) : 0;
|
||||||
|
current.current += (target.current - current.current) * 0.12;
|
||||||
|
if (barRef.current) {
|
||||||
|
barRef.current.style.transform = `scaleX(${current.current.toFixed(4)})`;
|
||||||
|
}
|
||||||
|
raf = requestAnimationFrame(tick);
|
||||||
|
};
|
||||||
|
raf = requestAnimationFrame(tick);
|
||||||
|
return () => cancelAnimationFrame(raf);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
aria-hidden
|
||||||
|
ref={barRef}
|
||||||
|
className="fixed left-0 top-0 z-[100000000] h-1.5 w-full origin-left bg-gradient-to-r from-[#FFC72C] via-[#FF2E88] to-[#8B3DFF]"
|
||||||
|
style={{ transform: "scaleX(0)" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,45 +1,109 @@
|
|||||||
import { Section, Pill, Card, Chip, Heading, Logo, Group, Reveal } from "./ui";
|
import { Section, Pill, Card, Chip, Heading, Group, Reveal } from "./ui";
|
||||||
import { C } from "./palette";
|
import { C } from "./palette";
|
||||||
|
|
||||||
/* 01 — INTRO / HERO */
|
/* 01 — INTRO / HERO */
|
||||||
export function Intro() {
|
export function Intro() {
|
||||||
return (
|
return (
|
||||||
<Section id="intro" variant="deep">
|
<Section id="intro" variant="deep">
|
||||||
{/* giant watermark */}
|
{/* animated ambient glows — soft washes, heavily blurred so no hard edge shows */}
|
||||||
<span className="pointer-events-none absolute right-0 top-1/2 -z-0 -translate-y-1/2 select-none font-sora text-[28vw] font-extrabold leading-none text-white/5">
|
<span aria-hidden className="animate-pulse-glow pointer-events-none absolute -left-40 -top-16 -z-0 h-[30rem] w-[30rem] rounded-full bg-[#FF2E88]/15 blur-[150px]" />
|
||||||
|
<span aria-hidden className="animate-float pointer-events-none absolute -bottom-16 left-1/4 -z-0 h-[28rem] w-[28rem] rounded-full bg-[#8B3DFF]/20 blur-[150px]" />
|
||||||
|
<span aria-hidden className="animate-float pointer-events-none absolute -right-16 top-1/3 -z-0 h-[26rem] w-[26rem] rounded-full bg-[#C8FF37]/10 blur-[140px]" style={{ animationDelay: "1.5s" }} />
|
||||||
|
|
||||||
|
{/* giant drifting watermark */}
|
||||||
|
<span className="animate-float pointer-events-none absolute right-0 top-1/2 -z-0 -translate-y-1/2 select-none font-sora text-[28vw] font-extrabold leading-none text-white/[0.06]">
|
||||||
LYTS
|
LYTS
|
||||||
</span>
|
</span>
|
||||||
<div className="relative z-10">
|
|
||||||
<Card bg="#fff" className="mb-8 w-fit px-6 py-4" rounded="rounded-2xl">
|
<div className="relative z-10 pt-24 sm:pt-28 lg:pt-32">
|
||||||
<Logo />
|
{/* eyebrow badge */}
|
||||||
</Card>
|
<Reveal>
|
||||||
<div className="mt-8 space-y-1 font-bold text-[#FFD21E] sm:text-lg">
|
<span className="nb inline-flex items-center gap-2.5 rounded-full bg-[#C8FF37] px-5 py-2.5 font-sora text-sm font-extrabold uppercase tracking-wide text-[#0a0a0a]">
|
||||||
<p>we built this for you.</p>
|
<span className="relative flex h-2.5 w-2.5">
|
||||||
<p>
|
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-[#FF2E88] opacity-75" />
|
||||||
social currency is value earned for <em className="italic">participating</em> in life.
|
<span className="relative inline-flex h-2.5 w-2.5 rounded-full bg-[#FF2E88]" />
|
||||||
</p>
|
|
||||||
<p>a LYTIAN believes every meaningful interaction has value.</p>
|
|
||||||
</div>
|
|
||||||
<h1 className="mt-8 font-sora text-6xl font-extrabold leading-[0.9] tracking-tight text-white sm:text-7xl lg:text-8xl">
|
|
||||||
social
|
|
||||||
<br />
|
|
||||||
currency
|
|
||||||
<br />
|
|
||||||
for real life.
|
|
||||||
</h1>
|
|
||||||
<div className="mt-8">
|
|
||||||
<Chip bg="#0a0a0a" text="#fff">
|
|
||||||
<span className="text-[#C8FF37]">"earn. spend. live more."</span>
|
|
||||||
<span className="ml-2 font-semibold text-white/80">
|
|
||||||
a quiet belief that everyday moments matter.
|
|
||||||
</span>
|
</span>
|
||||||
</Chip>
|
social currency, reimagined
|
||||||
</div>
|
</span>
|
||||||
|
</Reveal>
|
||||||
|
|
||||||
|
{/* eyebrow copy */}
|
||||||
|
<Reveal delay={0.08}>
|
||||||
|
<div className="mt-6 space-y-1 font-bold text-[#FFD21E] sm:text-lg">
|
||||||
|
<p>we built this for you.</p>
|
||||||
|
<p>
|
||||||
|
social currency is value earned for <em className="italic">participating</em> in life.
|
||||||
|
</p>
|
||||||
|
<p>a LYTIAN believes every meaningful interaction has value.</p>
|
||||||
|
</div>
|
||||||
|
</Reveal>
|
||||||
|
|
||||||
|
{/* headline — line-by-line reveal, shimmering last line */}
|
||||||
|
<h1 className="mt-8 font-sora text-6xl font-extrabold leading-[0.88] tracking-tight text-white sm:text-7xl lg:text-8xl">
|
||||||
|
<Reveal delay={0.14}><span className="block">social</span></Reveal>
|
||||||
|
<Reveal delay={0.22}><span className="block">currency</span></Reveal>
|
||||||
|
<Reveal delay={0.3}>
|
||||||
|
<span className="block">
|
||||||
|
for{" "}
|
||||||
|
<span className="animate-shimmer bg-gradient-to-r from-[#FFC72C] via-[#FF2E88] to-[#8B3DFF] bg-[length:200%_auto] bg-clip-text text-transparent">
|
||||||
|
real life.
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</Reveal>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
{/* CTA buttons */}
|
||||||
|
<Reveal delay={0.38}>
|
||||||
|
<div className="mt-9 flex flex-col items-start gap-4 sm:flex-row sm:items-center">
|
||||||
|
<a
|
||||||
|
href="#for-business"
|
||||||
|
className="nb nb-hover inline-flex items-center gap-2 rounded-full bg-[#FFC72C] px-8 py-4 font-sora text-base font-extrabold uppercase tracking-wide text-[#0a0a0a] sm:text-lg"
|
||||||
|
>
|
||||||
|
Get Started
|
||||||
|
<span aria-hidden>→</span>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="#how-it-works"
|
||||||
|
className="nb nb-hover inline-flex items-center gap-2 rounded-full bg-white px-8 py-4 font-sora text-base font-extrabold uppercase tracking-wide text-[#0a0a0a] sm:text-lg"
|
||||||
|
>
|
||||||
|
How it works
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</Reveal>
|
||||||
|
|
||||||
|
{/* tagline chip */}
|
||||||
|
<Reveal delay={0.46}>
|
||||||
|
<div className="mt-8">
|
||||||
|
<Chip bg="#0a0a0a" text="#fff">
|
||||||
|
<span className="text-[#C8FF37]">"earn. spend. live more."</span>
|
||||||
|
<span className="ml-2 font-semibold text-white/80">
|
||||||
|
a quiet belief that everyday moments matter.
|
||||||
|
</span>
|
||||||
|
</Chip>
|
||||||
|
</div>
|
||||||
|
</Reveal>
|
||||||
</div>
|
</div>
|
||||||
<div className="absolute right-8 top-24 hidden h-40 w-40 rotate-6 items-center justify-center rounded-full bg-[#FFD21E] text-center font-sora text-lg font-extrabold text-[#0a0a0a] nb lg:flex">
|
|
||||||
<div>
|
{/* floating reward stickers (desktop) */}
|
||||||
<div className="text-xs font-bold text-[#FF2E88]">psst</div>
|
<div aria-hidden className="pointer-events-none absolute inset-0 -z-0 hidden lg:block">
|
||||||
make everyday count.
|
<span className="animate-float nb-sm absolute right-[16%] top-[20%] -rotate-6 rounded-xl bg-[#FF2E88] px-4 py-2 font-sora text-lg font-extrabold text-white">
|
||||||
|
+50 LYTs
|
||||||
|
</span>
|
||||||
|
<span className="animate-float nb-sm absolute right-[30%] top-[52%] rotate-6 rounded-xl bg-white px-4 py-2 font-sora text-lg font-extrabold text-[#0a0a0a]" style={{ animationDelay: "0.8s" }}>
|
||||||
|
🔥 7-day streak
|
||||||
|
</span>
|
||||||
|
<span className="animate-float nb-sm absolute bottom-[16%] right-[20%] -rotate-3 rounded-xl bg-[#C8FF37] px-4 py-2 font-sora text-lg font-extrabold text-[#0a0a0a]" style={{ animationDelay: "1.6s" }}>
|
||||||
|
🎁 rewards unlocked
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* rotating "make everyday count" badge — pinned to the right, vertically centered */}
|
||||||
|
<div className="absolute right-8 top-1/2 hidden -translate-y-1/2 lg:block">
|
||||||
|
<div className="animate-float nb flex h-40 w-40 rotate-6 items-center justify-center rounded-full bg-[#FFD21E] text-center font-sora text-lg font-extrabold text-[#0a0a0a]">
|
||||||
|
<div>
|
||||||
|
<div className="text-xs font-bold uppercase tracking-widest text-[#FF2E88]">psst</div>
|
||||||
|
make everyday count.
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Section>
|
</Section>
|
||||||
@@ -78,7 +142,7 @@ export function TheWhy() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<Card bg="#fff" className="-rotate-1 p-5">
|
<Card bg="#fff" className="-rotate-1 p-5">
|
||||||
<div className="font-sora font-extrabold">🎬 DISCOVER ON TIKTOK</div>
|
<div className="font-sora font-extrabold">🎬 DISCOVER ON SOCIAL MEDIA</div>
|
||||||
<div className="text-sm font-semibold text-black/70">brand relationships start before purchase</div>
|
<div className="text-sm font-semibold text-black/70">brand relationships start before purchase</div>
|
||||||
</Card>
|
</Card>
|
||||||
<Card bg={C.pink} text="#fff" className="rotate-1 p-5">
|
<Card bg={C.pink} text="#fff" className="rotate-1 p-5">
|
||||||
|
|||||||
@@ -231,22 +231,20 @@ export function OurBelief() {
|
|||||||
return (
|
return (
|
||||||
<Section id="our-belief" variant="night">
|
<Section id="our-belief" variant="night">
|
||||||
<div className="mx-auto flex flex-col items-center text-center">
|
<div className="mx-auto flex flex-col items-center text-center">
|
||||||
<span className="nb flex h-20 w-20 items-center justify-center rounded-full bg-[#0a0a0a] font-sora text-sm font-extrabold text-[#FFD21E] ring-2 ring-[#FF2E88]">
|
<Pill bg="#0a0a0a" text={C.yellow}>🌱 our belief</Pill>
|
||||||
🌱 our belief
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-12 space-y-6">
|
<div className="mt-14 space-y-8">
|
||||||
<div className="flex flex-wrap items-center gap-3">
|
<div className="flex flex-wrap items-start gap-4">
|
||||||
<span className="flex h-8 w-8 items-center justify-center rounded bg-[#0a0a0a] font-extrabold text-white ring-2 ring-white/20">1</span>
|
<span className="nb-sm flex h-12 w-12 shrink-0 items-center justify-center rounded-xl bg-[#0a0a0a] font-sora text-2xl font-extrabold text-white">1</span>
|
||||||
<h3 className="font-sora text-4xl font-extrabold leading-tight sm:text-5xl">
|
<h3 className="font-sora text-4xl font-extrabold leading-[1.05] tracking-tight sm:text-6xl">
|
||||||
<span className="strike-pink">traditional loyalty</span> begins when you SPEND.
|
<span className="strike-pink">traditional loyalty</span> begins when you <span className="text-[#FFD21E]">SPEND.</span>
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap items-center gap-3">
|
<div className="flex flex-wrap items-start gap-4">
|
||||||
<span className="flex h-8 w-8 items-center justify-center rounded bg-[#C8FF37] font-extrabold text-[#0a0a0a]">2</span>
|
<span className="nb-sm flex h-12 w-12 shrink-0 items-center justify-center rounded-xl bg-[#C8FF37] font-sora text-2xl font-extrabold text-[#0a0a0a]">2</span>
|
||||||
<div className="nb-lg w-full rounded-2xl bg-gradient-to-r from-[#FF2E88] to-[#A020F0] p-6">
|
<div className="nb-lg w-full rounded-3xl bg-gradient-to-r from-[#FF2E88] to-[#A020F0] p-7 sm:p-9">
|
||||||
<h3 className="font-sora text-4xl font-extrabold leading-tight text-white sm:text-5xl">
|
<h3 className="font-sora text-4xl font-extrabold leading-[1.05] tracking-tight text-white sm:text-6xl">
|
||||||
<span className="nb-sm bg-[#C8FF37] px-2 text-[#0a0a0a]">LYTs</span> begins when you ENGAGE.
|
<span className="nb-sm inline-block rounded-lg bg-[#C8FF37] px-3 py-0.5 text-[#0a0a0a]">LYTs</span> begins when you ENGAGE.
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,20 +7,23 @@ import { C } from "./palette";
|
|||||||
|
|
||||||
export { C };
|
export { C };
|
||||||
|
|
||||||
const viewport = { once: true, amount: 0.25 } as const;
|
const viewport = { once: true, amount: 0.2 } as const;
|
||||||
|
|
||||||
|
/* Shared smooth easing — a soft, premium ease-out curve reused across reveals. */
|
||||||
|
const smoothEase = [0.22, 1, 0.36, 1] as const;
|
||||||
|
|
||||||
/* stagger container variants */
|
/* stagger container variants */
|
||||||
export const stagger: Variants = {
|
export const stagger: Variants = {
|
||||||
hidden: {},
|
hidden: {},
|
||||||
show: { transition: { staggerChildren: 0.09, delayChildren: 0.05 } },
|
show: { transition: { staggerChildren: 0.11, delayChildren: 0.06 } },
|
||||||
};
|
};
|
||||||
export const riseItem: Variants = {
|
export const riseItem: Variants = {
|
||||||
hidden: { opacity: 0, y: 30, scale: 0.96 },
|
hidden: { opacity: 0, y: 34, scale: 0.96 },
|
||||||
show: {
|
show: {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
y: 0,
|
y: 0,
|
||||||
scale: 1,
|
scale: 1,
|
||||||
transition: { type: "spring", stiffness: 130, damping: 16 },
|
transition: { duration: 0.7, ease: smoothEase },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -44,7 +47,7 @@ export function Section({ id, children, variant = "deep", className = "" }: Sect
|
|||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
id={id}
|
id={id}
|
||||||
className={`relative flex min-h-screen w-full flex-col justify-center overflow-hidden px-6 py-20 sm:px-10 lg:px-20 ${bg} ${className}`}
|
className={`relative m-5 flex min-h-[calc(100vh-40px)] flex-col justify-center overflow-hidden rounded-[20px] px-6 py-20 sm:px-10 lg:px-20 ${bg} ${className}`}
|
||||||
>
|
>
|
||||||
<div className="mx-auto w-full max-w-6xl">{children}</div>
|
<div className="mx-auto w-full max-w-6xl">{children}</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -69,7 +72,7 @@ export function Reveal({
|
|||||||
initial={{ opacity: 0, y }}
|
initial={{ opacity: 0, y }}
|
||||||
whileInView={{ opacity: 1, y: 0 }}
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
viewport={viewport}
|
viewport={viewport}
|
||||||
transition={{ type: "spring", stiffness: 120, damping: 18, delay }}
|
transition={{ duration: 0.7, ease: smoothEase, delay }}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@@ -109,12 +112,13 @@ export function Pill({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<motion.span
|
<motion.span
|
||||||
className="nb-sm inline-flex items-center gap-2 rounded-full px-4 py-1.5 text-xs font-extrabold uppercase tracking-wide sm:text-sm"
|
className="nb inline-flex items-center gap-2.5 rounded-full px-6 py-3 text-lg font-extrabold uppercase tracking-wide sm:px-8 sm:py-4 sm:text-2xl"
|
||||||
style={{ background: bg, color: text }}
|
style={{ background: bg, color: text }}
|
||||||
initial={{ opacity: 0, scale: 0.8, y: 12 }}
|
initial={{ opacity: 0, scale: 0.8, y: 12 }}
|
||||||
whileInView={{ opacity: 1, scale: 1, y: 0 }}
|
whileInView={{ opacity: 1, scale: 1, y: 0 }}
|
||||||
viewport={viewport}
|
viewport={viewport}
|
||||||
transition={{ type: "spring", stiffness: 320, damping: 15 }}
|
transition={{ type: "spring", stiffness: 320, damping: 15 }}
|
||||||
|
whileHover={{ rotate: -2, scale: 1.04 }}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</motion.span>
|
</motion.span>
|
||||||
@@ -146,7 +150,7 @@ export function Card({
|
|||||||
initial: { opacity: 0, y: 30, scale: 0.96 },
|
initial: { opacity: 0, y: 30, scale: 0.96 },
|
||||||
whileInView: { opacity: 1, y: 0, scale: 1 },
|
whileInView: { opacity: 1, y: 0, scale: 1 },
|
||||||
viewport,
|
viewport,
|
||||||
transition: { type: "spring" as const, stiffness: 130, damping: 16, delay },
|
transition: { duration: 0.7, ease: smoothEase, delay },
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
@@ -206,7 +210,7 @@ export function Heading({
|
|||||||
initial={{ opacity: 0, y: 28 }}
|
initial={{ opacity: 0, y: 28 }}
|
||||||
whileInView={{ opacity: 1, y: 0 }}
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
viewport={viewport}
|
viewport={viewport}
|
||||||
transition={{ type: "spring", stiffness: 120, damping: 18 }}
|
transition={{ duration: 0.75, ease: smoothEase }}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</motion.h2>
|
</motion.h2>
|
||||||
|
|||||||
Reference in New Issue
Block a user