// pages/home.jsx — the locked marketing home for Pawnther adults. // B (cinematic hero, panther eyes, paper intermissions, mascot peeks) // + C (instrument panel: brass gauges, eval bar, sparkline, Maia rating dial). const { useState: useSH, useEffect: useEH, useRef: useRH } = React; function HomePage(){ const [dark, setDark] = useSH(false); return ( ); } // ────────────────────────────────────────────────────────────────────── function DarkToggle({ dark, setDark }){ return ( ); } // ────────────────────────────────────────────────────────────────────── function HeroBlock({ dark }){ return (
VOL. I · NO. 01 · TRAINING FOR THE HUNT

Hunt your
blunders

Start the hunt Meet Maia ♛
{/* Hero meta strip with bullet dots */}
{['Adult MVP', 'Maia 2 sparring', 'Practical, not theoretical', 'Android first'].map(t => ( {t} ))}
{/* Floating board with eval bar + move list + idea */}
); } function ScrambleLede(){ const text = "Theory is the easy part. The hard part is seeing the board — the squares, the lines, the two moves you can't calculate before you blunder."; const [out, setOut] = useSH(''); const ref = useRH(null); useEH(() => { if (!ref.current) return; const io = new IntersectionObserver(([e]) => { if (e.isIntersecting){ io.disconnect(); const chars = "abcdefgh12345678NBRQKpx+ "; let i = 0; const reveal = () => { if (i >= text.length) return; const scram = text.slice(0, i) + Array.from({ length: Math.min(8, text.length - i) }, () => chars[Math.floor(Math.random() * chars.length)]).join(''); setOut(scram); i += 1; setTimeout(reveal, 22); }; reveal(); } }, { threshold: .3 }); io.observe(ref.current); return () => io.disconnect(); }, []); return (

{out || text}

); } // ────────────────────────────────────────────────────────────────────── function MarqueeLines(){ const items = [ ['Najdorf Sicilian', '1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 a6'], ['Ruy López, Berlin', '1.e4 e5 2.Nf3 Nc6 3.Bb5 Nf6 4.O-O Nxe4'], ["Queen's Gambit Declined", '1.d4 d5 2.c4 e6 3.Nc3 Nf6 4.Bg5 Be7'], ['Caro–Kann, Advance', '1.e4 c6 2.d4 d5 3.e5 Bf5'], ["King's Indian", '1.d4 Nf6 2.c4 g6 3.Nc3 Bg7 4.e4 d6'], ['Italian, Giuoco Pianissimo', '1.e4 e5 2.Nf3 Nc6 3.Bc4 Bc5 4.d3 Nf6'], ]; return (
{[...items, ...items].map(([name, moves], i) => ( {name} {moves} ))}
); } // ────────────────────────────────────────────────────────────────────── function ProblemSpread(){ return (
The problem

Apps overfeed theory and
underfeed sight.

Most platforms drown you in puzzles and openings while quietly avoiding the skills that actually decide club games — calculation, board geometry, and not blundering a piece on move 18.

); } function ComparisonCard({ variant, tag, items }){ const isBad = variant === 'bad'; return (
{tag}
); } // ────────────────────────────────────────────────────────────────────── // Three acts: SEE, CALCULATE, POUNCE — paper / dark / paper cinematic flow // ────────────────────────────────────────────────────────────────────── function ThreeActs(){ return ( <> ); } function SeeAct(){ const cards = [ { title:'Square Color', accent:'gold', icon:, desc:'Name the colour of any square instantly. Geometry internalised.' }, { title:'Tap the Square', accent:'blue', icon:, desc:'Hear a coordinate, find the square. Fluent coordinates.' }, { title:'Knight Pathfinder', accent:'olive', icon:, desc:'Walk the knight to the king via a legal path.' }, { title:'Position Memory', accent:'rose', icon:, desc:'Study, hide, recall. Mental board control.' }, ]; return (
01 — See

Before you can
calculate, you have
to see.

Four exercises that build coordinate fluency, board geometry, and mental control of squares the engine can't help you see.

{cards.map((c, i) => ( ))}
); } function CalculateAct(){ return (
02 — Calculate

Three clean moves
without losing
the line.

Notation, Blind Tactics, Blindfold. The drills that turn sight into calculation under pressure.

{[ { num:'05', title:'Notation', desc:'Read a game in algebraic. Hear "Nf3 e5 Bc4" and see the board, not the pieces.' }, { num:'06', title:'Blind Tactics', desc:'Solve a tactic from a position you only saw briefly. Calculation under pressure.' }, { num:'07', title:'Blindfold', desc:'Play a full game without seeing the pieces. The end-state of visualisation.' }, ].map((r, i) => ( EX·{r.num}
{r.title}
{r.desc}
))}
); } function PounceAct(){ return (
03 — Pounce

Beat a human-like
opponent.
Maia plays like Maia.

Maia is trained on millions of human games. She plays the moves a player at your ELO would actually play — including the mistakes. Beat her, and you've beaten a believable opponent.

Read about Maia Play vs Maia 1500
); } function MaiaPortraitCard(){ return (
Opponent · profile

Maia

Adjustable rating: 200 → 2000+

); } // ────────────────────────────────────────────────────────────────────── // INSTRUMENT ROW — the Codex panel, restyled as a "what you'll see when // you train" section. // ────────────────────────────────────────────────────────────────────── function InstrumentRow(){ return (
Your instruments

A reading room for
your sight.

Every session updates your instruments. Read them together — weakness, progress, and the right drill to do next at a glance.

1442 est. board-vision rating, last 14 sessions
{['M','T','W','T','F','S','S','M','T','W','T','F','S','S'].map((d,i) => {d})}

Stockfish breathes here — depth 22 in your last position.

Maia · dial ● 1700
); } // ────────────────────────────────────────────────────────────────────── // SPARRING PANEL — last-game review (carried from Hunt direction) // ────────────────────────────────────────────────────────────────────── function SparringPanel(){ return (
Last game · sparring

A review that
names what you did.

Load your last game from PGN or paste a FEN. Pawnther classifies every move, finds the recurring patterns, and queues the right drill.

    {['Stockfish-backed move classification, with a human reason.', 'Pattern notes that find the habit, not the move.', 'Every weakness feeds the next training set.'].map(t => (
  • {t}
  • ))}
Open analysis →
Sparring · last game ♛ Maia 1700
Result · loss in 34 moves
Knight dropped on move 18
After 17.Qxd5 you walked into a fork on c7.
{[ ['d6', 56, 'var(--gold)', 'Best · solid'], ['Nc6', 29, 'var(--blue)', 'Sound'], ['e6', 18, 'var(--rose)', 'Inaccuracy'], ].map(([sq, pct, col, note]) => (
{sq} {note} {pct}%
))}
Recommended drill
Knight forks after queen trades · 6 min
); } // ────────────────────────────────────────────────────────────────────── function PricingPreview(){ return (
Pricing

Free is real. Paid is honest.

Free covers all seven exercises with daily caps and unranked Maia sparring. Pro removes caps and funds the heavier review features.

Free · trainer

Trainer

€0 / forever
    {['Daily caps: 3 beginner sets, 2 intermediate, 1 advanced', 'Maia 2 sparring with adjustable rating', 'Opening tree (read-only)', 'Basic analysis on last 3 games'].map(t => (
  • {t}
  • ))}
Start free
Most loved Pro

Pawnther Pro

€4.99 / mo · yearly
    {['Everything in Trainer, unlimited', 'Maia 2 line play and memory modes as they land', 'Opening Improver + Remember-the-Line', 'Deeper Stockfish review and pattern notes', 'Cloud sync across devices'].map(t => (
  • {t}
  • ))}
See Pro →
); } // ────────────────────────────────────────────────────────────────────── function FinalCTA(){ return (
Early access

Join the hunt.
Train to see.

Android first — iOS coming after launch. One free Pro month for early joiners.

{ e.preventDefault(); e.currentTarget.querySelector('button').textContent='Saved ✓'; }} style={{ display:'flex', gap: 6, padding: 6, borderRadius: 999, background:'rgba(255,255,255,.08)', border:'1px solid rgba(255,255,255,.2)', minWidth: 360, }}>
); } // ────────────────────────────────────────────────────────────────────── function FCard({ accent, icon, title, desc, delay }){ const colors = { gold: ['rgba(227,155,68,.16)', 'var(--gold)'], olive: ['rgba(141,152,112,.16)', 'var(--olive)'], blue: ['rgba(110,138,160,.16)', 'var(--blue)'], rose: ['rgba(183,122,134,.16)', 'var(--rose)'], }[accent]; return (
{icon}

{title}

{desc}

); } function Ic({ name }){ const c = { stroke:'currentColor', strokeWidth: 2, strokeLinecap:'round', strokeLinejoin:'round', fill:'none' }; const map = { grid: , target: , knight: , memory: , }; return map[name] || null; } Object.assign(window, { HomePage });