feat: update story sections, header, footer, styles, and add gsapkit component
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import Link from 'next/link';
|
||||
import Image from 'next/image';
|
||||
import { gsap, useGSAP, syncLenisScrollTrigger } from '../story/gsapkit';
|
||||
|
||||
const INK = '#0a0a0a';
|
||||
const BLUE = '#2F6BFF';
|
||||
|
||||
const NAV = [
|
||||
{
|
||||
@@ -51,8 +53,20 @@ const SOCIALS = [
|
||||
},
|
||||
];
|
||||
|
||||
/* Kinetic ticker phrases + the giant wordmark letters */
|
||||
const TICKER = ['Earn', 'Spend', 'Live More', 'Make Everyday Count', 'Join The Loop', 'Real Value'];
|
||||
|
||||
function Star({ size = 22, color = INK }: { size?: number; color?: string }) {
|
||||
return (
|
||||
<svg width={size} height={size} viewBox="0 0 24 24" fill={color} aria-hidden="true" style={{ flexShrink: 0 }}>
|
||||
<path d="M12 0l2.5 8.2L22 6l-5.4 6.2L22 18l-7.5-2.2L12 24l-2.5-8.2L2 18l5.4-6.2L2 6l7.5 2.2z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Footer() {
|
||||
const [showScroll, setShowScroll] = useState(false);
|
||||
const rootRef = useRef<HTMLElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const onScroll = () => setShowScroll(window.scrollY > 400);
|
||||
@@ -60,46 +74,82 @@ export default function Footer() {
|
||||
return () => window.removeEventListener('scroll', onScroll);
|
||||
}, []);
|
||||
|
||||
useGSAP(
|
||||
() => {
|
||||
syncLenisScrollTrigger();
|
||||
const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
|
||||
// Infinite marquee ticker (two identical halves → seamless).
|
||||
if (!reduce) {
|
||||
gsap.to('.foot-ticker-track', { xPercent: -50, duration: 22, ease: 'none', repeat: -1 });
|
||||
gsap.to('.foot-cta-star', { rotate: 360, duration: 9, ease: 'none', repeat: -1 });
|
||||
}
|
||||
},
|
||||
{ scope: rootRef },
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<footer className="lu-footer bg-night font-sora" style={{
|
||||
color: '#fff',
|
||||
<footer ref={rootRef} className="lu-footer font-sora" style={{
|
||||
background: '#FFFDF5',
|
||||
color: INK,
|
||||
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)`,
|
||||
boxShadow: '0 12px 0 0 rgba(0,0,0,0.35)',
|
||||
}}>
|
||||
{/* ── KINETIC TICKER STRIP ── */}
|
||||
<div className="foot-ticker" style={{
|
||||
overflow: 'hidden',
|
||||
background: '#C8FF37',
|
||||
borderBottom: `4px solid ${INK}`,
|
||||
}}>
|
||||
<div className="foot-ticker-track" style={{ display: 'flex', width: 'max-content', willChange: 'transform' }}>
|
||||
{[0, 1].map((half) => (
|
||||
<div key={half} aria-hidden={half === 1} style={{ display: 'flex', alignItems: 'center' }}>
|
||||
{TICKER.map((t, i) => (
|
||||
<span key={`${half}-${i}`} style={{ display: 'inline-flex', alignItems: 'center', gap: 22, padding: '13px 22px' }}>
|
||||
<span style={{ fontSize: 'clamp(18px, 2.4vw, 30px)', fontWeight: 900, textTransform: 'uppercase', letterSpacing: '-0.01em', color: INK, whiteSpace: 'nowrap' }}>{t}</span>
|
||||
<Star size={20} />
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ── BIG CTA STICKER CARD ── */}
|
||||
<div className="lu-cta-wrap" style={{ padding: '56px 48px 40px' }}>
|
||||
<div className="lu-cta bg-cream" style={{
|
||||
<div className="lu-cta" style={{
|
||||
position: 'relative',
|
||||
color: INK,
|
||||
background: BLUE,
|
||||
color: '#fff',
|
||||
border: `4px solid ${INK}`,
|
||||
borderRadius: 24,
|
||||
boxShadow: `8px 8px 0 0 ${INK}`,
|
||||
padding: '44px 48px',
|
||||
padding: '48px 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>
|
||||
{/* rotating star sticker */}
|
||||
<span className="foot-cta-star" aria-hidden style={{ position: 'absolute', top: -20, right: 30, willChange: 'transform' }}>
|
||||
<span style={{ display: 'inline-flex', background: '#FF2E88', border: `3px solid ${INK}`, borderRadius: '50%', padding: 10, boxShadow: `3px 3px 0 0 ${INK}` }}>
|
||||
<Star size={22} color="#fff" />
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<div style={{ maxWidth: 620 }}>
|
||||
<div style={{ maxWidth: 640 }}>
|
||||
<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}` }}>
|
||||
Earn. Spend. Live More.
|
||||
</span>
|
||||
<h2 className="lu-cta-heading" style={{ fontSize: 'clamp(32px, 4.6vw, 60px)', fontWeight: 800, letterSpacing: '-0.03em', lineHeight: 0.98, margin: 0 }}>
|
||||
<h2 className="lu-cta-heading" style={{ fontSize: 'clamp(32px, 4.8vw, 62px)', fontWeight: 800, letterSpacing: '-0.03em', lineHeight: 0.96, margin: 0 }}>
|
||||
Turn everyday moments<br />
|
||||
<span style={{ position: 'relative', display: 'inline-block' }}>
|
||||
into <span style={{ color: '#FF2E88' }}>real value.</span>
|
||||
into <span style={{ position: 'relative', display: 'inline-block', color: '#FF2E88' }}>
|
||||
real value.
|
||||
<span aria-hidden style={{ position: 'absolute', left: 0, right: 0, bottom: 4, height: 6, background: '#C8FF37', zIndex: -1, borderRadius: 4 }} />
|
||||
</span>
|
||||
</h2>
|
||||
</div>
|
||||
@@ -112,7 +162,7 @@ export default function Footer() {
|
||||
boxShadow: `5px 5px 0 0 ${INK}`, whiteSpace: 'nowrap',
|
||||
transition: 'transform 0.12s ease, box-shadow 0.12s ease',
|
||||
}}>
|
||||
Get Started
|
||||
Download Now
|
||||
<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>
|
||||
</div>
|
||||
@@ -122,20 +172,18 @@ export default function Footer() {
|
||||
<div className="lu-columns" style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: '1.6fr 1fr 1fr 1fr',
|
||||
gap: 40, padding: '24px 48px 44px',
|
||||
gap: 40, padding: '24px 48px 36px',
|
||||
alignItems: 'start',
|
||||
}}>
|
||||
{/* Brand */}
|
||||
<div className="lu-brand" style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start' }}>
|
||||
<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}`,
|
||||
display: 'inline-flex', marginBottom: 22, textDecoration: 'none',
|
||||
}}>
|
||||
<Image src="/images/lytsup_app.png" alt="LytsUp" width={2048} height={554} style={{ height: 30, width: 'auto', display: 'block' }} />
|
||||
<Image src="/images/lytsup_app.png" alt="LytsUp" width={2048} height={554} style={{ height: 52, 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 style={{ fontSize: 15, lineHeight: 1.6, color: 'rgba(10,10,10,0.6)', margin: '0 0 24px', maxWidth: 300 }}>
|
||||
Offline shopping. Online intelligence.
|
||||
</p>
|
||||
<div style={{ display: 'flex', gap: 12 }}>
|
||||
{SOCIALS.map(({ label, href, icon, bg }) => (
|
||||
@@ -162,9 +210,9 @@ export default function Footer() {
|
||||
<ul style={{ listStyle: 'none', margin: 0, padding: 0, display: 'flex', flexDirection: 'column', gap: 12 }}>
|
||||
{col.links.map(({ label, href }) => (
|
||||
<li key={label}>
|
||||
<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' }}
|
||||
onMouseEnter={e => { const el = e.currentTarget as HTMLElement; el.style.color = col.color; el.style.transform = 'translateX(4px)'; }}
|
||||
onMouseLeave={e => { const el = e.currentTarget as HTMLElement; el.style.color = 'rgba(255,255,255,0.65)'; el.style.transform = 'translateX(0)'; }}
|
||||
<Link href={href} className="lu-link" style={{ textDecoration: 'none', fontSize: 15, color: 'rgba(10,10,10,0.62)', fontWeight: 600, transition: 'color 0.15s, transform 0.15s', display: 'inline-block' }}
|
||||
onMouseEnter={e => { const el = e.currentTarget as HTMLElement; el.style.color = INK; el.style.transform = 'translateX(4px)'; }}
|
||||
onMouseLeave={e => { const el = e.currentTarget as HTMLElement; el.style.color = 'rgba(10,10,10,0.62)'; el.style.transform = 'translateX(0)'; }}
|
||||
>{label}</Link>
|
||||
</li>
|
||||
))}
|
||||
@@ -178,8 +226,8 @@ export default function Footer() {
|
||||
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)',
|
||||
borderTop: '2px dashed rgba(10,10,10,0.2)',
|
||||
fontSize: 13, color: 'rgba(10,10,10,0.55)',
|
||||
}}>
|
||||
<span style={{ display: 'inline-flex', alignItems: 'center', gap: 8, fontWeight: 600 }}>
|
||||
© {new Date().getFullYear()} LytsUp. Made with
|
||||
@@ -188,8 +236,8 @@ export default function Footer() {
|
||||
<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)')}
|
||||
onMouseEnter={e => ((e.currentTarget as HTMLElement).style.color = INK)}
|
||||
onMouseLeave={e => ((e.currentTarget as HTMLElement).style.color = 'rgba(10,10,10,0.55)')}
|
||||
>{l}</Link>
|
||||
))}
|
||||
</div>
|
||||
@@ -203,7 +251,7 @@ export default function Footer() {
|
||||
.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-columns { grid-template-columns: 1fr 1fr !important; gap: 32px 24px !important; padding: 16px 24px 28px !important; }
|
||||
.lu-brand { grid-column: 1 / -1; }
|
||||
.lu-bottom { padding: 18px 24px 26px !important; flex-direction: column !important; align-items: flex-start !important; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user