// chrome.jsx — shared site chrome (nav, footer, ambient layers, page wrapper)
// for every adult-side page. Uses CSS vars for theming.
const { useState: useStateChr, useEffect: useEffectChr, useRef: useRefChr } = React;
// ──────────────────────────────────────────────────────────────────────
// PageShell — sets up the dark/light mode, ambient layers, mounts nav +
// footer + mascot peeks + scroll reveal.
//
//
// ...content
//
// ──────────────────────────────────────────────────────────────────────
function PageShell({ active = 'home', dark = false, children, hideNav = false, footer = true }){
const rootRef = useRefChr(null);
useReveal(rootRef);
const [secret, setSecret] = useStateChr(false);
return (
{/* Ambient background pieces */}
{!hideNav &&
{
setSecret(true);
setTimeout(() => setSecret(false), 2400);
}} />}
{children}
{footer && }
{secret && (
♟ → 🐆 — you've unlocked nothing, but Amigo saw you
)}
);
}
// ──────────────────────────────────────────────────────────────────────
// SiteNav — sticky pill nav with dark/light awareness
// ──────────────────────────────────────────────────────────────────────
function SiteNav({ active = 'home', dark = false, onSecret }){
const links = [
{ id:'home', label:'Home', href:'index.html' },
{ id:'training', label:'Training', href:'training.html' },
{ id:'play', label:'Play Maia', href:'play.html' },
{ id:'analysis', label:'Analysis', href:'analysis.html' },
{ id:'kids', label:'Kids', href:'kids.html' },
{ id:'pricing', label:'Pricing', href:'pricing.html' },
];
const navBg = dark ? 'rgba(20,16,12,.72)' : 'rgba(255,250,242,.86)';
const navBorder = dark ? 'rgba(255,243,217,.18)' : 'var(--line-strong)';
const linkColor = dark ? 'rgba(255,247,230,.7)' : 'var(--ink-soft)';
return (
);
}
// ──────────────────────────────────────────────────────────────────────
// SiteFooter — editorial colophon
// ──────────────────────────────────────────────────────────────────────
function SiteFooter({ dark = false }){
const muted = dark ? 'rgba(255,247,230,.5)' : 'var(--ink-muted)';
const text = dark ? 'rgba(255,247,230,.8)' : 'var(--ink-soft)';
const border = dark ? 'rgba(255,247,230,.12)' : 'var(--line-strong)';
const hover = dark ? '#fff7e6' : 'var(--ink)';
const sections = [
{ h:'Product', links:[
['Training', 'training.html'],
['Play Maia', 'play.html'],
['Analysis', 'analysis.html'],
['Kids', 'kids.html'],
['Pricing', 'pricing.html'],
] },
{ h:'Exercises', links:[
['Square Color', 'exercises/square-color.html'],
['Tap the Square', 'exercises/tap-square.html'],
['Knight Pathfinder', 'exercises/knight-pathfinder.html'],
['Position Memory', 'exercises/position-memory.html'],
['Notation', 'exercises/notation.html'],
['Blind Tactics', 'exercises/blind-tactics.html'],
['Blindfold', 'exercises/blindfold.html'],
] },
{ h:'Pawnther', links:[
['Join waitlist', 'pricing.html'],
['support@pawntherchess.com','mailto:support@pawntherchess.com'],
['About', 'about.html'],
] },
];
return (
);
}
// ──────────────────────────────────────────────────────────────────────
// AmbientPieces — drifting chess piece silhouettes for the page background
// ──────────────────────────────────────────────────────────────────────
function AmbientPieces({ dark = false }){
// Static placement, but each piece has its own pwBgFloat animation
const pieces = [
{ glyph:'♞', x:'8%', y:'14%', size: 92, rot: -8, dur: 24 },
{ glyph:'♛', x:'78%', y:'22%', size: 84, rot: 6, dur: 28 },
{ glyph:'♟', x:'12%', y:'62%', size: 64, rot: 12, dur: 18 },
{ glyph:'♝', x:'88%', y:'76%', size: 72, rot: -6, dur: 22 },
{ glyph:'♜', x:'42%', y:'92%', size: 68, rot: 3, dur: 26 },
];
const col = dark ? 'rgba(255,247,230,.06)' : 'rgba(25,23,20,.05)';
return (
{pieces.map((p, i) => (
{p.glyph}
))}
);
}
// ──────────────────────────────────────────────────────────────────────
// CinematicHero — the locked direction's hero treatment
// ──────────────────────────────────────────────────────────────────────
function CinematicHero({ children, height = 'auto' }){
return (
);
}
// ──────────────────────────────────────────────────────────────────────
// Folio — eyebrow text with line accent
// ──────────────────────────────────────────────────────────────────────
function Folio({ children, dark = false }){
return (
{children}
);
}
// ──────────────────────────────────────────────────────────────────────
// Kicker — orange eyebrow used in section heads
// ──────────────────────────────────────────────────────────────────────
function Kicker({ children, color = 'var(--gold)' }){
return (
{children}
);
}
// ──────────────────────────────────────────────────────────────────────
// CTAButton — primary CTA, theme aware
// ──────────────────────────────────────────────────────────────────────
function CTAButton({ children, variant = 'gold', size = 'md', ...rest }){
const sizes = {
md: { padding: '12px 18px', fontSize: 13.5 },
lg: { padding: '14px 22px', fontSize: 14 },
};
const variants = {
gold: { background:'var(--gold)', color:'#1a120a', shadow:'0 12px 30px -10px rgba(227,155,68,.5)' },
ink: { background:'var(--ink)', color:'var(--paper-100)', shadow:'0 8px 22px -12px rgba(0,0,0,.45)' },
ghost: { background:'rgba(255,253,248,.7)', color:'var(--ink)', shadow:'none', border:'1px solid var(--line)' },
dark: { background:'rgba(255,247,230,.07)', color:'#fff7e6', shadow:'none', border:'1px solid rgba(255,247,230,.2)' },
};
const v = variants[variant];
return (
);
}
Object.assign(window, {
PageShell, SiteNav, SiteFooter, AmbientPieces,
CinematicHero, Folio, Kicker, CTAButton,
});