/* chrome.jsx — Top status bar, Nav, Sticky Bottom CTA, Sales Notification */ const NAMES_POOL = [ /* ── USA ~75% ── */ ["Emma", "Austin, TX"], ["Jessica", "Miami, FL"], ["James", "Brooklyn, NY"], ["Olivia", "Los Angeles, CA"], ["Noah", "Chicago, IL"], ["Ava", "Houston, TX"], ["Liam", "Phoenix, AZ"], ["Sophia", "San Diego, CA"], ["Mason", "Dallas, TX"], ["Isabella", "Nashville, TN"], ["Logan", "Denver, CO"], ["Mia", "Seattle, WA"], ["Ethan", "Portland, OR"], ["Charlotte", "Atlanta, GA"], ["Aiden", "Boston, MA"], ["Amelia", "San Francisco, CA"], ["Lucas", "Charlotte, NC"], ["Harper", "Minneapolis, MN"], ["Jackson", "Philadelphia, PA"], ["Evelyn", "San Antonio, TX"], ["Carter", "Orlando, FL"], ["Abigail", "Columbus, OH"], ["Elijah", "Las Vegas, NV"], ["Emily", "Washington, DC"], ["Caleb", "Salt Lake City, UT"], ["Scarlett", "Raleigh, NC"], ["Ryan", "Tampa, FL"], ["Grace", "Kansas City, MO"], ["Hunter", "Sacramento, CA"], ["Lily", "Pittsburgh, PA"], ["Tyler", "Richmond, VA"], ["Chloe", "Scottsdale, AZ"], ["Wyatt", "Indianapolis, IN"], ["Nora", "Louisville, KY"], ["Jayden", "New Orleans, LA"], ["Zoe", "Boise, ID"], ["David & Lara", "Austin, TX"], ["Mike & Sara", "Denver, CO"], ["Tom & Amy", "Chicago, IL"], /* ── International ~25% ── */ ["Sarah", "Manchester, UK"], ["Hannah", "Dublin, IE"], ["Liam", "Toronto, ON"], ["Priya", "London, UK"], ["Marcus", "Berlin, DE"], ["Isla", "Sydney, AU"], ["Daniel", "Lyon, FR"], ["Aria", "Oslo, NO"], ["Sofia", "Amsterdam, NL"], ["Chloe", "Wellington, NZ"], ["Lucas", "São Paulo, BR"], ["Anya", "Edinburgh, UK"], ]; const TIMESTAMPS = ["just now", "1 min ago", "3 min ago", "5 min ago", "8 min ago", "12 min ago"]; function _rand(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } function _randItem(arr, exclude) { let pick = arr[_rand(0, arr.length - 1)]; let guard = 0; while (exclude && pick === exclude && guard++ < 8) pick = arr[_rand(0, arr.length - 1)]; return pick; } /* ===== Counter context (now with shared lastSale so ticker + popup stay in sync) ===== */ const LAUNCH_TOTAL = 1000; const MIN_COPIES_LO = 400; const MIN_COPIES_HI = 500; function _dayKey() { const d = new Date(); return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`; } function _msUntilNextMidnight() { const now = new Date(); const next = new Date(now); next.setHours(24, 0, 0, 0); return Math.max(1000, next.getTime() - now.getTime()); } /* Deterministic hash so the same day always yields the same base count on EVERY device (no localStorage randomness → desktop and mobile match). */ function _hashStr(s) { let h = 2166136261; for (let i = 0; i < s.length; i++) { h ^= s.charCodeAt(i); h = Math.imul(h, 16777619); } return h >>> 0; } /* Copies sold is a pure function of the wall clock: a per-day base (600-750) that starts exactly at 00:00 midnight and grows steadily through the day. Two devices at the same moment compute the exact same number. */ function _computeCopies() { const base = MIN_COPIES_LO + (_hashStr(_dayKey()) % (MIN_COPIES_HI - MIN_COPIES_LO + 1)); const now = new Date(); const minutesIntoDay = now.getHours() * 60 + now.getMinutes(); const grown = base + Math.floor(minutesIntoDay / 4); // ~360 max growth over full day return Math.min(LAUNCH_TOTAL - 2, grown); } function _newSale(excludeName) { const pick = _randItem(NAMES_POOL, excludeName); return { name: pick[0], city: pick[1], cityShort: pick[1].split(",")[0].trim(), minutesAgo: _rand(1, 12) }; } function _formatTime(min) { if (min <= 0) return "just now"; if (min === 1) return "1 min ago"; return `${min} min ago`; } const CounterCtx = React.createContext(null); function CounterProvider({ children }) { // Copies sold is derived deterministically from the wall clock so every // device (desktop, mobile, tablet) always displays the same number. const [copiesSold, setCopiesSold] = React.useState(_computeCopies); const [viewing, setViewing] = React.useState(_rand(12, 28)); const [lastSale, setLastSale] = React.useState(() => _newSale(null)); const [saleNonce, setSaleNonce] = React.useState(0); // bumps each time a new sale lands so popup re-fires // viewing fluctuates within a realistic small range React.useEffect(() => { const t = setInterval(() => { setViewing((v) => Math.max(8, Math.min(36, v + _rand(-3, 4)))); }, _rand(10000, 15000)); return () => clearInterval(t); }, []); // Poll every 60s. When the clock-counter ticks +1 (every 4 min), // fire a popup — Option B: popup = counter are fully in sync. const prevCopies = React.useRef(null); React.useEffect(() => { prevCopies.current = _computeCopies(); const t = setInterval(() => { const fresh = _computeCopies(); if (fresh > prevCopies.current) { prevCopies.current = fresh; setCopiesSold(fresh); setLastSale((prev) => _newSale(prev ? prev.name : null)); setSaleNonce((n) => n + 1); } }, 60000); // check every minute, fires popup when counter ticks return () => clearInterval(t); }, []); // Midnight rollover — recompute the new day's base. React.useEffect(() => { let timer; const schedule = () => { timer = setTimeout(() => { setCopiesSold(_computeCopies()); schedule(); // schedule the next midnight }, _msUntilNextMidnight()); }; schedule(); return () => clearTimeout(timer); }, []); // every minute, age the displayed minutesAgo by 1 React.useEffect(() => { const t = setInterval(() => { setLastSale((s) => s ? { ...s, minutesAgo: Math.min(12, s.minutesAgo + 1) } : s); }, 60000); return () => clearInterval(t); }, []); const value = { copiesSold, copiesTotal: LAUNCH_TOTAL, copiesRemaining: LAUNCH_TOTAL - copiesSold, viewing, lastSale, saleNonce }; return {children}; } function useCounters() { return React.useContext(CounterCtx); } /* ===== Top status bar — redesigned with icons, animated dots, more visual rhythm ===== */ function TopStatusBar() { const { viewing, lastSale, copiesRemaining, copiesSold, copiesTotal } = useCounters(); const pct = Math.min(100, (copiesSold / copiesTotal) * 100); return (
{/* Left — live viewing */}
{viewing} reading right now viewing
{/* Center — last sold ticker (desktop) — city + minutes sync with sales popup */}
Last copy sold {_formatTime(lastSale.minutesAgo)} in {lastSale.cityShort}
{/* Right — copies sold */}
{copiesSold.toLocaleString()} /{copiesTotal.toLocaleString()} sold · {copiesRemaining.toLocaleString()} left
); } /* ===== Nav bar with section anchor links ===== */ const NAV_LINKS = [ ["#story", "Story"], ["#chapters", "Chapters"], ["#preview", "Preview"], ["#reviews", "Reviews"], ["#faq", "FAQ"] ]; function NavBar() { const [open, setOpen] = React.useState(false); return (
Born to Know Born to Know {/* Center anchor nav (desktop) */} {/* CTA + mobile menu trigger */}
Get The Blueprint Get for $23.95
{/* Mobile drawer */} {open && (
)}
); } /* ===== Sticky bottom CTA bar — richer, more urgent ===== */ function StickyBottomCTA() { const [visible, setVisible] = React.useState(false); const [dismissed, setDismissed] = React.useState(false); // Reappear 60 seconds after being dismissed React.useEffect(() => { if (!dismissed) return; const t = setTimeout(() => setDismissed(false), 60000); return () => clearTimeout(t); }, [dismissed]); const { copiesRemaining, copiesSold, copiesTotal } = useCounters(); const pct = Math.min(100, (copiesSold / copiesTotal) * 100); React.useEffect(() => { const onScroll = () => { if (!visible && window.scrollY > window.innerHeight * 0.7) setVisible(true); }; window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, [visible]); if (!visible || dismissed) return null; // Hide on mobile if (typeof window !== 'undefined' && window.innerWidth < 768) return null; return (
{/* Top urgency strip */}
{/* Product thumbnail (hidden < sm) */}
The Baby Blueprint
108 pages · Instant PDF
{/* Price + progress (center, desktop) */}
$39 $23.95
SAVE $15
Going fast
{copiesSold.toLocaleString()} sold · {copiesRemaining.toLocaleString()} left
{/* Mobile compact column — price + same scarcity info as desktop */}
$39 $23.95 SAVE $15
Only {copiesRemaining.toLocaleString()} left
{/* Right — CTA */}
Get it — $23.95
); } /* ===== Mini Book product thumbnail (used in sales popup + sticky footer) ===== */ function MiniBook({ size = 56 }) { return ( The Baby Blueprint ); } /* ===== Sales Notification — reads shared lastSale state so it syncs with the top ticker ===== */ function SalesNotification() { const { lastSale, saleNonce } = useCounters(); const [phase, setPhase] = React.useState("hidden"); // 'in' | 'out' | 'hidden' const dismissed = React.useRef(false); const outTimer = React.useRef(null); const hideTimer = React.useRef(null); // Whenever lastSale rotates (saleNonce bumps), show a popup tied to that sale. React.useEffect(() => { if (dismissed.current) return; // small delay so the ticker text "clicks over" a beat before the popup arrives. // saleNonce === 0 is the page-load state (no sale has fired yet), so don't show then. if (saleNonce === 0) return; const inT = setTimeout(() => setPhase("in"), 400); clearTimeout(outTimer.current); clearTimeout(hideTimer.current); outTimer.current = setTimeout(() => setPhase("out"), 8400); hideTimer.current = setTimeout(() => setPhase("hidden"), 8720); return () => { clearTimeout(inT); clearTimeout(outTimer.current); clearTimeout(hideTimer.current); }; }, [saleNonce]); if (!lastSale || phase === "hidden" || dismissed.current) return null; return (
{lastSale.name} · {lastSale.city}
just got The Blueprint
{_formatTime(lastSale.minutesAgo)}
); } /* ── Scroll Progress Indicator ───────────────────────── */ function ScrollProgress() { const [pct, setPct] = React.useState(0); React.useEffect(() => { const onScroll = () => { const el = document.documentElement; const scrolled = el.scrollTop || document.body.scrollTop; const total = el.scrollHeight - el.clientHeight; setPct(total > 0 ? Math.min(100, (scrolled / total) * 100) : 0); }; window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, []); return (
); } Object.assign(window, { CounterProvider, useCounters, TopStatusBar, NavBar, StickyBottomCTA, SalesNotification, MiniBook, ScrollProgress });