/* hand-drawn.jsx — Icon helper + hand-drawn SVG accents + reveal hook */ const CHECKOUT_URL = "https://checkout.theborntoknow.com/checkout/buy/8edcc250-1c08-4dd6-a88a-a0081454cc63"; /* ===== Icon ===== lucide vanilla UMD exposes icons in PascalCase on window.lucide and also on window.lucide.icons. Each entry is an array: ["svg", attrs, children[]], where children = [[tagName, attrsObj], ...]. */ function _pascal(name) { if (!name) return name; return name[0].toUpperCase() + name.slice(1); } function _kebabToCamelAttrs(attrs) { const out = {}; for (const k of Object.keys(attrs || {})) { let nk = k; if (k === "stroke-width") nk = "strokeWidth"; else if (k === "stroke-linecap") nk = "strokeLinecap"; else if (k === "stroke-linejoin") nk = "strokeLinejoin"; else if (k === "fill-rule") nk = "fillRule"; else if (k === "clip-rule") nk = "clipRule"; else if (k === "stop-color") nk = "stopColor"; else if (k === "stop-opacity") nk = "stopOpacity"; else if (k.startsWith("aria-") || k.startsWith("data-")) nk = k; else if (k.includes("-")) { nk = k.replace(/-([a-z])/g, (_, c) => c.toUpperCase()); } out[nk] = attrs[k]; } return out; } function Icon({ name, size = 20, color = "currentColor", stroke = 1.5, className = "", style = {} }) { const L = (typeof window !== "undefined" && window.lucide) || {}; const key = _pascal(name); const entry = (L.icons && L.icons[key]) || L[key]; let children = null; if (Array.isArray(entry) && entry.length >= 3 && Array.isArray(entry[2])) { children = entry[2]; } else if (entry && entry.iconNode) { children = entry.iconNode; } return ( ); } /* ===== useReveal: IntersectionObserver based scroll reveal ===== */ function useReveal(threshold = 0.15) { const ref = React.useRef(null); const [shown, setShown] = React.useState(false); React.useEffect(() => { if (!ref.current) return; if (shown) return; const io = new IntersectionObserver((entries) => { entries.forEach((e) => { if (e.isIntersecting) { setShown(true); io.disconnect(); } }); }, { threshold, rootMargin: "-40px 0px" }); io.observe(ref.current); return () => io.disconnect(); }, [shown, threshold]); return [ref, shown]; } /* ===== Reveal wrapper ===== */ function Reveal({ as: As = "div", delay = 0, className = "", children, ...rest }) { const [ref, shown] = useReveal(); return ( {children} ); } /* ===== Hand-drawn marker underline (wavy gold stroke under emphasis word) ===== */ function MarkerUnderline({ children, color = "#C8A24A", opacity = 0.7, thickness = 8 }) { const [ref, shown] = useReveal(); // Slightly wavy path drawn as a single hand-drawn stroke // path covers from left to right with subtle tremor const d = "M 4 11 C 50 6, 110 14, 160 9 S 280 6, 340 11 S 460 14, 520 9"; return ( {children} ); } /* ===== Hand-drawn strikethrough for "wrong"-type emphasis ===== */ function MarkerStrike({ children, color = "#C8A24A", opacity = 0.85, thickness = 7 }) { const [ref, shown] = useReveal(); const d = "M 6 50 C 60 38, 140 60, 210 45 S 360 50, 430 38"; return ( {children} ); } /* ===== Hand-drawn arrow (curved, slight tremor) ===== direction: 'down-right' | 'down-left' | 'right' | 'left' | 'up-left' | 'up-right' */ function HandArrow({ direction = "down-right", color = "#C8A24A", width = 90, height = 90, style = {}, className = "" }) { // Clean, legible hand-drawn arrows on a 0 0 100 100 grid. // Each is a single gently-curved shaft ending in a clear two-stroke arrowhead. const paths = { "down-right": { d: "M 14 16 Q 44 30 56 50 T 82 82", head: "M 82 82 L 64 80 M 82 82 L 80 64" }, "down-left": { d: "M 86 16 Q 56 30 44 50 T 18 82", head: "M 18 82 L 36 80 M 18 82 L 20 64" }, "right": { d: "M 12 46 Q 44 34 70 46 T 88 50", head: "M 88 50 L 74 42 M 88 50 L 74 58" }, "left": { d: "M 88 46 Q 56 34 30 46 T 12 50", head: "M 12 50 L 26 42 M 12 50 L 26 58" }, "up-right": { d: "M 16 84 Q 44 66 54 48 T 84 16", head: "M 84 16 L 66 20 M 84 16 L 80 34" }, "down": { d: "M 50 12 Q 44 42 50 60 T 50 86", head: "M 50 86 L 38 72 M 50 86 L 62 72" } }; const p = paths[direction] || paths["down-right"]; return ( ); } /* ===== Sticky-note testimonial ===== */ function StickyNote({ quote, attribution, rotation = -4, width = 230, style = {}, className = "" }) { return (

{quote}

{attribution}

); } /* ===== Polaroid frame ===== */ function Polaroid({ children, caption, rotation = -3, width = 360 }) { return (
{children}
{caption && (

{caption}

)}
); } /* ===== Count-up number animation ===== */ function CountUp({ to = 1000000, duration = 2000, format }) { const [val, setVal] = React.useState(0); const [ref, shown] = useReveal(); const started = React.useRef(false); React.useEffect(() => { if (!shown || started.current) return; started.current = true; const start = performance.now(); const tick = (now) => { const progress = Math.min((now - start) / duration, 1); const ease = 1 - Math.pow(1 - progress, 3); setVal(Math.round(ease * to)); if (progress < 1) requestAnimationFrame(tick); }; requestAnimationFrame(tick); }, [shown]); const display = format ? format(val) : val.toLocaleString(); return {display}; } Object.assign(window, { CHECKOUT_URL, Icon, useReveal, Reveal, MarkerUnderline, MarkerStrike, HandArrow, CountUp, Polaroid, StickyNote });