Sessions 5-7a: 955 tests, deployment ready
This commit is contained in:
+136
-50
@@ -1,62 +1,148 @@
|
||||
'use client';
|
||||
const PRIMARY_LINKS = [
|
||||
{ label: 'Read', href: '/scan' },
|
||||
{ label: 'Tracker', href: '/tracker' },
|
||||
{ label: 'Ledger', href: '/ledger' },
|
||||
{ label: 'Pricing', href: '/#pricing' },
|
||||
{ label: 'Blog', href: '/blog' },
|
||||
];
|
||||
|
||||
import { useState } from 'react';
|
||||
const LEGAL_LINKS = [
|
||||
{ label: 'Terms', href: '/terms' },
|
||||
{ label: 'Privacy', href: '/privacy' },
|
||||
{ label: 'Responsible Gambling', href: '/responsible-gambling' },
|
||||
];
|
||||
|
||||
import Wordmark from '@/components/Wordmark';
|
||||
|
||||
const SOCIAL = [
|
||||
{ label: 'Twitter', href: 'https://twitter.com/getvyndr' },
|
||||
{ label: 'Discord', href: 'https://discord.gg/getvyndr' },
|
||||
];
|
||||
|
||||
export default function Footer() {
|
||||
const [email, setEmail] = useState('');
|
||||
const [submitted, setSubmitted] = useState(false);
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
// TODO: Store email in Supabase
|
||||
setSubmitted(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<footer className="py-16 px-4 border-t border-[var(--border)]">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<div className="grid md:grid-cols-2 gap-12 mb-12">
|
||||
<div>
|
||||
<h3 className="font-mono font-bold text-lg mb-2">
|
||||
Beton<span className="text-[var(--accent)]">BLK</span>
|
||||
</h3>
|
||||
<p className="text-sm text-[var(--text-muted)] max-w-sm">
|
||||
AI-powered parlay intelligence. Built by bettors, for bettors.
|
||||
<footer
|
||||
style={{
|
||||
borderTop: '1px solid var(--border)',
|
||||
padding: '64px 24px 32px',
|
||||
marginTop: 64,
|
||||
}}
|
||||
>
|
||||
<div style={{ maxWidth: 1200, margin: '0 auto' }}>
|
||||
<div
|
||||
style={{
|
||||
display: 'grid',
|
||||
gap: 48,
|
||||
marginBottom: 48,
|
||||
}}
|
||||
className="footer-top"
|
||||
>
|
||||
<div style={{ maxWidth: 400 }}>
|
||||
<a
|
||||
href="/"
|
||||
style={{ color: 'var(--text-0)', textDecoration: 'none', display: 'inline-flex', alignItems: 'center' }}
|
||||
aria-label="VYNDR — home"
|
||||
>
|
||||
<Wordmark size={24} />
|
||||
</a>
|
||||
<p
|
||||
style={{
|
||||
marginTop: 12,
|
||||
fontSize: 14,
|
||||
color: 'var(--text-secondary)',
|
||||
lineHeight: 1.6,
|
||||
}}
|
||||
>
|
||||
The books have every advantage. We built this to give it back.
|
||||
</p>
|
||||
<p className="mono" style={{ marginTop: 16, fontSize: 12, color: 'var(--text-tertiary)' }}>
|
||||
Built in Detroit.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold mb-3">Get early access + founder pricing</h4>
|
||||
{submitted ? (
|
||||
<p className="text-[var(--grade-a)] text-sm">You're in. We'll be in touch.</p>
|
||||
) : (
|
||||
<form onSubmit={handleSubmit} className="flex gap-2">
|
||||
<input
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="your@email.com"
|
||||
required
|
||||
className="flex-1 px-4 py-2 rounded-lg bg-[var(--card)] border border-[var(--border)] text-sm text-white placeholder:text-[var(--text-muted)] focus:outline-none focus:border-[var(--accent)]"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className="px-6 py-2 bg-[var(--accent)] text-white rounded-lg text-sm font-medium hover:opacity-90 transition"
|
||||
>
|
||||
Join
|
||||
</button>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<FooterColumn title="Product" links={PRIMARY_LINKS} />
|
||||
<FooterColumn title="Legal" links={LEGAL_LINKS} />
|
||||
<FooterColumn title="Community" links={SOCIAL} external />
|
||||
</div>
|
||||
<div className="flex justify-between items-center text-xs text-[var(--text-muted)] border-t border-[var(--border)] pt-6">
|
||||
<span>2026 BetonBLK. All rights reserved.</span>
|
||||
<div className="flex gap-4">
|
||||
<a href="#" className="hover:text-white transition">Terms</a>
|
||||
<a href="#" className="hover:text-white transition">Privacy</a>
|
||||
<a href="#" className="hover:text-white transition">Twitter/X</a>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
borderTop: '1px solid var(--border)',
|
||||
paddingTop: 24,
|
||||
display: 'grid',
|
||||
gap: 16,
|
||||
}}
|
||||
>
|
||||
<p style={{ fontSize: 12, color: 'var(--text-tertiary)', lineHeight: 1.6 }}>
|
||||
VYNDR is an analytics tool, not a sportsbook. We don't accept wagers. Gamble responsibly.
|
||||
If you or someone you know has a gambling problem, call <strong style={{ color: 'var(--text-secondary)' }}>1-800-522-4700</strong>{' '}
|
||||
or visit <a href="https://www.ncpgambling.org" target="_blank" rel="noopener noreferrer" style={{ color: 'var(--grade-a)' }}>ncpgambling.org</a>.
|
||||
</p>
|
||||
<p className="mono" style={{ fontSize: 11, color: 'var(--text-tertiary)' }}>
|
||||
© 2026 VYNDR. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style jsx>{`
|
||||
:global(.footer-top) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
:global(.footer-top) {
|
||||
grid-template-columns: 2fr 1fr 1fr 1fr;
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
function FooterColumn({
|
||||
title,
|
||||
links,
|
||||
external,
|
||||
}: {
|
||||
title: string;
|
||||
links: { label: string; href: string }[];
|
||||
external?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<div>
|
||||
<h4
|
||||
className="mono"
|
||||
style={{
|
||||
fontSize: 11,
|
||||
fontWeight: 700,
|
||||
letterSpacing: '0.08em',
|
||||
textTransform: 'uppercase',
|
||||
color: 'var(--text-tertiary)',
|
||||
marginBottom: 16,
|
||||
}}
|
||||
>
|
||||
{title}
|
||||
</h4>
|
||||
<ul style={{ display: 'grid', gap: 8 }}>
|
||||
{links.map((l) => (
|
||||
<li key={l.label}>
|
||||
<a
|
||||
href={l.href}
|
||||
target={external ? '_blank' : undefined}
|
||||
rel={external ? 'noopener noreferrer' : undefined}
|
||||
style={{
|
||||
color: 'var(--text-secondary)',
|
||||
textDecoration: 'none',
|
||||
fontSize: 14,
|
||||
transition: 'color 200ms ease',
|
||||
}}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.color = 'var(--text-primary)')}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.color = 'var(--text-secondary)')}
|
||||
>
|
||||
{l.label}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user