/* global React, ScreenPuzzle, ScreenWelcome, ScreenChooseApp, ScreenUnlock, InteractiveBoard, AppIcon, PieceImage, Chessboard, FORK_POSITION */ const { useState: useStateA, useEffect: useEffectA } = React; const HERO_SCREENS = ['puzzle', 'welcome', 'unlock']; const HERO_LABEL = { puzzle: 'Puzzle gate', welcome: 'Welcome', unlock: 'Unlocked' }; function HeroPhone() { const [idx, setIdx] = useStateA(0); useEffectA(() => { const t = setInterval(() => setIdx(i => (i + 1) % HERO_SCREENS.length), 4200); return () => clearInterval(t); }, []); const screen = HERO_SCREENS[idx]; return (
{/* floaters */}
{screen === 'puzzle' && } {screen === 'welcome' && } {screen === 'unlock' && }
{/* tiny screen-pager dots under the phone */}
{HERO_SCREENS.map((_, i) => (
))}
); } function FloatPiece({ kind = 'P', size = 64 }) { return (
); } // ===================================================================== // SECTIONS // ===================================================================== function HowItWorks() { return (
How it works

One quick tactic. Then you scroll.

Three steps. No nags, no shame, no hidden mode where the app pretends you didn’t open it.

} /> } /> } />
); } function Step({ num, title, body, art }) { return (
{art}
STEP {num}

{title}

{body}

); } function StepArtApps() { return (
); } function StepArtBoard() { return (
); } function StepArtLadder() { const bars = [ { h: 26, label: '+5' }, { h: 46, label: '+5' }, { h: 74, label: '+7' }, ]; return (
{bars.map((b, i) => (
{b.label}
))}
); } function DemoSection() { return (
Try it now

This is what your phone hands you instead.

White to move. Your knight is sitting on e5. There’s a square that wins material on the spot. Find it, and you’d earn five minutes in the real app.

  • Puzzles scale to your rating — no mate-in-one if you’re strong.
  • Hints exist, but they cost you reward time.
  • Solving more makes the next puzzle harder — and worth more.
); } function Check() { return ( ); } function BlocksSection() { const apps = [ { kind: 'ig', name: 'Instagram' }, { kind: 'tt', name: 'TikTok' }, ]; return (
What it gates

Two apps to start. More on the way.

{apps.map(a => (
{a.name}
))}
More
soon
); } function FAQ() { const items = [ { q: 'I’m bad at chess. Does this just lock me out forever?', a: 'No. The first thing you do is pick your level. If you’re new, the puzzles are very gentle — think "the queen takes the free piece." The point is to make you pause and think, not to humiliate you.', }, { q: 'What if I genuinely need to open Instagram right now?', a: 'Tap "Give up." You’ll get a one-time short pass, but no scroll reward. Most people find they didn’t actually need the app that badly. The rest get to skip the puzzle when it matters.', }, { q: 'How is this different from a normal app blocker?', a: 'App blockers say no. Scroll Gambit says "earn it." That tiny shift — from punishment to a small game — is the whole point. You feel like you won something instead of feeling lectured.', }, { q: 'Will I actually get better at chess?', a: 'Probably, yeah. You’ll see hundreds of tactical patterns. We track your rating gently in the background so puzzles stay challenging without becoming impossible.', }, { q: 'Can I be in early access?', a: 'Drop your email at the top. iOS beta starts soon.', }, ]; const [open, setOpen] = useStateA(0); return (
Questions

Reasonable concerns,
answered.

{items.map((it, i) => (
setOpen(open === i ? -1 : i)}> {it.q}

{it.a}

))}
); } function SignupForm({ size = 'normal' }) { const [email, setEmail] = useStateA(''); const [sent, setSent] = useStateA(false); const [sending, setSending] = useStateA(false); const [error, setError] = useStateA(null); async function submit(e) { e.preventDefault(); if (!email || !email.includes('@') || sending) return; setSending(true); setError(null); try { const base = (typeof window !== 'undefined' && window.__API_BASE) || ''; const r = await fetch(`${base}/api/waitlist`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, source: 'landing' }), }); const body = await r.json().catch(() => ({})); if (!r.ok || !body.ok) { if (body.error === 'invalid_email') { setError('That email doesn’t look right.'); } else if (body.error === 'rate_limited') { setError('Too many tries. Wait a minute and retry.'); } else { setError('Something went wrong. Try again?'); } return; } setSent(true); setEmail(''); } catch { setError('Couldn’t reach the server. Try again?'); } finally { setSending(false); } } if (sent) { return (
You’re on the list. We’ll be in touch.
); } return (
setEmail(e.target.value)} disabled={sending} />
{error && (
{error}
)}
); } function Hero() { return (
iOS beta — invites going out weekly

Solve a chess
puzzle before

you scroll.

Scroll Gambit puts a quick tactic between you and Instagram. Crack it, earn five minutes. Skip it, miss the scroll. No nagging, no shame — just a small, clever obstacle.

2,847 on the waitlist
); } function CTAStrip() { return (

Solve. Scroll. Repeat.

The whole product is one screen. Get the email when it ships.

); } function Nav() { return ( ); } function Footer() { return ( ); } function Landing() { return (
); } Object.assign(window, { Landing });