/* ── Raj Danej Portfolio v4 — Core: Colors, Icons, Shared Components ── */

const C = {
  purple: '#7c3aed', purpleLight: '#a78bfa', purpleDark: '#6d28d9',
  purpleGlow: 'rgba(124,58,237,0.25)', purpleSubtle: 'rgba(124,58,237,0.08)',
  teal: '#2dd4bf', tealDark: '#14b8a6', tealGlow: 'rgba(45,212,191,0.2)',
  bg: '#0c1222', bgCard: '#131b2e', bgCardHover: '#182240', bgSurface: '#0f172a',
  border: 'rgba(255,255,255,0.06)', borderHover: 'rgba(255,255,255,0.12)',
  text: '#e2e8f0', textMuted: '#94a3b8', textDim: '#64748b', white: '#fff',
  gold: '#f59e0b', green: '#22c55e', red: '#ef4444'
};
window.C = C;

/* ── SVG Icons ── */
const Icons = {
  github: (sz = 20, c = C.textMuted) => <svg width={sz} height={sz} viewBox="0 0 24 24" fill={c}><path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z" /></svg>,
  linkedin: (sz = 20, c = C.textMuted) => <svg width={sz} height={sz} viewBox="0 0 24 24" fill={c}><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" /></svg>,
  mail: (sz = 20, c = C.textMuted) => <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="2" y="4" width="20" height="16" rx="2" /><path d="M22 7l-10 7L2 7" /></svg>,
  download: (sz = 18, c = 'currentColor') => <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" /><polyline points="7 10 12 15 17 10" /><line x1="12" y1="15" x2="12" y2="3" /></svg>,
  send: (sz = 18, c = 'currentColor') => <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="22" y1="2" x2="11" y2="13" /><polygon points="22 2 15 22 11 13 2 9 22 2" /></svg>,
  external: (sz = 14, c = 'currentColor') => <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6" /><polyline points="15 3 21 3 21 9" /><line x1="10" y1="14" x2="21" y2="3" /></svg>,
  check: (sz = 18, c = 'currentColor') => <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" stroke={c} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12" /></svg>,
  star: (sz = 14, c = C.gold) => <svg width={sz} height={sz} viewBox="0 0 24 24" fill={c} stroke="none" style={{ opacity: "0" }}><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" style={{ opacity: "0" }} /></svg>,
  close: (sz = 20, c = C.textMuted) => <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" /></svg>,
  arrowUp: (sz = 18, c = 'currentColor') => <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="12" y1="19" x2="12" y2="5" /><polyline points="5 12 12 5 19 12" /></svg>,
  chat: (sz = 18, c = 'currentColor') => <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z" /></svg>,
  target: (sz = 16, c = 'currentColor') => <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10" /><circle cx="12" cy="12" r="6" /><circle cx="12" cy="12" r="2" /></svg>,
  microscope: (sz = 16, c = 'currentColor') => <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M6 18h8" /><path d="M3 22h18" /><path d="M14 22a7 7 0 100-14h-1" /><path d="M9 14h2" /><path d="M9 12a2 2 0 01-2-2V6h6v4a2 2 0 01-2 2H9z" /><path d="M12 6V3a1 1 0 00-1-1H9a1 1 0 00-1 1v3" /></svg>,
  chart: (sz = 16, c = 'currentColor') => <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="20" x2="18" y2="10" /><line x1="12" y1="20" x2="12" y2="4" /><line x1="6" y1="20" x2="6" y2="14" /></svg>,
  briefcase: (sz = 16, c = 'currentColor') => <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="2" y="7" width="20" height="14" rx="2" ry="2" /><path d="M16 21V5a2 2 0 00-2-2h-4a2 2 0 00-2 2v16" /></svg>,
  sparkles: (sz = 16, c = 'currentColor') => <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z" /><path d="M19 13l.75 2.25L22 16l-2.25.75L19 19l-.75-2.25L16 16l2.25-.75L19 13z" /></svg>,
  award: (sz = 16, c = 'currentColor') => <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="8" r="7" /><polyline points="8.21 13.89 7 23 12 20 17 23 15.79 13.88" /></svg>,
  book: (sz = 16, c = 'currentColor') => <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M4 19.5A2.5 2.5 0 016.5 17H20" /><path d="M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z" /></svg>,
  pkg: (sz = 14, c = 'currentColor') => <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" stroke={c} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M16.5 9.4l-9-5.19M21 16V8a2 2 0 00-1-1.73l-7-4a2 2 0 00-2 0l-7 4A2 2 0 003 8v8a2 2 0 001 1.73l7 4a2 2 0 002 0l7-4A2 2 0 0021 16z" /><polyline points="3.27 6.96 12 12.01 20.73 6.96" /><line x1="12" y1="22.08" x2="12" y2="12" /></svg>
};
window.Icons = Icons;

/* ── Animated Button ── */
function Btn({ children, href, onClick, variant = 'primary', size = 'md', icon, className = '', style: sx, ...rest }) {
  const cls = {
    primary: 'btn-primary', outline: 'btn-outline', ghost: 'btn-ghost',
    social: 'btn-social-icon', danger: 'btn-outline'
  }[variant] || '';
  const sizes = { sm: 'btn-sm', md: 'btn-md', lg: 'btn-lg', icon: 'btn-icon-size' };
  const fullCls = `btn-base ${cls} ${sizes[size] || ''} ${className}`.trim();
  const track = (ev) => {
    if (typeof window.plausible === 'function') {
      if (href && href.includes('github')) window.plausible('GitHub Click');
      if (href && href.includes('Resume')) window.plausible('CV Download');
    }
    if (onClick) onClick(ev);
  };
  if (href) {
    const isMailto = href.startsWith('mailto:');
    return <a href={href} target={isMailto ? undefined : '_blank'} rel={isMailto ? undefined : 'noopener noreferrer'} className={fullCls} style={sx} onClick={track} {...rest}>{icon}{children}</a>;
  }
  return <button className={fullCls} style={sx} onClick={track} {...rest}>{icon}{children}</button>;
}
window.Btn = Btn;

/* ── Section Title ── */
function SectionTitle({ label, highlight, sub }) {
  return (
    <div style={{ textAlign: 'center', marginBottom: 56 }}>
      <h2 style={{ fontSize: 'clamp(28px, 4vw, 36px)', fontWeight: 700, color: C.white, margin: 0, letterSpacing: '-0.02em' }}>
        {label} <span style={{ color: C.purple }}>{highlight}</span>
      </h2>
      {sub && <p style={{ color: C.textMuted, fontSize: 16, marginTop: 12, maxWidth: 580, marginInline: 'auto', lineHeight: 1.6 }}>{sub}</p>}
      <div className="section-divider-accent" style={{ width: 48, height: 3, background: `linear-gradient(90deg, ${C.teal}, ${C.purple})`, borderRadius: 2, margin: '16px auto 0' }}></div>
    </div>);

}
window.SectionTitle = SectionTitle;

/* ── Section Divider ── */
function SectionDivider() {
  return <div style={{ height: 1, background: 'linear-gradient(90deg, transparent, rgba(124,58,237,0.3), transparent)' }}></div>;
}
window.SectionDivider = SectionDivider;

/* ── Scroll-reveal hook ── */
function useReveal(threshold = 0.15) {
  const ref = React.useRef(null);
  const [visible, setVisible] = React.useState(false);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const obs = new IntersectionObserver(([e]) => {if (e.isIntersecting) {setVisible(true);obs.disconnect();}}, { threshold });
    obs.observe(el);
    return () => obs.disconnect();
  }, []);
  return [ref, visible];
}
window.useReveal = useReveal;

function Reveal({ children, delay = 0, direction = 'up', style: sx }) {
  const [ref, visible] = useReveal(0.1);
  const t = { up: 'translateY(40px)', down: 'translateY(-40px)', left: 'translateX(40px)', right: 'translateX(-40px)', none: 'none' };
  return (
    <div ref={ref} style={{ opacity: visible ? 1 : 0, transform: visible ? 'none' : t[direction], transition: `all 0.7s cubic-bezier(0.16,1,0.3,1) ${delay}s`, ...sx }}>{children}</div>);

}
window.Reveal = Reveal;

/* ── Counter ── */
function Counter({ end, duration = 2000, suffix = '', prefix = '' }) {
  const [ref, visible] = useReveal(0.3);
  const [val, setVal] = React.useState(0);
  React.useEffect(() => {
    if (!visible) return;
    const start = Date.now();
    const tick = () => {
      const p = Math.min((Date.now() - start) / duration, 1);
      setVal(Math.floor((1 - Math.pow(1 - p, 3)) * end));
      if (p < 1) requestAnimationFrame(tick);
    };
    requestAnimationFrame(tick);
  }, [visible, end, duration]);
  return <span ref={ref}>{prefix}{val.toLocaleString()}{suffix}</span>;
}
window.Counter = Counter;

/* ── Ticker ── */
function Ticker({ items }) {
  const doubled = [...items, ...items];
  return (
    <div style={{ overflow: 'hidden', width: '100%' }}>
      <div style={{ display: 'flex', gap: 48, animation: 'ticker 35s linear infinite', willChange: 'transform', whiteSpace: 'nowrap' }}>
        {doubled.map((item, i) =>
        <span key={i} style={{ color: C.textDim, fontSize: 12, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.1em', display: 'flex', alignItems: 'center', gap: 8, flexShrink: 0 }}>
            <span style={{ width: 4, height: 4, borderRadius: '50%', background: C.purple, flexShrink: 0 }}></span>
            {item}
          </span>
        )}
      </div>
    </div>);

}
window.Ticker = Ticker;

/* ── Filter Tabs ── */
function FilterTabs({ categories, active, onChange }) {
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'center', gap: 8, marginBottom: 40 }}>
      {categories.map((cat) =>
      <button key={cat} onClick={() => onChange(cat)} className={active === cat ? 'filter-btn filter-btn-active' : 'filter-btn'}>{cat}</button>
      )}
    </div>);

}
window.FilterTabs = FilterTabs;

/* ── GitHub Stats Hook ── */
function useGitHubStats(username) {
  const [stats, setStats] = React.useState(null);
  React.useEffect(() => {
    const CACHE_KEY = `gh_stats_${username}`;
    const cached = localStorage.getItem(CACHE_KEY);
    if (cached) {
      try {
        const { data, ts } = JSON.parse(cached);
        if (Date.now() - ts < 3600000) {setStats(data);return;}
      } catch (e) {}
    }
    fetch(`https://api.github.com/users/${username}/repos?sort=updated&per_page=30`).
    then((r) => {if (!r.ok) throw new Error();return r.json();}).
    then((repos) => {
      const langs = {};
      let totalStars = 0;
      repos.forEach((r) => {
        totalStars += r.stargazers_count || 0;
        if (r.language) langs[r.language] = (langs[r.language] || 0) + 1;
      });
      const topLang = Object.entries(langs).sort((a, b) => b[1] - a[1])[0];
      const lastUpdate = repos[0] ? repos[0].updated_at : null;
      const data = { repoCount: repos.length, stars: totalStars, topLang: topLang ? topLang[0] : 'Python', lastUpdate };
      localStorage.setItem(CACHE_KEY, JSON.stringify({ data, ts: Date.now() }));
      setStats(data);
    }).
    catch(() => setStats({ repoCount: 18, stars: 12, topLang: 'Python', lastUpdate: null }));
  }, [username]);
  return stats;
}
window.useGitHubStats = useGitHubStats;

/* ── Analytics helper ── */
function track(event, props) {
  if (typeof window.plausible === 'function') window.plausible(event, props ? { props } : undefined);
}
window.track = track;