/* eslint-disable */
const { useState, useEffect, useRef, useCallback } = React;

/* ===================== SHARED HOOKS ===================== */

/* Detect reduced motion preference */
function usePrefersReducedMotion() {
  const [reduced, setReduced] = useState(() =>
    window.matchMedia("(prefers-reduced-motion: reduce)").matches
  );
  useEffect(() => {
    const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
    const handler = (e) => setReduced(e.matches);
    mq.addEventListener("change", handler);
    return () => mq.removeEventListener("change", handler);
  }, []);
  return reduced;
}

/* Scroll-triggered reveal for sections */
function useReveal(threshold = 0.12) {
  const ref = useRef(null);
  const reduced = usePrefersReducedMotion();
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    if (reduced) { el.classList.add("revealed"); return; }
    const obs = new IntersectionObserver(
      ([entry]) => { if (entry.isIntersecting) { el.classList.add("revealed"); obs.unobserve(el); } },
      { threshold }
    );
    obs.observe(el);
    return () => obs.disconnect();
  }, [reduced, threshold]);
  return ref;
}

/* Staggered reveal for grids of cards */
function useStagger(count, delay = 80) {
  const ref = useRef(null);
  const reduced = usePrefersReducedMotion();
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const children = el.children;
    if (reduced) {
      Array.from(children).forEach(c => c.classList.add("revealed"));
      return;
    }
    const obs = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          Array.from(children).forEach((c, i) => {
            c.style.transitionDelay = `${i * delay}ms`;
            c.classList.add("revealed");
          });
          obs.unobserve(el);
        }
      },
      { threshold: 0.08 }
    );
    obs.observe(el);
    return () => obs.disconnect();
  }, [reduced, count, delay]);
  return ref;
}

/* Track active section for nav highlighting */
function useActiveSection(sectionIds) {
  const [active, setActive] = useState("");
  useEffect(() => {
    const obs = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) setActive(entry.target.id);
        });
      },
      { rootMargin: "-40% 0px -55% 0px" }
    );
    sectionIds.forEach((id) => {
      const el = document.getElementById(id);
      if (el) obs.observe(el);
    });
    return () => obs.disconnect();
  }, [sectionIds]);
  return active;
}

/* Counter animation */
function CountUp({ target, suffix = "", duration = 1200 }) {
  const [val, setVal] = useState(0);
  const ref = useRef(null);
  const reduced = usePrefersReducedMotion();
  const num = parseInt(target.replace(/[^0-9]/g, ""), 10) || 0;
  useEffect(() => {
    const el = ref.current;
    if (!el || !num) return;
    if (reduced) { setVal(num); return; }
    const obs = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          const start = performance.now();
          const animate = (now) => {
            const progress = Math.min((now - start) / duration, 1);
            const eased = 1 - Math.pow(1 - progress, 3);
            setVal(Math.round(eased * num));
            if (progress < 1) requestAnimationFrame(animate);
          };
          requestAnimationFrame(animate);
          obs.unobserve(el);
        }
      },
      { threshold: 0.5 }
    );
    obs.observe(el);
    return () => obs.disconnect();
  }, [num, reduced, duration]);
  return <span ref={ref}>{val}{suffix}</span>;
}

/* ===================== KINETIC TYPE BACKDROP ===================== */
const TYPE_COLUMNS = [
  ["GO", "DOCKER", "KUBERNETES", "AWS", "AZURE", "REDIS", "MYSQL", "LINUX", "GRAFANA", "MICROSERVICES", "REST API", "BACKEND"],
  ["vibe coding", "AI", "cloud native", "serverless", "devops", "containers", "observability", "golang", "open source", "CI/CD", "infrastructure", "scalability"],
  ["DEVELOPER", "ENGINEER", "BUILDER", "CREATOR", "CONTRIBUTOR", "DEPLOYER", "DEBUGGER", "ARCHITECT", "CODER", "INNOVATOR", "PROBLEM SOLVER", "CRAFTSMAN"],
  ["gofr", "react", "websocket", "grpc", "jwt", "oauth", "swagger", "prometheus", "helm", "terraform", "github actions", "docker compose"],
  ["systems design", "clean code", "test driven", "production ready", "high availability", "low latency", "distributed", "event driven", "api first", "cloud cost", "full stack", "type safe"],
];

function KineticType({ parallaxY }) {
  return (
    <div className="kinetic" style={parallaxY ? { transform: `translateY(${parallaxY}px)` } : undefined}>
      {TYPE_COLUMNS.map((col, i) => {
        const dur = 38 + i * 9;
        const dir = i % 2 === 0 ? "up" : "down";
        const items = [...col, ...col, ...col];
        return (
          <div key={i} className={`kcol kcol-${dir}`} style={{ animationDuration: `${dur}s` }}>
            {items.map((w, j) => (
              <span key={j} className={`kword ${j % 4 === 0 ? "kword-accent" : ""} ${j % 7 === 0 ? "kword-outline" : ""}`}>{w}</span>
            ))}
          </div>
        );
      })}
    </div>
  );
}

/* ===================== Tech Logos (official CDN) ===================== */
const LOGO_URLS = {
  "Go": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/go/go-original.svg",
  "Java": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/java/java-original.svg",
  "C": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/c/c-original.svg",
  "C++": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/cplusplus/cplusplus-original.svg",
  "MySQL": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/mysql/mysql-original.svg",
  "Redis": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/redis/redis-original.svg",
  "Docker": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/docker/docker-original.svg",
  "Kubernetes": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/kubernetes/kubernetes-original.svg",
  "AWS": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/amazonwebservices/amazonwebservices-plain-wordmark.svg",
  "Azure": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/azure/azure-original.svg",
  "Git": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/git/git-original.svg",
  "Linux": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/linux/linux-original.svg",
  "Grafana": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/grafana/grafana-original.svg",
  "Postman": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/postman/postman-original.svg",
  "GoFr": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/go/go-original.svg",
  "REST APIs": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/openapi/openapi-original.svg",
  "Swagger": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/swagger/swagger-original.svg",
  "OpenObserve": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/grafana/grafana-original.svg",
  "Lens": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/kubernetes/kubernetes-original.svg",
  "gomock": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/go/go-original.svg",
  "CI/CD": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/githubactions/githubactions-original.svg",
  "JavaScript": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/javascript/javascript-original.svg",
  "Chrome Extension": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/chrome/chrome-original.svg",
  "Gemini AI": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/google/google-original.svg",
  "GitHub API": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/github/github-original.svg",
  "WebSocket": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/socketio/socketio-original.svg",
  "JWT": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/json/json-original.svg",
  "OTP": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/json/json-original.svg",
  "REST API": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/openapi/openapi-original.svg",
  "Open Source": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/github/github-original.svg",
  "gRPC": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/grpc/grpc-original.svg",
  "MCP Server": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/json/json-original.svg",
  "npm": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/npm/npm-original-wordmark.svg",
  "Cursor": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/vscode/vscode-original.svg",
  "Claude Code": "",
  "Codex": "",
  "GitHub": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/github/github-original.svg",
  "Microservices": "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/docker/docker-original.svg",
};

const INLINE_LOGOS = {
  "Claude Code": <svg viewBox="0 0 24 24" width="16" height="16"><rect width="24" height="24" rx="6" fill="#D97757"/><text x="12" y="17" textAnchor="middle" fontSize="13" fill="white" fontWeight="700" fontFamily="sans-serif">C</text></svg>,
  "Microservices": <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="var(--ink-2)" strokeWidth="2"><circle cx="12" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="18" r="3"/><path d="M12 9v3M9 15l-1.5 1.5M15 15l1.5 1.5"/></svg>,
  "MCP Server": <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="var(--ink-2)" strokeWidth="2"><rect x="4" y="4" width="16" height="16" rx="3"/><path d="M9 9h6M9 12h4M9 15h5"/></svg>,
  "Codex": <svg viewBox="0 0 24 24" width="16" height="16"><rect width="24" height="24" rx="6" fill="#10a37f"/><text x="12" y="17" textAnchor="middle" fontSize="13" fill="white" fontWeight="700" fontFamily="sans-serif">X</text></svg>,
  "CLI": <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="var(--ink-2)" strokeWidth="2"><rect x="3" y="3" width="18" height="18" rx="3"/><path d="M7 10l3 3-3 3M13 16h4"/></svg>,
};
function Logo({ name }) {
  if (INLINE_LOGOS[name]) return <span className="logo">{INLINE_LOGOS[name]}</span>;
  const url = LOGO_URLS[name];
  if (url) return <span className="logo"><img src={url} alt={name} width="16" height="16" loading="lazy" /></span>;
  return <span className="logo"><span style={{ width: 16, height: 16, borderRadius: '50%', background: 'var(--accent)', opacity: .4, display: 'inline-block' }} /></span>;
}

/* ===================== Modal (with focus trap) ===================== */
function Modal({ open, onClose, children }) {
  const closeRef = useRef(null);
  useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    document.body.style.overflow = "hidden";
    window.addEventListener("keydown", onKey);
    if (closeRef.current) closeRef.current.focus();
    return () => { document.body.style.overflow = ""; window.removeEventListener("keydown", onKey); };
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div className="modal-bg" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <button ref={closeRef} className="modal-close" onClick={onClose} aria-label="Close modal">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M18 6L6 18M6 6l12 12"/></svg>
        </button>
        {children}
      </div>
    </div>
  );
}

/* ===================== Scroll Progress Bar ===================== */
function ScrollProgress() {
  const [progress, setProgress] = useState(0);
  useEffect(() => {
    const onScroll = () => {
      const h = document.documentElement.scrollHeight - window.innerHeight;
      setProgress(h > 0 ? (window.scrollY / h) * 100 : 0);
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  return <div className="scroll-progress" style={{ width: `${progress}%` }} />;
}

/* ===================== Back to Top ===================== */
function BackToTop() {
  const [show, setShow] = useState(false);
  useEffect(() => {
    const onScroll = () => setShow(window.scrollY > window.innerHeight);
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  if (!show) return null;
  return (
    <button className="back-to-top" onClick={() => window.scrollTo({ top: 0, behavior: "smooth" })} aria-label="Back to top">
      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M18 15l-6-6-6 6"/></svg>
    </button>
  );
}

/* ===================== Nav (with hamburger + auto-hide + active section) ===================== */
function Nav({ theme, toggleTheme, activeSection }) {
  const [menuOpen, setMenuOpen] = useState(false);
  const [hidden, setHidden] = useState(false);
  const lastScrollRef = useRef(0);

  useEffect(() => {
    const onScroll = () => {
      const y = window.scrollY;
      if (y > 80 && y > lastScrollRef.current + 5) setHidden(true);
      else if (y < lastScrollRef.current - 5) setHidden(false);
      lastScrollRef.current = y;
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  useEffect(() => {
    if (menuOpen) document.body.style.overflow = "hidden";
    else document.body.style.overflow = "";
    return () => { document.body.style.overflow = ""; };
  }, [menuOpen]);

  const navLinks = [
    { href: "#about", label: "About" },
    { href: "#experience", label: "Experience" },
    { href: "#projects", label: "Projects" },
    { href: "#education", label: "Education" },
    { href: "#stack", label: "Stack" },
  ];

  return (
    <>
      <nav className={`nav ${hidden ? "nav-hidden" : ""}`}>
        <a href="#top" className="nav-logo">gm<span className="dot">.</span></a>
        <div className="nav-links">
          {navLinks.map((l) => (
            <a key={l.href} href={l.href} className={activeSection === l.href.slice(1) ? "active" : ""}>{l.label}</a>
          ))}
        </div>
        <div className="nav-right">
          <button className="theme-toggle" onClick={toggleTheme} aria-label="Toggle theme">
            {theme === "dark" ? (
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg>
            ) : (
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
            )}
          </button>
          <button className="hamburger" onClick={() => setMenuOpen(!menuOpen)} aria-label="Toggle menu">
            <span className={`hamburger-line ${menuOpen ? "open" : ""}`} />
            <span className={`hamburger-line ${menuOpen ? "open" : ""}`} />
            <span className={`hamburger-line ${menuOpen ? "open" : ""}`} />
          </button>
          <a href="#contact" className="nav-cta">Let's talk <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M5 12h14M13 5l7 7-7 7"/></svg></a>
        </div>
      </nav>
      {menuOpen && (
        <div className="mobile-menu" onClick={() => setMenuOpen(false)}>
          <div className="mobile-menu-inner" onClick={(e) => e.stopPropagation()}>
            {navLinks.map((l) => (
              <a key={l.href} href={l.href} className={`mobile-link ${activeSection === l.href.slice(1) ? "active" : ""}`} onClick={() => setMenuOpen(false)}>{l.label}</a>
            ))}
            <a href="#contact" className="mobile-link" onClick={() => setMenuOpen(false)}>Contact</a>
          </div>
        </div>
      )}
    </>
  );
}

/* ===================== Hero (with parallax) ===================== */
const ROTATE_WORDS = ["systems.", "microservices.", "with Go.", "for scale.", "from scratch."];
function RotatingWord() {
  const [i, setI] = useState(0);
  useEffect(() => {
    const t = setInterval(() => setI(v => (v + 1) % ROTATE_WORDS.length), 2200);
    return () => clearInterval(t);
  }, []);
  return (
    <span className="rot-wrap">
      {ROTATE_WORDS.map((w, idx) => (
        <span key={idx} className={`rot-word ${idx === i ? "rot-active" : idx === (i - 1 + ROTATE_WORDS.length) % ROTATE_WORDS.length ? "rot-prev" : ""}`}>{w}</span>
      ))}
    </span>
  );
}

function Hero() {
  const [parallaxY, setParallaxY] = useState(0);
  const reduced = usePrefersReducedMotion();
  useEffect(() => {
    if (reduced) return;
    const onScroll = () => setParallaxY(window.scrollY * 0.25);
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, [reduced]);

  return (
    <header className="hero" id="top">
      <div className="hero-canvas-wrap"><KineticType parallaxY={parallaxY} /></div>
      <div className="hero-scrim" />
      <div className="app">
        <div className="hero-content">
          <div className="hero-eyebrow"><span className="pulse" /> Software Developer at ZopDev</div>
          <div className="hero-name">Gajendra Malviya</div>
          <h1>
            <span className="h1-line">I build</span>
            <span className="h1-line h1-rot"><RotatingWord /></span>
          </h1>
          <p className="hero-tagline">
            Software developer who loves turning ideas into real, working software. Go enthusiast, open-source contributor, and someone who genuinely enjoys the craft of building things.
          </p>
          <div className="hero-ctas">
            <a href="#projects" className="btn btn-primary">See what I've built <span className="arrow">&rarr;</span></a>
            <a href="https://drive.google.com/file/d/1Wz6vopr_YYozdQlVvbVIBV0HzR5yFRmu/view?usp=sharing" target="_blank" rel="noopener" className="btn btn-ghost">Resume</a>
          </div>
        </div>
      </div>
      <div className="hero-scroll">scroll<span className="line" /></div>
    </header>
  );
}

function SecH({ num, title, em, lede }) {
  return <div className="sec-h"><span className="num">{num}</span><h2>{title} <em>{em}</em></h2>{lede && <p className="lede">{lede}</p>}</div>;
}

/* ===================== About ===================== */
function About() {
  const revealRef = useReveal();
  return (
    <section className="section reveal" id="about" ref={revealRef}>
      <div className="app">
        <SecH num="01 — about" title="quietly" em="building." lede="A short version of who I am, what I care about, and how I work." />
        <div className="about-grid">
          <div className="about">
            <p>Hey, I'm Gajendra — a software developer from Pali, a small town in Rajasthan, India. I studied Computer Science Engineering at Chandigarh University and currently work as an SDE Intern at ZopDev.</p>
            <p>I'm someone who fell in love with building software — not just writing code, but understanding how systems work under the hood and making them better, one piece at a time. From designing clean APIs to optimizing database queries to setting up observability — I find real satisfaction in the craft.</p>
            <p>When I'm not coding, I'm probably contributing to open-source projects, reading about distributed systems, or capturing moments through my camera. I believe good engineering is about curiosity, consistency, and caring about the small details that add up.</p>
          </div>
          <div className="about-photo">
            <div className="about-photo-frame">
              <img src="profile.jpg" alt="Gajendra Malviya" />
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ===================== Experience ===================== */
function Experience() {
  const revealRef = useReveal();
  const [openZopdev, setOpenZopdev] = useState(false);
  const [openTrainee, setOpenTrainee] = useState(false);
  const techStack = ["Go", "GoFr", "MySQL", "Redis", "Docker", "Kubernetes", "AWS", "Azure", "Grafana"];
  const traineeTech = ["Java"];
  return (
    <section className="section reveal" id="experience" ref={revealRef}>
      <div className="app">
        <SecH num="02 — experience" title="where I" em="work." lede="Production backend work, training, and real releases." />

        <div className="exp-card" onClick={() => setOpenZopdev(true)} style={{ cursor: "pointer" }}>
          <div>
            <div className="exp-head">
              <h3>Software Development Engineer Intern <em>— ZopDev Pvt. Ltd.</em></h3>
              <span className="sub"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" style={{verticalAlign:"-1px",marginRight:"4px"}}><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>Bengaluru, Karnataka, India</span>
              <span className="meta">June 2025 — Present</span>
            </div>
            <div className="exp-tech-logos">
              {techStack.map(t => <span key={t} className="exp-logo-item"><Logo name={t} /><span className="exp-logo-label">{t}</span></span>)}
            </div>
            <p style={{ marginTop: 14, fontSize: 14, color: "var(--ink-3)" }}>View details &rarr;</p>
          </div>
          <aside className="exp-side">
            <div className="stat-row"><span className="lbl">Features</span><span className="val"><CountUp target="20" suffix="+" /></span></div>
            <div className="stat-row"><span className="lbl">Bugs Fixed</span><span className="val"><CountUp target="50" suffix="+" /></span></div>
            <div className="stat-row"><span className="lbl">Releases</span><span className="val"><CountUp target="8" suffix="+" /></span></div>
            <div className="stat-row"><span className="lbl">SLA</span><span className="val">99%+</span></div>
            <div className="stat-row"><span className="lbl">API Coverage</span><span className="val">90%+</span></div>
          </aside>
        </div>

        <div className="exp-card" onClick={() => setOpenTrainee(true)} style={{ cursor: "pointer", marginTop: 14 }}>
          <div>
            <div className="exp-head">
              <h3>Java Inhouse Summer Trainee <em>— Chandigarh University</em></h3>
              <span className="sub"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" style={{verticalAlign:"-1px",marginRight:"4px"}}><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>Mohali, Punjab, India</span>
              <span className="meta">May 2024 — June 2024 · 2 months</span>
            </div>
            <div className="exp-tech-logos">
              {traineeTech.map(t => <span key={t} className="exp-logo-item"><Logo name={t} /><span className="exp-logo-label">{t}</span></span>)}
            </div>
            <p style={{ marginTop: 14, fontSize: 14, color: "var(--ink-3)" }}>View details &rarr;</p>
          </div>
          <aside className="exp-side">
            <div className="stat-row"><span className="lbl">Duration</span><span className="val">2 months</span></div>
            <div className="stat-row"><span className="lbl">Type</span><span className="val">Apprenticeship</span></div>
            <div className="stat-row"><span className="lbl">Mode</span><span className="val">Hybrid</span></div>
          </aside>
        </div>
      </div>

      <Modal open={openZopdev} onClose={() => setOpenZopdev(false)}>
        <div className="modal-hero">
          <svg viewBox="0 0 840 360" width="100%" height="100%" preserveAspectRatio="xMidYMid slice"><rect width="840" height="360" fill="var(--bg-2)"/>
            {[0,1,2,3,4,5,6].map(i => <rect key={i} x={60+i*110} y={60} width="80" height="180" rx="10" fill="var(--surface)" stroke="var(--border-2)"/>)}
            {[0,1,2,3,4,5,6].map(i => <rect key={"b"+i} x={72+i*110} y={80+i*14} width="56" height={140-i*14} rx="5" fill="var(--accent)" opacity={0.15+i*0.1}/>)}
            <line x1="50" y1="280" x2="790" y2="280" stroke="var(--border-2)"/>
            <text x="420" y="320" textAnchor="middle" fontSize="14" fill="var(--ink-3)" fontFamily="monospace">microservices · cloud · observability</text>
          </svg>
        </div>
        <div className="modal-body">
          <span className="modal-tag">Current Role</span>
          <h2>SDE Intern at ZopDev</h2>
          <p className="lede">Backend Developer working on Go microservices, cloud infrastructure, and observability tooling. Full ownership from API design to production on-call.</p>
          <h3>Key Contributions</h3>
          <ul>
            <li>Shipped 20+ features and resolved 50+ bugs across Go microservices; managed 8+ releases with semantic versioning</li>
            <li>Built MCP server and recommendation system engine for ZopNight — ZopDev's cloud cost-optimization product</li>
            <li>Developed cloud cost-optimization engine end-to-end with 50+ compliance checks across 2 providers (AWS, Azure)</li>
            <li>Managed on-call for 5+ services; triaged 30+ incidents with 99%+ SLA via Grafana and OpenObserve</li>
            <li>Reduced incident detection time by 40% via Grafana alerting and centralized logging across 5+ microservices</li>
            <li>Improved API response times by 30% by optimizing MySQL queries, adding Redis caching, and tuning indexes</li>
            <li>Designed 50+ REST APIs (GoFr, handler-service-store), 90%+ test coverage (gomock), Swagger/OpenAPI docs</li>
          </ul>
          <h3>By the numbers</h3>
          <div className="modal-stats">
            <div className="modal-stat"><div className="v">20+</div><div className="l">features shipped</div></div>
            <div className="modal-stat"><div className="v">50+</div><div className="l">bugs resolved</div></div>
            <div className="modal-stat"><div className="v">8+</div><div className="l">releases</div></div>
            <div className="modal-stat"><div className="v">99%+</div><div className="l">SLA</div></div>
            <div className="modal-stat"><div className="v">30%</div><div className="l">faster APIs</div></div>
            <div className="modal-stat"><div className="v">90%+</div><div className="l">test coverage</div></div>
          </div>
          <h3>Tech Stack</h3>
          <div className="modal-stack">
            {techStack.map(s => <span key={s} className="chip"><Logo name={s} /> {s}</span>)}
          </div>
        </div>
      </Modal>

      <Modal open={openTrainee} onClose={() => setOpenTrainee(false)}>
        <div className="modal-hero">
          <svg viewBox="0 0 840 360" width="100%" height="100%" preserveAspectRatio="xMidYMid slice"><rect width="840" height="360" fill="var(--bg-2)"/>
            <rect x="250" y="60" width="340" height="200" rx="14" fill="var(--surface)" stroke="var(--border-2)"/>
            <rect x="280" y="90" width="100" height="10" rx="5" fill="var(--accent)" opacity="0.4"/>
            <rect x="280" y="115" width="260" height="7" rx="3" fill="var(--ink-3)" opacity="0.2"/>
            <rect x="280" y="135" width="220" height="7" rx="3" fill="var(--ink-3)" opacity="0.2"/>
            <rect x="280" y="155" width="240" height="7" rx="3" fill="var(--ink-3)" opacity="0.2"/>
            <rect x="280" y="190" width="120" height="30" rx="8" fill="var(--accent)" opacity="0.1" stroke="var(--accent)" strokeWidth="1"/>
            <circle cx="140" cy="160" r="45" fill="var(--accent)" opacity="0.04"/>
            <circle cx="720" cy="140" r="30" fill="var(--accent)" opacity="0.04"/>
            <text x="420" y="320" textAnchor="middle" fontSize="13" fill="var(--ink-3)" fontFamily="monospace">java · jvm · multithreading</text>
          </svg>
        </div>
        <div className="modal-body">
          <span className="modal-tag">Training</span>
          <h2>Java Inhouse Summer Trainee</h2>
          <p className="lede">High-level Java programming summer training at Chandigarh University, going beyond basic syntax to explore advanced concepts in JVM, concurrency, and scalable software design.</p>
          <h3>What I Learned</h3>
          <ul>
            <li>Advanced Java concepts — memory management, JVM optimization, and Garbage Collection</li>
            <li>Multithreading and concurrency for building high-performance applications</li>
            <li>Network programming and Java's Collections Framework for effective data management</li>
            <li>Writing efficient, optimized algorithms and scalable software solutions</li>
            <li>Hands-on experience tackling large-scale, real-world projects</li>
          </ul>
          <h3>Details</h3>
          <div className="modal-stats">
            <div className="modal-stat"><div className="v">2 mo</div><div className="l">duration</div></div>
            <div className="modal-stat"><div className="v">Hybrid</div><div className="l">mode</div></div>
            <div className="modal-stat"><div className="v">Java</div><div className="l">focus</div></div>
          </div>
          <h3>Tech</h3>
          <div className="modal-stack">
            <span className="chip"><Logo name="Java" /> Java</span>
          </div>
        </div>
      </Modal>
    </section>
  );
}

/* ===================== Project Art (GitHub OG images) ===================== */
const PROJECT_IMAGES = {
  mindswap: "https://opengraph.githubassets.com/1/ShipOrBleed/mindswap",
  reqflow: "https://opengraph.githubassets.com/1/ShipOrBleed/reqflow",
};
function ProjectArt({ kind }) {
  const url = PROJECT_IMAGES[kind];
  if (url) return <img src={url} alt={kind} />;
  if (kind === "bugbuddy") return (
    <svg viewBox="0 0 400 250" preserveAspectRatio="xMidYMid slice" style={{width:"100%",height:"100%"}}>
      <defs><linearGradient id="bb" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stopColor="#1a1a2e"/><stop offset="100%" stopColor="#16213e"/></linearGradient></defs>
      <rect width="400" height="250" fill="url(#bb)"/>
      <circle cx="320" cy="80" r="45" fill="#6ee04a" opacity="0.08"/>
      <circle cx="320" cy="80" r="28" fill="#6ee04a" opacity="0.12"/>
      <text x="320" y="87" textAnchor="middle" fontSize="22" fill="#6ee04a" fontFamily="monospace" fontWeight="700">AI</text>
      <rect x="40" y="45" width="200" height="130" rx="12" fill="rgba(255,255,255,0.05)" stroke="rgba(255,255,255,0.1)"/>
      <rect x="58" y="68" width="130" height="8" rx="4" fill="#6ee04a" opacity="0.5"/>
      <rect x="58" y="88" width="160" height="5" rx="2" fill="rgba(255,255,255,0.15)"/>
      <rect x="58" y="102" width="140" height="5" rx="2" fill="rgba(255,255,255,0.1)"/>
      <rect x="58" y="116" width="100" height="5" rx="2" fill="rgba(255,255,255,0.08)"/>
      <rect x="58" y="140" width="65" height="22" rx="6" fill="#6ee04a" opacity="0.9"/>
      <text x="90" y="155" textAnchor="middle" fontSize="9" fill="#1a1a2e" fontFamily="monospace" fontWeight="600">Report Bug</text>
      <text x="200" y="225" textAnchor="middle" fontSize="11" fill="rgba(255,255,255,0.3)" fontFamily="monospace">bug reporting in 60 seconds</text>
    </svg>
  );
  return null;
}

/* ===================== Projects ===================== */
const PROJECTS = [
  {
    title: "BugBuddy",
    tag: "AI Platform · Coming Soon",
    art: "bugbuddy",
    desc: "AI-powered bug reporting platform — Chrome extension + Go backend. Report bugs in 60 seconds.",
    problem: "Bug reporting is painful — it takes 10+ minutes to write a proper report with screenshots, console logs, and steps to reproduce. Non-technical users struggle even more, leading to vague bug reports that waste developer time.",
    solution: "BugBuddy pairs a Chrome extension with a Go backend so anyone can file detailed, structured bug reports in under 60 seconds. AI predicts root causes automatically.",
    bullets: [
      "Chrome extension captures screenshots, console logs, network requests, and screen recordings in one click",
      "Gemini Flash AI analyzes bug context and predicts top 3 root causes with confidence scoring",
      "4 export formats (GitHub Issue, JSON, PDF, Markdown) and 4 severity levels",
      "OAuth 2.0 + JWT auth, real-time WebSocket collaboration, GitHub API integration"
    ],
    stack: ["Go", "GoFr", "MySQL", "JavaScript", "Chrome Extension", "Gemini AI", "GitHub API", "WebSocket", "Docker"],
    github: "https://github.com/thzgajendra/BugBuddy",
    demo: "",
  },
  {
    title: "MindSwap",
    tag: "Developer Tool · Open Source",
    art: "mindswap",
    desc: "Context persistence for AI coding agents — save, search, and restore conversation context across sessions.",
    problem: "AI coding assistants lose all context when you start a new session. You end up re-explaining your project, preferences, and decisions every single time.",
    solution: "MindSwap lets you save and search context across AI sessions. Works as an npm package and MCP server so your AI assistant remembers what matters.",
    bullets: [
      "Save structured context with tags and metadata from any AI coding session",
      "Semantic search across saved contexts — find relevant past decisions instantly",
      "Works as both an npm package and an MCP server for broad compatibility",
      "Built for the ShipOrBleed workflow — fast context switching between projects"
    ],
    stack: ["JavaScript", "MCP Server", "CLI", "npm", "Open Source"],
    github: "https://github.com/ShipOrBleed/mindswap",
    demo: "https://mindswap.vercel.app",
  },
  {
    title: "reqflow",
    tag: "Go Package · Open Source",
    art: "reqflow",
    desc: "Trace any HTTP request through your Go codebase, statically. One command shows handler → service → store.",
    problem: "You join a new team, there's a bug in POST /orders. You grep for the route, cmd-click through handler → service → store, read struct tags for the DB table. You do this every time, for every repo.",
    solution: "reqflow does all of that in one command. No instrumentation, no runtime — just point it at your Go code and see the complete request path with exact method names and file locations.",
    bullets: [
      "Static analysis — parses Go code without running it, zero instrumentation needed",
      "Traces full request path: handler → service → store with exact file locations",
      "Supports substring search — find all routes matching a keyword",
      "Officially published Go package on pkg.go.dev"
    ],
    stack: ["Go", "CLI", "Open Source"],
    github: "https://github.com/ShipOrBleed/reqflow",
  },
];

function ProjectCard({ p, onOpen }) {
  return (
    <article className="proj-card reveal-stagger" onClick={onOpen} style={{ cursor: "pointer" }}>
      <div className="proj-preview">
        <div className="proj-preview-art"><ProjectArt kind={p.art} /></div>
        <div className="proj-tag">{p.tag}</div>
      </div>
      <div className="proj-body">
        <h3>{p.title}</h3>
        <p>{p.desc}</p>
        <div className="proj-chips">{p.stack.slice(0, 5).map((s) => <span key={s} className="proj-chip"><Logo name={s} /> {s}</span>)}</div>
        <div className="proj-actions" onClick={(e) => e.stopPropagation()}>
          <button className="proj-link primary" onClick={onOpen}>
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M7 17L17 7M7 7h10v10"/></svg>
            View details
          </button>
        </div>
      </div>
    </article>
  );
}

function Projects() {
  const revealRef = useReveal();
  const staggerRef = useStagger(PROJECTS.length);
  const [active, setActive] = useState(null);
  return (
    <section className="section reveal" id="projects" ref={revealRef}>
      <div className="app">
        <SecH num="03 — projects" title="things I've" em="built." lede="All built under ShipOrBleed — my solo GitHub org where I ship open-source developer tools." />
        <div className="proj-org">
          <a href="https://github.com/ShipOrBleed" target="_blank" rel="noopener" className="proj-org-link">
            <img src="https://avatars.githubusercontent.com/u/277386582?v=4" alt="ShipOrBleed" width="24" height="24" style={{ borderRadius: "50%" }} />
            <span>ShipOrBleed</span>
            <span className="proj-org-badge">Solo Org</span>
          </a>
        </div>
        <div className="proj-track" ref={staggerRef}>{PROJECTS.map((p, i) => <ProjectCard key={p.title} p={p} onOpen={() => setActive(i)} />)}</div>
      </div>
      <Modal open={active !== null} onClose={() => setActive(null)}>
        {active !== null && (() => {
          const p = PROJECTS[active];
          return (
            <>
              <div className="modal-hero"><ProjectArt kind={p.art} /></div>
              <div className="modal-body">
                <span className="modal-tag">{p.tag}</span>
                <h2>{p.title}</h2>
                {p.problem && (<><h3>The Problem</h3><p className="lede">{p.problem}</p></>)}
                {p.solution && (<><h3>The Solution</h3><p>{p.solution}</p></>)}
                <h3>How it works</h3>
                <ul>{p.bullets.map((b, i) => <li key={i}>{b}</li>)}</ul>
                <h3>Tech Stack</h3>
                <div className="modal-stack">{p.stack.map((s) => <span key={s} className="chip"><Logo name={s} /> {s}</span>)}</div>
                <div className="modal-actions">
                  {p.github && <a href={p.github} target="_blank" rel="noopener" className="btn btn-primary">View on GitHub <span className="arrow">&rarr;</span></a>}
                  {p.demo && <a href={p.demo} target="_blank" rel="noopener" className="btn btn-ghost">Live Demo <span className="arrow">&rarr;</span></a>}
                </div>
              </div>
            </>
          );
        })()}
      </Modal>
    </section>
  );
}

/* ===================== Education ===================== */
const EDU_DATA = [
  {
    title: "B.E Computer Science Engineering", sub: "Chandigarh University, Mohali, Punjab, India", meta: "Aug 2022 — June 2026",
    shortDesc: "CGPA 8.5 / 10",
    long: "Four years of Computer Science Engineering covering everything from low-level computer architecture to distributed systems. Built my foundation through rigorous coursework, competing in hackathons, and building real projects alongside academics. The combination of theory and hands-on practice shaped how I approach software engineering today.",
    bullets: ["CGPA 8.5 / 10", "National-level top performer — NPTEL Cloud, IoT & Edge ML (IIT Kanpur)", "Finalist in Code Relay at TECH INVENT 2024 — 2-day, 3-round coding competition at Chandigarh University", "Member of C Square Club — actively participated in hackathons and coding competitions"],
    highlights: ["Algorithms", "OS", "DBMS", "Networks", "Cloud Computing", "Distributed Systems"],
    stats: [{ v: "8.5", l: "CGPA" }],
  },
  {
    title: "High Schooling", sub: "Sooraj Sikshan Sansthan Sr. Sec. School, Pali, Rajasthan, India", meta: "May 2019 — May 2021",
    shortDesc: "12th: 98.80% | 10th: 92.17%",
    long: "Strong academic foundation with exceptional performance in board examinations. Studied Science and Mathematics stream. Beyond academics, I represented Rajasthan in the National Softball Championship and served as class representative — building leadership and teamwork skills early on.",
    bullets: ["12th Board: 98.80%", "10th Board: 92.17%", "Stream: Science & Mathematics", "Represented Rajasthan state in National Softball Championship", "Class Representative — led student coordination and activities"],
    highlights: ["Science", "Mathematics", "Physics", "Chemistry"],
    stats: [{ v: "98.80%", l: "12th score" }, { v: "92.17%", l: "10th score" }],
  },
];

function Education() {
  const revealRef = useReveal();
  const [active, setActive] = useState(null);
  return (
    <section className="section reveal" id="education" ref={revealRef}>
      <div className="app">
        <SecH num="04 — education" title="where I" em="studied." lede="The classrooms, competitions, and communities that shaped me." />
        <div>
          {EDU_DATA.map((edu, i) => (
            <div key={i} className="edu-card" onClick={() => setActive(i)} style={{ cursor: "pointer" }}>
              <div>
                <div className="edu-head">
                  <h3>{edu.title}</h3>
                  <span className="sub"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" style={{verticalAlign:"-1px",marginRight:"4px"}}><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>{edu.sub}</span>
                </div>
                <p style={{ fontSize: 13, color: "var(--ink-3)", margin: "12px 0 0" }}>Explore &rarr;</p>
              </div>
              <aside className="edu-side">
                {edu.stats.map((s, j) => (
                  <div key={j} className="stat-row"><span className="lbl">{s.l}</span><span className="val">{s.v}</span></div>
                ))}
                <div className="stat-row"><span className="lbl">Timeline</span><span className="val">{edu.meta}</span></div>
              </aside>
            </div>
          ))}
        </div>
      </div>
      <Modal open={active !== null} onClose={() => setActive(null)}>
        {active !== null && (() => {
          const edu = EDU_DATA[active];
          return (
            <>
              <div className="modal-hero">
                <svg viewBox="0 0 840 360" width="100%" height="100%" preserveAspectRatio="xMidYMid slice"><rect width="840" height="360" fill="var(--bg-2)"/>
                  <rect x="280" y="50" width="280" height="180" rx="14" fill="var(--surface)" stroke="var(--border-2)"/>
                  <rect x="310" y="80" width="220" height="10" rx="5" fill="var(--accent)" opacity="0.4"/>
                  <rect x="310" y="108" width="170" height="7" rx="3" fill="var(--ink-3)" opacity="0.2"/>
                  <rect x="310" y="128" width="190" height="7" rx="3" fill="var(--ink-3)" opacity="0.2"/>
                  <rect x="310" y="148" width="130" height="7" rx="3" fill="var(--ink-3)" opacity="0.2"/>
                  <rect x="310" y="180" width="80" height="28" rx="8" fill="var(--accent)" opacity="0.12" stroke="var(--accent)" strokeWidth="1"/>
                  <circle cx="160" cy="140" r="60" fill="var(--accent)" opacity="0.05"/>
                  <circle cx="720" cy="120" r="40" fill="var(--accent)" opacity="0.05"/>
                  {edu.highlights.map((h, hi) => <rect key={hi} x={200 + hi * 80} y={280} width="60" height="8" rx="4" fill="var(--accent)" opacity={0.15 + hi * 0.08} />)}
                </svg>
              </div>
              <div className="modal-body">
                <span className="modal-tag">Education</span>
                <h2>{edu.title}</h2>
                <p className="lede">{edu.long}</p>
                <h3>Details</h3>
                <ul>
                  <li><strong>Timeline:</strong> {edu.meta}</li>
                  <li><strong>Institution:</strong> {edu.sub}</li>
                </ul>
                <h3>Achievements & Highlights</h3>
                <ul>{edu.bullets.map((b, i) => <li key={i}>{b}</li>)}</ul>
                {edu.highlights.length > 0 && (<><h3>Key Subjects</h3><div className="modal-stack">{edu.highlights.map((h) => <span key={h} className="chip">{h}</span>)}</div></>)}
              </div>
            </>
          );
        })()}
      </Modal>
    </section>
  );
}

/* ===================== Stack ===================== */
function Stack() {
  const revealRef = useReveal();
  const staggerRef = useStagger(7);
  const groups = [
    { h: "Languages", items: ["Go", "C", "C++"] },
    { h: "Backend", items: ["REST APIs", "GoFr", "gRPC", "MCP Server", "Microservices"] },
    { h: "Databases", items: ["MySQL", "Redis"] },
    { h: "DevOps & Cloud", items: ["Docker", "Kubernetes", "AWS", "Azure", "CI/CD"] },
    { h: "Observability", items: ["Grafana", "OpenObserve", "Lens"] },
    { h: "Testing & Tools", items: ["gomock", "Grafana", "Git", "GitHub", "Postman", "Linux"] },
    { h: "AI & Extra", items: ["Claude Code", "Cursor", "Codex"] },
  ];
  return (
    <section className="section reveal" id="stack" ref={revealRef}>
      <div className="app">
        <SecH num="05 — stack" title="tools I" em="reach for." lede="What I use in production every day — comfortable enough to debug at 2am." />
        <div className="stack-grid" ref={staggerRef}>
          {groups.map((g) => (
            <div key={g.h} className="stack-card reveal-stagger">
              <h4>{g.h}</h4>
              <div className="stack-row">
                {g.items.map((i) => <span key={i} className="item"><Logo name={i} />{i}</span>)}
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ===================== Achievements ===================== */
const ACHIEVEMENTS = [
  { g: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>, h: "900+ DSA Problems Solved", short: "Across LeetCode, GeeksforGeeks, and HackerRank.",
    long: "Methodically worked through every major pattern — arrays, linked lists, trees, graphs, dynamic programming, greedy, segment trees, tries, union-find, concurrency. This daily practice sharpened my problem-solving under time pressure and helped me crack coding interviews with confidence.",
    details: ["Platforms: LeetCode, GeeksforGeeks, HackerRank", "Patterns: DP, Graphs, Trees, Greedy, Segment Trees, Tries", "Practice: Consistent daily problem solving over 2+ years"],
    links: [{ label: "LeetCode", url: "https://leetcode.com/u/thzgajendra/" }, { label: "Codolio", url: "https://codolio.com/profile/thzgajendra" }, { label: "GeeksforGeeks", url: "https://www.geeksforgeeks.org/profile/gajendra_malviya" }],
    art: "problems" },
  { g: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/></svg>, h: "GoFr Open-Source Contributor", short: "Core modules and CLI tooling for the GoFr framework.",
    long: "Active contributor to GoFr — an opinionated Go framework for accelerated microservice development used in production at ZopDev. My contributions include core framework modules and CLI tooling improvements. Working on open source taught me how senior engineers think about API design, backwards compatibility, and writing production-grade code.",
    details: ["Contributions: Core modules, CLI tooling", "Framework: GoFr (Go microservice framework)", "Impact: Used in production at ZopDev daily"],
    art: "github" },
  { g: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M12 2l3 7h7l-5.5 4 2 7L12 16l-6.5 4 2-7L2 9h7z"/></svg>, h: "LeetCode Contest #150 Global", short: "Globally ranked 150th / 30,000+ in Biweekly Contest 150.",
    long: "Achieved a global rank of 150th out of 30,000+ participants in LeetCode Biweekly Contest 150. This was the result of years of consistent practice — solving problems daily, competing in weekly contests, and building deep pattern recognition under time pressure.",
    details: ["Rank: #150 out of 30,000+ participants globally", "Contest: LeetCode Biweekly Contest 150", "Skills: Pattern recognition, speed coding, algorithm optimization"],
    art: "leetcode" },
  { g: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M22 10v6M2 10l10-5 10 5-10 5z"/><path d="M6 12v5c0 1.66 2.69 3 6 3s6-1.34 6-3v-5"/></svg>, h: "NPTEL National Top Performer", short: "Cloud, IoT & Edge ML course — IIT Kanpur.",
    long: "Achieved national-level top performer status in the NPTEL SWAYAM 'Cloud Computing, IoT & Edge ML' course conducted by IIT Kanpur. The course covered cloud-native architectures, IoT system design, and edge ML deployment — strengthening my understanding of distributed cloud systems.",
    details: ["Course: Cloud Computing, IoT & Edge ML", "Institution: IIT Kanpur via NPTEL SWAYAM", "Recognition: National-level top performer"],
    links: [{ label: "View Course on NPTEL", url: "https://nptel.ac.in/courses/106104242" }],
    art: "nptel" },
  { g: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M6 9H4.5a2.5 2.5 0 0 1 0-5C7 4 7 7 7 7"/><path d="M18 9h1.5a2.5 2.5 0 0 0 0-5C17 4 17 7 17 7"/><path d="M4 22h16"/><path d="M10 22V2h4v20"/><rect x="8" y="9" width="8" height="6" rx="1"/></svg>, h: "National Softball Championship", short: "Represented Rajasthan state at the national level.",
    long: "Represented the state of Rajasthan in the National Softball Championship. Competing at the national level taught me teamwork, discipline, and performing under pressure — skills that directly translate to on-call rotations and cross-team collaboration in engineering.",
    details: ["Represented: State of Rajasthan", "Level: National Championship", "Location: India", "Skills gained: Teamwork, discipline, performing under pressure"],
    art: "sports" },
];

function AchievementArt({ kind }) {
  if (kind === "problems") return (<svg viewBox="0 0 400 170" preserveAspectRatio="xMidYMid slice"><rect width="400" height="170" fill="var(--bg-2)"/>{Array.from({length:50}).map((_,i)=>{const r=Math.floor(i/10),c=i%10;return <rect key={i} x={45+c*32} y={20+r*28} width="24" height="24" rx="4" fill={Math.random()>0.12?"var(--accent)":"var(--surface-2)"} opacity={0.25+Math.random()*0.6} stroke="var(--border)"/>})}</svg>);
  if (kind === "github") return (<svg viewBox="0 0 400 170" preserveAspectRatio="xMidYMid slice"><rect width="400" height="170" fill="var(--bg-2)"/><circle cx="200" cy="80" r="40" fill="none" stroke="var(--accent)" strokeWidth="2"/><circle cx="200" cy="80" r="28" fill="var(--accent)" opacity="0.15"/><text x="200" y="75" textAnchor="middle" fontFamily="monospace" fontSize="20" fill="var(--accent)" fontWeight="700">GoFr</text><text x="200" y="92" textAnchor="middle" fontFamily="monospace" fontSize="10" fill="var(--ink-3)">contributor</text></svg>);
  if (kind === "leetcode") return (<img src="leetcode-contest.png" alt="LeetCode Contest Rating" style={{width:"100%",height:"100%",objectFit:"contain",objectPosition:"center",background:"#282828",padding:"12px"}} />);
  if (kind === "nptel") return (<img src="nptel-topper.png" alt="NPTEL Top Performer" style={{width:"100%",height:"100%",objectFit:"cover",background:"var(--bg-2)"}} />);
  if (kind === "sports") return (<svg viewBox="0 0 400 170" preserveAspectRatio="xMidYMid slice"><rect width="400" height="170" fill="var(--bg-2)"/><circle cx="200" cy="75" r="35" fill="var(--accent)" opacity="0.12" stroke="var(--accent)" strokeWidth="1"/><text x="200" y="82" textAnchor="middle" fontSize="30" fill="var(--accent)">&#9733;</text><text x="200" y="135" textAnchor="middle" fontFamily="monospace" fontSize="11" fill="var(--ink-3)">Rajasthan State Team</text></svg>);
  return null;
}

function Achievements() {
  const revealRef = useReveal();
  const staggerRef = useStagger(ACHIEVEMENTS.length);
  const [active, setActive] = useState(null);
  return (
    <section className="section reveal" id="achievements" ref={revealRef}>
      <div className="app">
        <SecH num="06 — wins" title="small" em="trophies." lede="Some moments I'm proud of along the way." />
        <div className="ach-list" ref={staggerRef}>
          {ACHIEVEMENTS.map((it, i) => (
            <div key={it.h} className="ach reveal-stagger" onClick={() => setActive(i)}>
              <div className="glyph">{it.g}</div>
              <div style={{ flex: 1 }}><h4>{it.h}</h4><p>{it.short}</p></div>
              <div className="more">view &rarr;</div>
            </div>
          ))}
        </div>
      </div>
      <Modal open={active !== null} onClose={() => setActive(null)}>
        {active !== null && (
          <>
            <div className="modal-hero"><AchievementArt kind={ACHIEVEMENTS[active].art} /></div>
            <div className="modal-body">
              <span className="modal-tag">Achievement</span>
              <h2>{ACHIEVEMENTS[active].h}</h2>
              <p className="lede">{ACHIEVEMENTS[active].long}</p>
              <h3>Details</h3>
              <ul>{ACHIEVEMENTS[active].details.map((d, i) => <li key={i}>{d}</li>)}</ul>
              {ACHIEVEMENTS[active].links && (<><h3>Links</h3><div className="modal-actions" style={{ borderTop: "none", paddingTop: 0 }}>{ACHIEVEMENTS[active].links.map((l) => (<a key={l.label} href={l.url} target="_blank" rel="noopener" className="btn btn-ghost">{l.label} <span className="arrow">&rarr;</span></a>))}</div></>)}
            </div>
          </>
        )}
      </Modal>
    </section>
  );
}

/* ===================== Certifications ===================== */
const CERTS = [
  { title: "Cloud Computing, IoT & Edge ML", issuer: "IIT Kanpur (NPTEL SWAYAM)", icon: "\u2601",
    long: "Comprehensive course covering cloud-native architectures, IoT system design, and edge ML deployment. Achieved national-level top performer status.",
    topics: ["Cloud Architecture", "IoT Systems", "Edge ML", "Distributed Computing", "Containers"] },
  { title: "Computer Organization & Architecture", issuer: "IIT Guwahati (NPTEL SWAYAM)", icon: "\u2699",
    long: "In-depth study of computer architecture fundamentals — instruction sets, pipelining, memory hierarchy, cache design, and parallel processing.",
    topics: ["Instruction Sets", "Pipelining", "Memory Hierarchy", "Cache Design", "Parallel Processing"] },
  { title: "Introduction to Databases", issuer: "Meta (Coursera)", icon: "\uD83D\uDDC4",
    long: "Foundation course on database design, SQL querying, normalization, indexing strategies, and transaction management.",
    topics: ["SQL", "Normalization", "Indexing", "Transactions", "Schema Design"] },
];

function Certifications() {
  const revealRef = useReveal();
  const staggerRef = useStagger(CERTS.length);
  const [active, setActive] = useState(null);
  return (
    <section className="section reveal" id="certifications" ref={revealRef}>
      <div className="app">
        <SecH num="07 — certifications" title="verified" em="learning." lede="Courses that leveled me up beyond the classroom." />
        <div className="cert-list" ref={staggerRef}>
          {CERTS.map((c, i) => (
            <div key={c.title} className="cert-card reveal-stagger" onClick={() => setActive(i)} style={{ cursor: "pointer" }}>
              <div className="cert-icon">{c.icon}</div>
              <h4>{c.title}</h4>
              <div className="cert-issuer">{c.issuer}</div>
              <div style={{ fontSize: 12, color: "var(--ink-3)", marginTop: 4 }}>Explore &rarr;</div>
            </div>
          ))}
        </div>
      </div>
      <Modal open={active !== null} onClose={() => setActive(null)}>
        {active !== null && (
          <>
            <div className="modal-hero">
              <svg viewBox="0 0 840 360" width="100%" height="100%" preserveAspectRatio="xMidYMid slice"><rect width="840" height="360" fill="var(--bg-2)"/>
                <rect x="250" y="40" width="340" height="220" rx="14" fill="var(--surface)" stroke="var(--border-2)"/>
                <rect x="285" y="75" width="270" height="12" rx="6" fill="var(--accent)" opacity="0.3"/>
                <rect x="285" y="108" width="220" height="8" rx="4" fill="var(--ink-3)" opacity="0.15"/>
                <rect x="285" y="130" width="200" height="8" rx="4" fill="var(--ink-3)" opacity="0.15"/>
                <rect x="285" y="170" width="110" height="32" rx="8" fill="var(--accent)" opacity="0.12" stroke="var(--accent)" strokeWidth="1"/>
                <circle cx="130" cy="160" r="50" fill="var(--accent)" opacity="0.04"/>
                <circle cx="720" cy="120" r="35" fill="var(--accent)" opacity="0.04"/>
                <text x="420" y="325" textAnchor="middle" fontSize="13" fill="var(--ink-3)" fontFamily="monospace">verified learning</text>
              </svg>
            </div>
            <div className="modal-body">
              <span className="modal-tag">Certification</span>
              <h2>{CERTS[active].title}</h2>
              <p className="lede">{CERTS[active].long}</p>
              <h3>Issued by</h3>
              <p>{CERTS[active].issuer}</p>
              <h3>Topics Covered</h3>
              <div className="modal-stack">{CERTS[active].topics.map((t) => <span key={t} className="chip">{t}</span>)}</div>
            </div>
          </>
        )}
      </Modal>
    </section>
  );
}

/* ===================== Hobbies ===================== */
const HOBBIES = [
  { icon: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M2 7h6l2 3h12v10H2z"/><path d="M14 13h4M14 17h4"/></svg>,
    title: "Building Things", em: "side projects", short: "Solo founder of ShipOrBleed — my GitHub org where I ship open-source developer tools.",
    long: "I run ShipOrBleed, a GitHub organization where I build and maintain open-source developer tools solo. MindSwap, reqflow, and more — all shipped from here. Most weekends I'm tinkering on a new idea, and ShipOrBleed is where it all lives. I love the part where an idea becomes something you can deploy, use, and share with the world.",
    stats: [{ v: "3+", l: "projects shipped" }, { v: "ShipOrBleed", l: "GitHub org" }],
    links: [{ label: "ShipOrBleed on GitHub", url: "https://github.com/ShipOrBleed" }] },
  { icon: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="3" y="3" width="18" height="18" rx="5"/><circle cx="12" cy="12" r="4"/><circle cx="17.5" cy="6.5" r="1.2" fill="currentColor"/></svg>,
    title: "Photography", em: "capturing moments", short: "Love capturing the world through a lens — streets, landscapes, and everyday life.",
    long: "Photography is my creative outlet. I enjoy street photography, landscapes, and finding beauty in everyday moments. It teaches me to observe details — a skill that helps in code reviews too. Check out my work on Instagram!",
    hasInstaGrid: true,
    links: [{ label: "Follow on Instagram", url: "https://www.instagram.com/thzseven" }] },
];

function Hobbies() {
  const revealRef = useReveal();
  const staggerRef = useStagger(HOBBIES.length);
  const [active, setActive] = useState(null);
  return (
    <section className="section reveal" id="hobbies" ref={revealRef}>
      <div className="app">
        <SecH num="07 — outside code" title="when I'm" em="not coding." lede="Because life isn't all semicolons and pull requests." />
        <div className="hobbies-grid" ref={staggerRef}>
          {HOBBIES.map((h, i) => (
            <div key={h.title} className="hobby reveal-stagger" onClick={() => setActive(i)} style={{ cursor: "pointer" }}>
              <div className="glyph">{h.icon}</div>
              <div>
                <h3>{h.title} <em>— {h.em}</em></h3>
                <p>{h.short}</p>
                <p style={{ fontSize: 12, color: "var(--ink-3)", margin: "8px 0 0" }}>Explore &rarr;</p>
              </div>
            </div>
          ))}
        </div>
      </div>
      <Modal open={active !== null} onClose={() => setActive(null)}>
        {active !== null && (
          <>
            <div className="modal-hero">
              {HOBBIES[active].title === "Building Things" ? (
                <div style={{width:"100%",height:"100%",background:"var(--bg-2)",display:"flex",alignItems:"center",justifyContent:"center"}}>
                  <img src="https://avatars.githubusercontent.com/u/277386582?v=4" alt="ShipOrBleed" style={{width:"120px",height:"120px",borderRadius:"50%",border:"3px solid var(--border-2)"}} />
                </div>
              ) : (
                <svg viewBox="0 0 840 360" width="100%" height="100%" preserveAspectRatio="xMidYMid slice"><rect width="840" height="360" fill="var(--bg-2)"/>
                  <circle cx="420" cy="150" r="60" fill="var(--accent)" opacity="0.06"/>
                  <circle cx="420" cy="150" r="35" fill="var(--accent)" opacity="0.1"/>
                  <text x="420" y="320" textAnchor="middle" fontSize="13" fill="var(--ink-3)" fontFamily="monospace">{HOBBIES[active].em}</text>
                </svg>
              )}
            </div>
            <div className="modal-body">
              <span className="modal-tag">Outside Code</span>
              <h2>{HOBBIES[active].title}</h2>
              <p className="lede">{HOBBIES[active].long}</p>
              {HOBBIES[active].stats && (<><h3>By the numbers</h3><div className="modal-stats">{HOBBIES[active].stats.map((s, i) => <div key={i} className="modal-stat"><div className="v">{s.v}</div><div className="l">{s.l}</div></div>)}</div></>)}
              {HOBBIES[active].links && (<><h3>Links</h3><div className="modal-actions" style={{ borderTop: "none", paddingTop: 0 }}>{HOBBIES[active].links.map((l) => (<a key={l.label} href={l.url} target="_blank" rel="noopener" className="btn btn-ghost">{l.label} <span className="arrow">&rarr;</span></a>))}</div></>)}
            </div>
          </>
        )}
      </Modal>
    </section>
  );
}

/* ===================== Contact ===================== */
function Contact() {
  const revealRef = useReveal();
  return (
    <section className="section reveal" id="contact" ref={revealRef}>
      <div className="app">
        <div className="contact">
          <h2>let's <em>talk.</em></h2>
          <p>Got an idea, a project, or just wanna vibe about tech? I'm always down for a good conversation. Drop a message — worst case, we both learn something new.</p>
          <a href="mailto:gajendramalviya1512@gmail.com" className="btn btn-primary">Get in Touch <span className="arrow">&rarr;</span></a>
          <div className="contact-grid">
            <a href="mailto:gajendramalviya1512@gmail.com">
              <svg className="ico ico-email" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="m3 7 9 6 9-6"/></svg>
              <div><div className="lbl">email</div><div className="val">gajendramalviya1512@gmail.com</div></div>
            </a>
            <a href="tel:+919521871512">
              <svg className="ico ico-phone" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
              <div><div className="lbl">phone</div><div className="val">+91 95218 71512</div></div>
            </a>
            <a href="https://www.linkedin.com/in/gajendra-malviya-99226a291/" target="_blank" rel="noopener">
              <svg className="ico ico-linkedin" viewBox="0 0 24 24" fill="currentColor"><path d="M19 0h-14c-2.8 0-5 2.2-5 5v14c0 2.8 2.2 5 5 5h14c2.8 0 5-2.2 5-5v-14c0-2.8-2.2-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.3c-1 0-1.7-.8-1.7-1.7s.7-1.7 1.7-1.7 1.7.8 1.7 1.7-.7 1.7-1.7 1.7zm13.5 12.3h-3v-5.6c0-1.4-.5-2.4-1.7-2.4-.9 0-1.5.6-1.7 1.2-.1.2-.1.5-.1.8v6h-3v-11h3v1.5c.4-.6 1.1-1.5 2.7-1.5 2 0 3.5 1.3 3.5 4.1v6.9z"/></svg>
              <div><div className="lbl">linkedin</div><div className="val">/in/gajendra-malviya</div></div>
            </a>
            <a href="https://github.com/thzgajendra" target="_blank" rel="noopener">
              <svg className="ico ico-github" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.4 0 0 5.4 0 12c0 5.3 3.4 9.8 8.2 11.4.6.1.8-.3.8-.6v-2.2c-3.3.7-4-1.6-4-1.6-.5-1.4-1.3-1.8-1.3-1.8-1.1-.7.1-.7.1-.7 1.2.1 1.8 1.2 1.8 1.2 1.1 1.8 2.8 1.3 3.5 1 .1-.8.4-1.3.8-1.6-2.7-.3-5.5-1.3-5.5-5.9 0-1.3.5-2.4 1.2-3.2-.1-.3-.5-1.5.1-3.2 0 0 1-.3 3.3 1.2 1-.3 2-.4 3-.4s2 .1 3 .4c2.3-1.5 3.3-1.2 3.3-1.2.7 1.6.2 2.9.1 3.2.8.8 1.2 1.9 1.2 3.2 0 4.6-2.8 5.6-5.5 5.9.4.4.8 1.1.8 2.2v3.3c0 .3.2.7.8.6C20.6 21.8 24 17.3 24 12c0-6.6-5.4-12-12-12z"/></svg>
              <div><div className="lbl">github</div><div className="val">@thzgajendra</div></div>
            </a>
          </div>
          <div className="profile-row">
            <a href="https://codolio.com/profile/thzgajendra" target="_blank" rel="noopener" className="profile">
              <div className="pf-icon">CD</div>
              <div className="pf-meta"><div className="pf-name">Codolio</div><div className="pf-handle">@thzgajendra</div></div>
            </a>
            <a href="https://leetcode.com/u/thzgajendra/" target="_blank" rel="noopener" className="profile">
              <div className="pf-icon"><svg viewBox="0 0 24 24" width="18" height="18" fill="#FFA116"><path d="M13.483 0a1.374 1.374 0 0 0-.961.438L7.116 6.226l-3.854 4.126a5.266 5.266 0 0 0-1.209 2.104 5.35 5.35 0 0 0-.125.513 5.527 5.527 0 0 0 .062 2.362 5.83 5.83 0 0 0 .349 1.017 5.938 5.938 0 0 0 1.271 1.818l4.277 4.193.039.038c2.248 2.165 5.852 2.133 8.063-.074l2.396-2.392c.54-.54.54-1.414.003-1.955a1.378 1.378 0 0 0-1.951-.003l-2.396 2.392a3.021 3.021 0 0 1-4.205.038l-.02-.019-4.276-4.193c-.652-.64-.972-1.469-.948-2.263a2.68 2.68 0 0 1 .066-.523 2.545 2.545 0 0 1 .619-1.164L9.13 8.114c1.058-1.134 3.204-1.27 4.43-.278l3.501 2.831c.593.48 1.461.387 1.94-.207a1.384 1.384 0 0 0-.207-1.943l-3.5-2.831c-.8-.647-1.766-1.045-2.774-1.202l2.015-2.158A1.384 1.384 0 0 0 13.483 0zm-2.866 12.815a1.38 1.38 0 0 0-1.38 1.382 1.38 1.38 0 0 0 1.38 1.382H20.79a1.38 1.38 0 0 0 1.38-1.382 1.38 1.38 0 0 0-1.38-1.382z"/></svg></div>
              <div className="pf-meta"><div className="pf-name">LeetCode</div><div className="pf-handle">@thzgajendra</div></div>
            </a>
          </div>
        </div>
        <footer className="footer">
          <div className="footer-slogan">"Ship fast, learn faster, break nothing."</div>
          <div className="footer-row">
            <span className="footer-item">
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
              Pali, Rajasthan
            </span>
            <span className="footer-dot">&middot;</span>
            <span className="footer-item">&copy; {new Date().getFullYear()} Gajendra Malviya</span>
            <span className="footer-dot">&middot;</span>
            <span className="footer-item">Built with Go, coffee &amp; Claude Code</span>
          </div>
        </footer>
      </div>
    </section>
  );
}

/* ===================== App ===================== */
const SECTION_IDS = ["about", "experience", "projects", "education", "stack", "achievements", "certifications", "hobbies", "contact"];

function App() {
  const [theme, setTheme] = useState(() => {
    const saved = localStorage.getItem("gm-theme");
    if (saved) return saved;
    return window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";
  });
  const activeSection = useActiveSection(SECTION_IDS);

  useEffect(() => {
    document.documentElement.setAttribute("data-theme", theme);
    localStorage.setItem("gm-theme", theme);
  }, [theme]);

  useEffect(() => {
    const el = document.getElementById("preloader");
    if (el) {
      el.style.opacity = "0";
      setTimeout(() => el.remove(), 500);
    }
  }, []);

  return (
    <>
      <ScrollProgress />
      <Nav theme={theme} toggleTheme={() => setTheme(theme === "dark" ? "light" : "dark")} activeSection={activeSection} />
      <Hero />
      <About />
      <Experience />
      <Projects />
      <Education />
      <Stack />
      <Achievements />
      <Hobbies />
      <Contact />
      <BackToTop />
    </>
  );
}
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
