/* global React, window */ // Eyad Academy — shared atoms: icons, mascot, reveal, counter const { useEffect, useRef, useState } = React; // ============================================================ // Icon set — hand-tuned to match brand. Uses currentColor. // ============================================================ function Icon({ name, size = 22 }) { const s = { width: size, height: size, display: "inline-block", verticalAlign: "middle" }; const stroke = { fill: "none", stroke: "currentColor", strokeWidth: 1.8, strokeLinecap: "round", strokeLinejoin: "round" }; switch (name) { case "menu": return (); case "arrow": return (); case "play": return (); case "spark": return (); case "compass": return (); case "shield": return (); case "trophy": return (); case "book": return (); case "clock": return (); case "users": return (); case "star": return (); case "check": return (); case "close": return (); case "chevron": return (); case "quote": return (); case "quran": return (); case "arabic": return (); case "math": return (); case "science": return (); case "lightning": return (); case "twitter": return (); case "insta": return (); case "youtube": return (); case "tiktok": return (); default: return null; } } // ============================================================ // Mascot — 4 styles, swap via Tweaks // ============================================================ function Mascot({ style = "real", className = "", size }) { const sty = size ? { width: size, height: size } : {}; if (style === "real") { return (
نجمة إياد
); } if (style === "geometric") { return (
); } if (style === "lineart") { return (
); } // "sunny" — soft sun return (
{[0,30,60,90,120,150,180,210,240,270,300,330].map(a => ( ))}
); } // ============================================================ // Reveal — fade-up on scroll // ============================================================ function Reveal({ children, delay = 0, as = "div", ...rest }) { const ref = useRef(null); const [shown, setShown] = useState(false); useEffect(() => { const el = ref.current; if (!el) return; const io = new IntersectionObserver((entries) => { entries.forEach(e => { if (e.isIntersecting) { setTimeout(() => setShown(true), delay); io.disconnect(); } }); }, { threshold: 0.12, rootMargin: "0px 0px -40px 0px" }); io.observe(el); return () => io.disconnect(); }, [delay]); const Tag = as; return ( {children} ); } // ============================================================ // Animated counter — counts up when in view // ============================================================ function Counter({ value, decimal = false, suffix = "" }) { const ref = useRef(null); const [n, setN] = useState(0); useEffect(() => { const el = ref.current; if (!el) return; let started = false; const io = new IntersectionObserver((entries) => { if (entries[0].isIntersecting && !started) { started = true; const start = performance.now(); const dur = 1600; const tick = (t) => { const p = Math.min(1, (t - start) / dur); const eased = 1 - Math.pow(1 - p, 3); setN(value * eased); if (p < 1) requestAnimationFrame(tick); }; requestAnimationFrame(tick); } }, { threshold: 0.3 }); io.observe(el); return () => io.disconnect(); }, [value]); const display = decimal ? n.toFixed(1) : Math.round(n).toLocaleString("ar-EG"); return {display}{suffix}; } // ============================================================ // Floating decorative shapes for backgrounds // ============================================================ function FloatingDeco({ variant = "hero" }) { if (variant === "hero") { return (